mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-19 11:12:43 +00:00
Rollup merge of #112122 - compiler-errors:next-coherence, r=lcnr
Add `-Ztrait-solver=next-coherence` Flag that conditionally uses the trait solver *only* during coherence, for more testing and/or eventual partial-migration onto the trait solver (in the medium- to long-term). * This still uses the selection context in some of the coherence methods I think, so it's not "complete". Putting this up for review and/or for further work in-tree. * I probably need to spend a bit more time making sure that we don't sneakily create any other infcx's during coherence that also need the new solver enabled. r? `@lcnr`
This commit is contained in:
commit
0b002eb906
@ -285,7 +285,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
let infcx = self
|
||||
.tcx
|
||||
.infer_ctxt()
|
||||
.with_opaque_type_inference(if self.tcx.trait_solver_next() {
|
||||
.with_opaque_type_inference(if self.next_trait_solver() {
|
||||
DefiningAnchor::Bind(def_id)
|
||||
} else {
|
||||
DefiningAnchor::Bubble
|
||||
|
@ -188,7 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
|
||||
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
|
||||
// predefined opaques in the typeck root.
|
||||
if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
|
||||
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
|
||||
checker.register_predefined_opaques_in_new_solver();
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
|
||||
// NOTE: we may still need to normalize the built-in deref in case
|
||||
// we have some type like `&<Ty as Trait>::Assoc`, since users of
|
||||
// autoderef expect this type to have been structurally normalized.
|
||||
if self.infcx.tcx.trait_solver_next()
|
||||
if self.infcx.next_trait_solver()
|
||||
&& let ty::Alias(ty::Projection, _) = ty.kind()
|
||||
{
|
||||
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
|
||||
@ -161,8 +161,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
|
||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.infcx);
|
||||
|
||||
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||
let normalized_ty = match self
|
||||
|
@ -1549,7 +1549,7 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
.with_opaque_type_inference(DefiningAnchor::Bind(def_id))
|
||||
.build();
|
||||
|
||||
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
|
||||
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
|
||||
for (predicate, cause) in generator_interior_predicates {
|
||||
let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
|
||||
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
|
||||
|
@ -156,7 +156,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
// In the new solver, lazy norm may allow us to shallowly equate
|
||||
// more types, but we emit possibly impossible-to-satisfy obligations.
|
||||
// Filter these cases out to make sure our coercion is more accurate.
|
||||
if self.tcx.trait_solver_next() {
|
||||
if self.next_trait_solver() {
|
||||
if let Ok(res) = &res {
|
||||
for obligation in &res.obligations {
|
||||
if !self.predicate_may_hold(&obligation) {
|
||||
|
@ -1476,7 +1476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let mut ty = self.resolve_vars_with_obligations(ty);
|
||||
|
||||
if self.tcx.trait_solver_next()
|
||||
if self.next_trait_solver()
|
||||
&& let ty::Alias(ty::Projection, _) = ty.kind()
|
||||
{
|
||||
match self
|
||||
|
@ -86,8 +86,8 @@ impl<'tcx> Inherited<'tcx> {
|
||||
|
||||
Inherited {
|
||||
typeck_results,
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(&infcx)),
|
||||
infcx,
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
|
||||
locals: RefCell::new(Default::default()),
|
||||
deferred_sized_obligations: RefCell::new(Vec::new()),
|
||||
deferred_call_resolutions: RefCell::new(Default::default()),
|
||||
|
@ -591,7 +591,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
.insert(opaque_type_key, hidden_type)
|
||||
&& last_opaque_ty.ty != hidden_type.ty
|
||||
{
|
||||
assert!(!self.tcx().trait_solver_next());
|
||||
assert!(!self.fcx.next_trait_solver());
|
||||
hidden_type
|
||||
.report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
|
||||
.stash(
|
||||
@ -812,7 +812,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match self.fcx.fully_resolve(t) {
|
||||
Ok(t) if self.fcx.tcx.trait_solver_next() => {
|
||||
Ok(t) if self.fcx.next_trait_solver() => {
|
||||
// We must normalize erasing regions here, since later lints
|
||||
// expect that types that show up in the typeck are fully
|
||||
// normalized.
|
||||
|
@ -82,6 +82,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
in_snapshot: self.in_snapshot.clone(),
|
||||
universe: self.universe.clone(),
|
||||
intercrate: self.intercrate,
|
||||
next_trait_solver: self.next_trait_solver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,11 +109,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
| (
|
||||
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
|
||||
ty::Alias(AliasKind::Projection, _),
|
||||
) if self.tcx.trait_solver_next() => {
|
||||
) if self.next_trait_solver() => {
|
||||
bug!()
|
||||
}
|
||||
|
||||
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => {
|
||||
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
|
||||
relation.register_type_relate_obligation(a, b);
|
||||
Ok(a)
|
||||
}
|
||||
@ -227,9 +227,20 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
return self.unify_const_variable(vid, a, relation.param_env());
|
||||
}
|
||||
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
|
||||
if self.tcx.features().generic_const_exprs || self.tcx.trait_solver_next() =>
|
||||
if self.tcx.features().generic_const_exprs || self.next_trait_solver() =>
|
||||
{
|
||||
relation.register_const_equate_obligation(a, b);
|
||||
let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) };
|
||||
|
||||
relation.register_predicates([ty::Binder::dummy(if self.next_trait_solver() {
|
||||
ty::PredicateKind::AliasRelate(
|
||||
a.into(),
|
||||
b.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
)
|
||||
} else {
|
||||
ty::PredicateKind::ConstEquate(a, b)
|
||||
})]);
|
||||
|
||||
return Ok(b);
|
||||
}
|
||||
_ => {}
|
||||
@ -453,19 +464,6 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
|
||||
/// be used if control over the obligation causes is required.
|
||||
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>);
|
||||
|
||||
/// Register an obligation that both constants must be equal to each other.
|
||||
///
|
||||
/// If they aren't equal then the relation doesn't hold.
|
||||
fn register_const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
|
||||
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
|
||||
|
||||
self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() {
|
||||
ty::PredicateKind::AliasRelate(a.into(), b.into(), ty::AliasRelationDirection::Equate)
|
||||
} else {
|
||||
ty::PredicateKind::ConstEquate(a, b)
|
||||
})]);
|
||||
}
|
||||
|
||||
/// Register an obligation that both types must be related to each other according to
|
||||
/// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`]
|
||||
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
|
||||
|
@ -105,7 +105,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local()
|
||||
&& !self.tcx().trait_solver_next() =>
|
||||
&& !self.fields.infcx.next_trait_solver() =>
|
||||
{
|
||||
self.fields.obligations.extend(
|
||||
infcx
|
||||
|
@ -113,7 +113,7 @@ where
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if this.define_opaque_types() == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local()
|
||||
&& !this.tcx().trait_solver_next() =>
|
||||
&& !this.infcx().next_trait_solver() =>
|
||||
{
|
||||
this.register_obligations(
|
||||
infcx
|
||||
|
@ -330,6 +330,8 @@ pub struct InferCtxt<'tcx> {
|
||||
/// there is no type that the user could *actually name* that
|
||||
/// would satisfy it. This avoids crippling inference, basically.
|
||||
pub intercrate: bool,
|
||||
|
||||
next_trait_solver: bool,
|
||||
}
|
||||
|
||||
/// See the `error_reporting` module for more details.
|
||||
@ -545,6 +547,9 @@ pub struct InferCtxtBuilder<'tcx> {
|
||||
skip_leak_check: bool,
|
||||
/// Whether we are in coherence mode.
|
||||
intercrate: bool,
|
||||
/// Whether we should use the new trait solver in the local inference context,
|
||||
/// which affects things like which solver is used in `predicate_may_hold`.
|
||||
next_trait_solver: bool,
|
||||
}
|
||||
|
||||
pub trait TyCtxtInferExt<'tcx> {
|
||||
@ -559,6 +564,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
||||
considering_regions: true,
|
||||
skip_leak_check: false,
|
||||
intercrate: false,
|
||||
next_trait_solver: self.next_trait_solver_globally(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -575,6 +581,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
|
||||
self.next_trait_solver = next_trait_solver;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn intercrate(mut self, intercrate: bool) -> Self {
|
||||
self.intercrate = intercrate;
|
||||
self
|
||||
@ -617,6 +628,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
considering_regions,
|
||||
skip_leak_check,
|
||||
intercrate,
|
||||
next_trait_solver,
|
||||
} = *self;
|
||||
InferCtxt {
|
||||
tcx,
|
||||
@ -634,6 +646,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
in_snapshot: Cell::new(false),
|
||||
universe: Cell::new(ty::UniverseIndex::ROOT),
|
||||
intercrate,
|
||||
next_trait_solver,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -670,6 +683,10 @@ pub struct CombinedSnapshot<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn next_trait_solver(&self) -> bool {
|
||||
self.next_trait_solver
|
||||
}
|
||||
|
||||
/// Creates a `TypeErrCtxt` for emitting various inference errors.
|
||||
/// During typeck, use `FnCtxt::err_ctxt` instead.
|
||||
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
|
||||
|
@ -491,12 +491,12 @@ where
|
||||
(
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
|
||||
) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => {
|
||||
) if a_def_id == b_def_id || infcx.next_trait_solver() => {
|
||||
infcx.super_combine_tys(self, a, b).or_else(|err| {
|
||||
// This behavior is only there for the old solver, the new solver
|
||||
// shouldn't ever fail. Instead, it unconditionally emits an
|
||||
// alias-relate goal.
|
||||
assert!(!self.tcx().trait_solver_next());
|
||||
assert!(!self.infcx.next_trait_solver());
|
||||
self.tcx().sess.delay_span_bug(
|
||||
self.delegate.span(),
|
||||
"failure to relate an opaque to itself should result in an error later on",
|
||||
@ -506,7 +506,7 @@ where
|
||||
}
|
||||
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if def_id.is_local() && !self.tcx().trait_solver_next() =>
|
||||
if def_id.is_local() && !self.infcx.next_trait_solver() =>
|
||||
{
|
||||
self.relate_opaques(a, b)
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> InferOk<'tcx, T> {
|
||||
// We handle opaque types differently in the new solver.
|
||||
if self.tcx.trait_solver_next() {
|
||||
if self.next_trait_solver() {
|
||||
return InferOk { value, obligations: vec![] };
|
||||
}
|
||||
|
||||
@ -578,7 +578,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
) -> InferResult<'tcx, ()> {
|
||||
assert!(self.tcx.trait_solver_next());
|
||||
assert!(self.next_trait_solver());
|
||||
let origin = self
|
||||
.opaque_type_origin(opaque_type_key.def_id)
|
||||
.expect("should be called for defining usages only");
|
||||
@ -614,7 +614,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
ty::Alias(ty::Projection, projection_ty)
|
||||
if !projection_ty.has_escaping_bound_vars()
|
||||
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
|
||||
&& !tcx.trait_solver_next() =>
|
||||
&& !self.next_trait_solver() =>
|
||||
{
|
||||
self.infer_projection(
|
||||
param_env,
|
||||
|
@ -21,7 +21,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
recursion_depth: usize,
|
||||
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
||||
) -> Ty<'tcx> {
|
||||
if self.tcx.trait_solver_next() {
|
||||
if self.next_trait_solver() {
|
||||
// FIXME(-Ztrait-solver=next): Instead of branching here,
|
||||
// completely change the normalization routine with the new solver.
|
||||
//
|
||||
|
@ -132,7 +132,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local()
|
||||
&& !self.tcx().trait_solver_next() =>
|
||||
&& !self.fields.infcx.next_trait_solver() =>
|
||||
{
|
||||
self.fields.obligations.extend(
|
||||
infcx
|
||||
|
@ -2333,10 +2333,18 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
|
||||
}
|
||||
|
||||
pub fn trait_solver_next(self) -> bool {
|
||||
pub fn next_trait_solver_globally(self) -> bool {
|
||||
self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
|
||||
}
|
||||
|
||||
pub fn next_trait_solver_in_coherence(self) -> bool {
|
||||
matches!(
|
||||
self.sess.opts.unstable_opts.trait_solver,
|
||||
rustc_session::config::TraitSolver::Next
|
||||
| rustc_session::config::TraitSolver::NextCoherence
|
||||
)
|
||||
}
|
||||
|
||||
pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
|
||||
self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
|
||||
}
|
||||
|
@ -610,6 +610,8 @@ pub enum TraitSolver {
|
||||
Chalk,
|
||||
/// Experimental trait solver in `rustc_trait_selection::solve`
|
||||
Next,
|
||||
/// Use the new trait solver during coherence
|
||||
NextCoherence,
|
||||
}
|
||||
|
||||
pub enum Input {
|
||||
|
@ -986,6 +986,7 @@ mod parse {
|
||||
Some("classic") => *slot = TraitSolver::Classic,
|
||||
Some("chalk") => *slot = TraitSolver::Chalk,
|
||||
Some("next") => *slot = TraitSolver::Next,
|
||||
Some("next-coherence") => *slot = TraitSolver::NextCoherence,
|
||||
// default trait solver is subject to change..
|
||||
Some("default") => *slot = TraitSolver::Classic,
|
||||
_ => return false,
|
||||
|
@ -187,6 +187,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
let (ref infcx, input, var_values) = tcx
|
||||
.infer_ctxt()
|
||||
.intercrate(intercrate)
|
||||
.with_next_trait_solver(true)
|
||||
.with_opaque_type_inference(canonical_input.value.anchor)
|
||||
.build_with_canonical(DUMMY_SP, &canonical_input);
|
||||
|
||||
|
@ -182,6 +182,7 @@ fn overlap<'tcx>(
|
||||
.with_opaque_type_inference(DefiningAnchor::Bubble)
|
||||
.skip_leak_check(skip_leak_check.is_yes())
|
||||
.intercrate(true)
|
||||
.with_next_trait_solver(tcx.next_trait_solver_in_coherence())
|
||||
.build();
|
||||
let selcx = &mut SelectionContext::new(&infcx);
|
||||
if track_ambiguity_causes.is_yes() {
|
||||
|
@ -27,24 +27,42 @@ use rustc_session::config::TraitSolver;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub trait TraitEngineExt<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> Box<Self>;
|
||||
fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box<Self>;
|
||||
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>;
|
||||
fn new_in_snapshot(infcx: &InferCtxt<'tcx>) -> Box<Self>;
|
||||
}
|
||||
|
||||
impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> Box<Self> {
|
||||
match tcx.sess.opts.unstable_opts.trait_solver {
|
||||
TraitSolver::Classic => Box::new(FulfillmentContext::new()),
|
||||
TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new()),
|
||||
TraitSolver::Next => Box::new(NextFulfillmentCtxt::new()),
|
||||
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
|
||||
match (infcx.tcx.sess.opts.unstable_opts.trait_solver, infcx.next_trait_solver()) {
|
||||
(TraitSolver::Classic, false) | (TraitSolver::NextCoherence, false) => {
|
||||
Box::new(FulfillmentContext::new())
|
||||
}
|
||||
(TraitSolver::Next | TraitSolver::NextCoherence, true) => {
|
||||
Box::new(NextFulfillmentCtxt::new())
|
||||
}
|
||||
(TraitSolver::Chalk, false) => Box::new(ChalkFulfillmentContext::new()),
|
||||
_ => bug!(
|
||||
"incompatible combination of -Ztrait-solver flag ({:?}) and InferCtxt::next_trait_solver ({:?})",
|
||||
infcx.tcx.sess.opts.unstable_opts.trait_solver,
|
||||
infcx.next_trait_solver()
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box<Self> {
|
||||
match tcx.sess.opts.unstable_opts.trait_solver {
|
||||
TraitSolver::Classic => Box::new(FulfillmentContext::new_in_snapshot()),
|
||||
TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new_in_snapshot()),
|
||||
TraitSolver::Next => Box::new(NextFulfillmentCtxt::new()),
|
||||
fn new_in_snapshot(infcx: &InferCtxt<'tcx>) -> Box<Self> {
|
||||
match (infcx.tcx.sess.opts.unstable_opts.trait_solver, infcx.next_trait_solver()) {
|
||||
(TraitSolver::Classic, false) | (TraitSolver::NextCoherence, false) => {
|
||||
Box::new(FulfillmentContext::new_in_snapshot())
|
||||
}
|
||||
(TraitSolver::Next | TraitSolver::NextCoherence, true) => {
|
||||
Box::new(NextFulfillmentCtxt::new())
|
||||
}
|
||||
(TraitSolver::Chalk, false) => Box::new(ChalkFulfillmentContext::new_in_snapshot()),
|
||||
_ => bug!(
|
||||
"incompatible combination of -Ztrait-solver flag ({:?}) and InferCtxt::next_trait_solver ({:?})",
|
||||
infcx.tcx.sess.opts.unstable_opts.trait_solver,
|
||||
infcx.next_trait_solver()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,11 +76,11 @@ pub struct ObligationCtxt<'a, 'tcx> {
|
||||
|
||||
impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
|
||||
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new(infcx.tcx)) }
|
||||
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new(infcx)) }
|
||||
}
|
||||
|
||||
pub fn new_in_snapshot(infcx: &'a InferCtxt<'tcx>) -> Self {
|
||||
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new_in_snapshot(infcx.tcx)) }
|
||||
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new_in_snapshot(infcx)) }
|
||||
}
|
||||
|
||||
pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
|
||||
|
@ -1047,7 +1047,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
// (which may fail).
|
||||
span_bug!(span, "WF predicate not satisfied for {:?}", ty);
|
||||
}
|
||||
TraitSolver::Chalk | TraitSolver::Next => {
|
||||
TraitSolver::Chalk | TraitSolver::Next | TraitSolver::NextCoherence => {
|
||||
// FIXME: we'll need a better message which takes into account
|
||||
// which bounds actually failed to hold.
|
||||
self.tcx.sess.struct_span_err(
|
||||
|
@ -78,7 +78,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
_ => obligation.param_env.without_const(),
|
||||
};
|
||||
|
||||
if self.tcx.trait_solver_next() {
|
||||
if self.next_trait_solver() {
|
||||
self.probe(|snapshot| {
|
||||
let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
|
||||
fulfill_cx.register_predicate_obligation(self, obligation.clone());
|
||||
|
@ -146,7 +146,7 @@ where
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
span: Span,
|
||||
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
|
||||
if infcx.tcx.trait_solver_next() {
|
||||
if infcx.next_trait_solver() {
|
||||
return Ok(scrape_region_constraints(
|
||||
infcx,
|
||||
|ocx| QueryTypeOp::perform_locally_in_new_solver(ocx, self),
|
||||
|
@ -539,7 +539,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
self.evaluation_probe(|this| {
|
||||
let goal =
|
||||
this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
|
||||
let mut result = if this.tcx().trait_solver_next() {
|
||||
let mut result = if this.infcx.next_trait_solver() {
|
||||
this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
|
||||
} else {
|
||||
this.evaluate_predicate_recursively(
|
||||
@ -593,7 +593,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
where
|
||||
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
|
||||
{
|
||||
if self.tcx().trait_solver_next() {
|
||||
if self.infcx.next_trait_solver() {
|
||||
self.evaluate_predicates_recursively_in_new_solver(predicates)
|
||||
} else {
|
||||
let mut result = EvaluatedToOk;
|
||||
|
@ -21,7 +21,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
|
||||
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
||||
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
|
||||
|
||||
if self.infcx.tcx.trait_solver_next() {
|
||||
if self.infcx.next_trait_solver() {
|
||||
while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
|
||||
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
||||
|
@ -55,7 +55,7 @@ pub fn codegen_select_candidate<'tcx>(
|
||||
// Currently, we use a fulfillment context to completely resolve
|
||||
// all nested obligations. This is because they can inform the
|
||||
// inference of the impl's type parameters.
|
||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
|
||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(&infcx);
|
||||
let impl_source = selection.map(|predicate| {
|
||||
fulfill_cx.register_predicate_obligation(&infcx, predicate);
|
||||
});
|
||||
|
@ -16,7 +16,7 @@ fn evaluate_obligation<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
canonical_goal: CanonicalPredicateGoal<'tcx>,
|
||||
) -> Result<EvaluationResult, OverflowError> {
|
||||
assert!(!tcx.trait_solver_next());
|
||||
assert!(!tcx.next_trait_solver_globally());
|
||||
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
|
||||
// HACK This bubble is required for this tests to pass:
|
||||
// impl-trait/issue99642.rs
|
||||
|
@ -108,6 +108,7 @@ string_enum! {
|
||||
Polonius => "polonius",
|
||||
Chalk => "chalk",
|
||||
NextSolver => "next-solver",
|
||||
NextSolverCoherence => "next-solver-coherence",
|
||||
SplitDwarf => "split-dwarf",
|
||||
SplitDwarfSingle => "split-dwarf-single",
|
||||
}
|
||||
|
@ -2127,6 +2127,9 @@ impl<'test> TestCx<'test> {
|
||||
Some(CompareMode::NextSolver) => {
|
||||
rustc.args(&["-Ztrait-solver=next"]);
|
||||
}
|
||||
Some(CompareMode::NextSolverCoherence) => {
|
||||
rustc.args(&["-Ztrait-solver=next-coherence"]);
|
||||
}
|
||||
Some(CompareMode::SplitDwarf) if self.config.target.contains("windows") => {
|
||||
rustc.args(&["-Csplit-debuginfo=unpacked", "-Zunstable-options"]);
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
error[E0119]: conflicting implementations of trait `Overlap` for type `u32`
|
||||
--> $DIR/specialization-default-items-drop-coherence.rs:29:1
|
||||
|
|
||||
LL | impl Overlap for u32 {
|
||||
| -------------------- first implementation here
|
||||
...
|
||||
LL | impl Overlap for <u32 as Default>::Id {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
@ -0,0 +1,12 @@
|
||||
error[E0119]: conflicting implementations of trait `Overlap` for type `u32`
|
||||
--> $DIR/specialization-default-items-drop-coherence.rs:29:1
|
||||
|
|
||||
LL | impl Overlap for u32 {
|
||||
| -------------------- first implementation here
|
||||
...
|
||||
LL | impl Overlap for <u32 as Default>::Id {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
@ -1,5 +1,8 @@
|
||||
// check-pass
|
||||
// known-bug: #105782
|
||||
// revisions: classic coherence next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
//[coherence] compile-flags: -Ztrait-solver=next-coherence
|
||||
//[classic] check-pass
|
||||
//[classic] known-bug: #105782
|
||||
|
||||
// Should fail. Default items completely drop candidates instead of ambiguity,
|
||||
// which is unsound during coherence, since coherence requires completeness.
|
||||
@ -24,6 +27,8 @@ impl Overlap for u32 {
|
||||
}
|
||||
|
||||
impl Overlap for <u32 as Default>::Id {
|
||||
//[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32`
|
||||
//[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32`
|
||||
type Assoc = Box<usize>;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user