diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/coherence.rs')
-rw-r--r-- | compiler/rustc_trait_selection/src/traits/coherence.rs | 68 |
1 files changed, 33 insertions, 35 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 8aab75490..899e30275 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -11,14 +11,14 @@ use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::util::impl_subject_and_oblig; use crate::traits::SkipLeakCheck; use crate::traits::{ - self, Normalized, Obligation, ObligationCause, ObligationCtxt, PredicateObligation, - PredicateObligations, SelectionContext, + self, Obligation, ObligationCause, ObligationCtxt, PredicateObligation, PredicateObligations, + SelectionContext, }; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::CRATE_HIR_ID; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; @@ -30,6 +30,8 @@ use std::fmt::Debug; use std::iter; use std::ops::ControlFlow; +use super::NormalizeExt; + /// Whether we do the orphan check relative to this crate or /// to some remote crate. #[derive(Copy, Clone, Debug)] @@ -64,13 +66,13 @@ pub fn add_placeholder_note(err: &mut Diagnostic) { /// with a suitably-freshened `ImplHeader` with those types /// substituted. Otherwise, returns `None`. #[instrument(skip(tcx, skip_leak_check), level = "debug")] -pub fn overlapping_impls( - tcx: TyCtxt<'_>, +pub fn overlapping_impls<'tcx>( + tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId, skip_leak_check: SkipLeakCheck, overlap_mode: OverlapMode, -) -> Option<OverlapResult<'_>> { +) -> Option<OverlapResult<'tcx>> { // Before doing expensive operations like entering an inference context, do // a quick check via fast_reject to tell if the impl headers could possibly // unify. @@ -94,8 +96,9 @@ pub fn overlapping_impls( return None; } - let infcx = tcx.infer_ctxt().build(); - let selcx = &mut SelectionContext::intercrate(&infcx); + let infcx = + tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build(); + let selcx = &mut SelectionContext::new(&infcx); let overlaps = overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some(); if !overlaps { @@ -105,8 +108,9 @@ pub fn overlapping_impls( // In the case where we detect an error, run the check again, but // this time tracking intercrate ambiguity causes for better // diagnostics. (These take time and can lead to false errors.) - let infcx = tcx.infer_ctxt().build(); - let selcx = &mut SelectionContext::intercrate(&infcx); + let infcx = + tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build(); + let selcx = &mut SelectionContext::new(&infcx); selcx.enable_tracking_intercrate_ambiguity_causes(); Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap()) } @@ -117,7 +121,7 @@ fn with_fresh_ty_vars<'cx, 'tcx>( impl_def_id: DefId, ) -> ty::ImplHeader<'tcx> { let tcx = selcx.tcx(); - let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id); + let impl_substs = selcx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); let header = ty::ImplHeader { impl_def_id, @@ -126,8 +130,8 @@ fn with_fresh_ty_vars<'cx, 'tcx>( predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates, }; - let Normalized { value: mut header, obligations } = - traits::normalize(selcx, param_env, ObligationCause::dummy(), header); + let InferOk { value: mut header, obligations } = + selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(header); header.predicates.extend(obligations.into_iter().map(|o| o.predicate)); header @@ -147,7 +151,7 @@ fn overlap<'cx, 'tcx>( impl1_def_id, impl2_def_id, overlap_mode ); - selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { + selcx.infcx.probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { overlap_within_probe(selcx, impl1_def_id, impl2_def_id, overlap_mode, snapshot) }) } @@ -159,11 +163,11 @@ fn overlap_within_probe<'cx, 'tcx>( overlap_mode: OverlapMode, snapshot: &CombinedSnapshot<'tcx>, ) -> Option<OverlapResult<'tcx>> { - let infcx = selcx.infcx(); + let infcx = selcx.infcx; if overlap_mode.use_negative_impl() { - if negative_impl(selcx, impl1_def_id, impl2_def_id) - || negative_impl(selcx, impl2_def_id, impl1_def_id) + if negative_impl(infcx.tcx, impl1_def_id, impl2_def_id) + || negative_impl(infcx.tcx, impl2_def_id, impl1_def_id) { return None; } @@ -198,9 +202,9 @@ fn overlap_within_probe<'cx, 'tcx>( debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); let involves_placeholder = - matches!(selcx.infcx().region_constraints_added_in_snapshot(snapshot), Some(true)); + matches!(selcx.infcx.region_constraints_added_in_snapshot(snapshot), Some(true)); - let impl_header = selcx.infcx().resolve_vars_if_possible(impl1_header); + let impl_header = selcx.infcx.resolve_vars_if_possible(impl1_header); Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder }) } @@ -212,7 +216,7 @@ fn equate_impl_headers<'cx, 'tcx>( // Do `a` and `b` unify? If not, no overlap. debug!("equate_impl_headers(impl1_header={:?}, impl2_header={:?}", impl1_header, impl2_header); selcx - .infcx() + .infcx .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) .eq_impl_headers(impl1_header, impl2_header) .map(|infer_ok| infer_ok.obligations) @@ -253,7 +257,7 @@ fn implicit_negative<'cx, 'tcx>( "implicit_negative(impl1_header={:?}, impl2_header={:?}, obligations={:?})", impl1_header, impl2_header, obligations ); - let infcx = selcx.infcx(); + let infcx = selcx.infcx; let opt_failing_obligation = impl1_header .predicates .iter() @@ -279,13 +283,8 @@ fn implicit_negative<'cx, 'tcx>( /// Given impl1 and impl2 check if both impls are never satisfied by a common type (including /// where-clauses) If so, return true, they are disjoint and false otherwise. -fn negative_impl<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - impl1_def_id: DefId, - impl2_def_id: DefId, -) -> bool { +fn negative_impl<'tcx>(tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> bool { debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id); - let tcx = selcx.infcx().tcx; // Create an infcx, taking the predicates of impl1 as assumptions: let infcx = tcx.infer_ctxt().build(); @@ -332,11 +331,10 @@ fn equate<'tcx>( return true; }; - let selcx = &mut SelectionContext::new(&infcx); let opt_failing_obligation = obligations .into_iter() .chain(more_obligations) - .find(|o| negative_impl_exists(selcx, o, body_def_id)); + .find(|o| negative_impl_exists(infcx, o, body_def_id)); if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); @@ -347,19 +345,19 @@ fn equate<'tcx>( } /// Try to prove that a negative impl exist for the given obligation and its super predicates. -#[instrument(level = "debug", skip(selcx))] -fn negative_impl_exists<'cx, 'tcx>( - selcx: &SelectionContext<'cx, 'tcx>, +#[instrument(level = "debug", skip(infcx))] +fn negative_impl_exists<'tcx>( + infcx: &InferCtxt<'tcx>, o: &PredicateObligation<'tcx>, body_def_id: DefId, ) -> bool { - if resolve_negative_obligation(selcx.infcx().fork(), o, body_def_id) { + if resolve_negative_obligation(infcx.fork(), o, body_def_id) { return true; } // Try to prove a negative obligation exists for super predicates - for o in util::elaborate_predicates(selcx.tcx(), iter::once(o.predicate)) { - if resolve_negative_obligation(selcx.infcx().fork(), &o, body_def_id) { + for o in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) { + if resolve_negative_obligation(infcx.fork(), &o, body_def_id) { return true; } } |