From 2fa7479d80f77e639bb85bb44f14a4187b702074 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 14 Mar 2023 11:19:16 +0100 Subject: [PATCH 1/4] w --- compiler/rustc_borrowck/src/consumers.rs | 6 +- .../src/diagnostics/bound_region_errors.rs | 7 +- compiler/rustc_borrowck/src/lib.rs | 14 +++- compiler/rustc_borrowck/src/nll.rs | 3 + .../src/region_infer/opaque_types.rs | 5 +- .../src/type_check/canonical.rs | 6 +- .../src/type_check/free_region_relations.rs | 4 +- .../src/type_check/liveness/trace.rs | 6 +- compiler/rustc_borrowck/src/type_check/mod.rs | 21 ++++-- .../src/type_check/relate_tys.rs | 4 + .../src/transform/check_consts/check.rs | 6 +- .../src/transform/check_consts/ops.rs | 4 +- .../src/transform/check_consts/qualifs.rs | 11 ++- .../src/util/compare_types.rs | 5 +- .../rustc_hir_analysis/src/astconv/mod.rs | 4 +- compiler/rustc_hir_analysis/src/autoderef.rs | 9 ++- .../rustc_hir_analysis/src/check/check.rs | 12 +-- .../src/check/compare_impl_item.rs | 14 ++-- .../rustc_hir_analysis/src/check/wfcheck.rs | 13 +++- .../src/coherence/builtin.rs | 14 ++-- compiler/rustc_hir_analysis/src/collect.rs | 4 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 1 + .../src/impl_wf_check/min_specialization.rs | 4 +- compiler/rustc_hir_analysis/src/lib.rs | 12 ++- compiler/rustc_hir_typeck/src/autoderef.rs | 9 ++- compiler/rustc_hir_typeck/src/check.rs | 1 + compiler/rustc_hir_typeck/src/closure.rs | 9 ++- compiler/rustc_hir_typeck/src/coercion.rs | 35 ++++----- compiler/rustc_hir_typeck/src/demand.rs | 4 +- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 13 ++-- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 ++- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 9 ++- .../src/generator_interior/mod.rs | 2 +- compiler/rustc_hir_typeck/src/inherited.rs | 13 ++-- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- compiler/rustc_hir_typeck/src/method/mod.rs | 6 +- compiler/rustc_hir_typeck/src/method/probe.rs | 54 +++++++------- compiler/rustc_hir_typeck/src/op.rs | 6 +- compiler/rustc_infer/src/infer/at.rs | 11 +-- .../src/infer/canonical/query_response.rs | 48 +++++++++--- compiler/rustc_infer/src/infer/combine.rs | 7 +- compiler/rustc_infer/src/infer/equate.rs | 3 +- compiler/rustc_infer/src/infer/glb.rs | 4 +- compiler/rustc_infer/src/infer/lattice.rs | 15 +++- compiler/rustc_infer/src/infer/lub.rs | 4 +- compiler/rustc_infer/src/infer/mod.rs | 50 ++++--------- .../rustc_infer/src/infer/nll_relate/mod.rs | 11 ++- .../rustc_infer/src/infer/opaque_types.rs | 41 +++++++--- compiler/rustc_infer/src/infer/sub.rs | 3 +- compiler/rustc_infer/src/traits/engine.rs | 4 +- compiler/rustc_trait_selection/src/infer.rs | 2 +- .../src/solve/eval_ctxt.rs | 8 +- .../src/solve/fulfill.rs | 11 ++- .../rustc_trait_selection/src/solve/mod.rs | 6 +- .../solve/trait_goals/structural_traits.rs | 2 +- .../src/traits/auto_trait.rs | 6 +- .../src/traits/chalk_fulfill.rs | 20 ++++- .../src/traits/coherence.rs | 28 +++---- .../src/traits/const_evaluatable.rs | 6 +- .../src/traits/engine.rs | 74 +++++++++++++------ .../src/traits/error_reporting/ambiguity.rs | 6 +- .../src/traits/error_reporting/mod.rs | 16 ++-- .../src/traits/error_reporting/suggestions.rs | 11 +-- .../src/traits/fulfill.rs | 45 ++++++++--- .../rustc_trait_selection/src/traits/misc.rs | 6 +- .../rustc_trait_selection/src/traits/mod.rs | 15 ++-- .../src/traits/outlives_bounds.rs | 3 +- .../src/traits/project.rs | 14 ++-- .../src/traits/query/evaluate_obligation.rs | 3 +- .../src/traits/query/normalize.rs | 5 ++ .../src/traits/query/type_op/custom.rs | 12 ++- .../src/traits/query/type_op/mod.rs | 18 ++++- .../src/traits/select/confirmation.rs | 20 ++--- .../src/traits/select/mod.rs | 59 +++++++++++---- .../src/traits/specialize/mod.rs | 7 +- .../rustc_trait_selection/src/traits/util.rs | 14 ++-- .../rustc_trait_selection/src/traits/wf.rs | 3 +- compiler/rustc_traits/src/codegen.rs | 12 +-- compiler/rustc_traits/src/dropck_outlives.rs | 4 +- .../rustc_traits/src/evaluate_obligation.rs | 14 ++-- .../src/normalize_erasing_regions.rs | 4 +- .../src/normalize_projection_ty.rs | 4 +- compiler/rustc_traits/src/type_op.rs | 19 ++--- .../rustc_ty_utils/src/structural_match.rs | 4 +- src/librustdoc/clean/blanket_impl.rs | 6 +- src/librustdoc/clean/mod.rs | 3 +- src/tools/clippy/clippy_utils/src/ty.rs | 4 +- tests/ui/impl-trait/issues/issue-70877.stderr | 21 +++--- .../issue-53398-cyclic-types.stderr | 5 +- 90 files changed, 652 insertions(+), 435 deletions(-) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 055b281bc2e70..bee58e4ad9e88 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -33,8 +33,10 @@ pub fn get_body_with_borrowck_facts( def: ty::WithOptConstParam, ) -> BodyWithBorrowckFacts<'_> { let (input_body, promoted) = tcx.mir_promoted(def); - let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build(); + let infcx = tcx.infer_ctxt().build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); - *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap() + *super::do_mir_borrowck(&infcx, input_body, promoted, true, DefiningAnchor::Bind(def.did)) + .1 + .unwrap() } diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 68205fa45587b..a6a76bfe30b4c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_infer::infer::region_constraints::Constraint; use rustc_infer::infer::region_constraints::RegionConstraintData; +use rustc_infer::infer::DefiningAnchor; use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _}; use rustc_infer::traits::ObligationCause; @@ -245,7 +246,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { ) -> Option> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); type_op_prove_predicate_with_cause(&ocx, key, cause); try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) } @@ -286,7 +287,7 @@ where ) -> Option> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); // FIXME(lqd): Unify and de-duplicate the following with the actual // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the @@ -330,7 +331,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { ) -> Option> { let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?; try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 5e77f6b190a69..fe3a2c77c9354 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -151,11 +151,17 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> &Bor let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner; - let infcx = - tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); + let infcx = tcx.infer_ctxt().build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); - let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0; + let opt_closure_req = do_mir_borrowck( + &infcx, + input_body, + promoted, + false, + DefiningAnchor::Bind(hir_owner.def_id), + ) + .0; debug!("mir_borrowck done"); tcx.arena.alloc(opt_closure_req) @@ -172,6 +178,7 @@ fn do_mir_borrowck<'tcx>( input_body: &Body<'tcx>, input_promoted: &IndexVec>, return_body_with_facts: bool, + defining_use_anchor: DefiningAnchor, ) -> (BorrowCheckResult<'tcx>, Option>>) { let def = input_body.source.with_opt_param().as_local().unwrap(); debug!(?def); @@ -274,6 +281,7 @@ fn do_mir_borrowck<'tcx>( &borrow_set, &upvars, use_polonius, + defining_use_anchor, ); // Dump MIR results into a file, if that is enabled. This let us diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 96228338a4c22..5028984dc6592 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -5,6 +5,7 @@ use rustc_data_structures::vec_map::VecMap; use rustc_hir::def_id::LocalDefId; use rustc_index::vec::IndexVec; +use rustc_infer::infer::DefiningAnchor; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, @@ -166,6 +167,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( borrow_set: &BorrowSet<'tcx>, upvars: &[Upvar<'tcx>], use_polonius: bool, + defining_use_anchor: DefiningAnchor, ) -> NllOutput<'tcx> { let mut all_facts = (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default()); @@ -190,6 +192,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( elements, upvars, use_polonius, + defining_use_anchor, ); if let Some(all_facts) = &mut all_facts { diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 748c8b9e4420c..9a0c852ebe216 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -273,12 +273,11 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { // This logic duplicates most of `check_opaque_meets_bounds`. // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. let param_env = self.tcx.param_env(def_id); + let infcx = self.tcx.infer_ctxt().build(); // HACK This bubble is required for this tests to pass: // nested-return-type2-tait2.rs // nested-return-type2-tait3.rs - let infcx = - self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Bubble); // Require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the // hidden type is well formed even without those bounds. diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index b27d5d2053213..459d4eb0a147b 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -1,5 +1,6 @@ use std::fmt; +use rustc_infer::infer::DefiningAnchor; use rustc_infer::infer::{canonical::Canonical, InferOk}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; @@ -37,7 +38,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { { let old_universe = self.infcx.universe(); - let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?; + let TypeOpOutput { output, constraints, error_info } = + op.fully_perform(self.infcx, self.defining_use_anchor)?; debug!(?output, ?constraints); @@ -220,7 +222,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let cause = ObligationCause::dummy_with_span(span); let param_env = self.param_env; let op = |infcx: &'_ _| { - let ocx = ObligationCtxt::new_in_snapshot(infcx); + let ocx = ObligationCtxt::new_in_snapshot(infcx, DefiningAnchor::Error); let user_ty = ocx.normalize(&cause, param_env, user_ty); ocx.eq(&cause, param_env, user_ty, mir_ty)?; if !ocx.select_all_or_error().is_empty() { diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 4004966c40a77..957857dd00f91 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -243,7 +243,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) - .fully_perform(self.infcx) + .fully_perform(self.infcx, rustc_infer::infer::DefiningAnchor::Error) .unwrap_or_else(|_| { let guar = self .infcx @@ -324,7 +324,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let TypeOpOutput { output: bounds, constraints, .. } = self .param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) - .fully_perform(self.infcx) + .fully_perform(self.infcx, rustc_infer::infer::DefiningAnchor::Error) .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty)); debug!(?bounds, ?constraints); self.add_outlives_bounds(bounds); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 9731b10aa99d9..dd4123b8977d7 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -569,8 +569,10 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,); let param_env = typeck.param_env; - let TypeOpOutput { output, constraints, .. } = - param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap(); + let TypeOpOutput { output, constraints, .. } = param_env + .and(DropckOutlives::new(dropped_ty)) + .fully_perform(typeck.infcx, typeck.defining_use_anchor) + .unwrap(); DropData { dropck_result: output, region_constraint_data: constraints } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3919c4793a06f..8b3cd0d5cc17d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -21,7 +21,8 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ - InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin, + DefiningAnchor, InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, + NllRegionVariableOrigin, }; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; @@ -136,6 +137,7 @@ pub(crate) fn type_check<'mir, 'tcx>( elements: &Rc, upvars: &[Upvar<'tcx>], use_polonius: bool, + defining_use_anchor: DefiningAnchor, ) -> MirTypeckResults<'tcx> { let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body); let mut constraints = MirTypeckRegionConstraints { @@ -182,6 +184,7 @@ pub(crate) fn type_check<'mir, 'tcx>( ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, + defining_use_anchor, ); let errors_reported = { @@ -879,6 +882,7 @@ struct TypeChecker<'a, 'tcx> { implicit_region_bound: ty::Region<'tcx>, reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, + defining_use_anchor: DefiningAnchor, } struct BorrowCheckContext<'a, 'tcx> { @@ -1027,6 +1031,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, + defining_use_anchor: DefiningAnchor, ) -> Self { let mut checker = Self { infcx, @@ -1038,6 +1043,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { implicit_region_bound, borrowck_context, reported_errors: Default::default(), + defining_use_anchor, }; checker.check_user_type_annotations(); checker @@ -2698,10 +2704,15 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> { /// constraints in our `InferCtxt` type ErrorInfo = InstantiateOpaqueType<'tcx>; - fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible> { - let (mut output, region_constraints) = scrape_region_constraints(infcx, || { - Ok(InferOk { value: (), obligations: self.obligations.clone() }) - })?; + fn fully_perform( + mut self, + infcx: &InferCtxt<'tcx>, + defining_use_anchor: DefiningAnchor, + ) -> Fallible> { + let (mut output, region_constraints) = + scrape_region_constraints(infcx, defining_use_anchor, || { + Ok(InferOk { value: (), obligations: self.obligations.clone() }) + })?; self.region_constraints = Some(region_constraints); output.error_info = Some(self); Ok(output) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index d96372fb99baa..30803e6fd8e91 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -87,6 +87,10 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> self.locations.span(self.type_checker.body) } + fn defining_use_anchor(&self) -> rustc_infer::infer::DefiningAnchor { + self.type_checker.defining_use_anchor + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.type_checker.param_env } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index db55dbc2bfd70..be3eef51319ed 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -4,7 +4,7 @@ use rustc_errors::{Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -745,7 +745,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let implsrc = { let infcx = tcx.infer_ctxt().build(); - let mut selcx = SelectionContext::new(&infcx); + let mut selcx = SelectionContext::new(&infcx, DefiningAnchor::Error); selcx.select(&obligation) }; @@ -753,7 +753,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // "non-const" check. This is required for correctness here. { let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); let predicates = tcx.predicates_of(callee).instantiate(tcx, substs); let cause = ObligationCause::new( diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index e586720a0d088..decbfd3a789f0 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -7,7 +7,7 @@ use rustc_errors::{ }; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -147,7 +147,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { ); let infcx = tcx.infer_ctxt().build(); - let mut selcx = SelectionContext::new(&infcx); + let mut selcx = SelectionContext::new(&infcx, DefiningAnchor::Error); let implsrc = selcx.select(&obligation); if let Ok(Some(ImplSource::UserDefined(data))) = implsrc { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index bb4b7ad50b8f2..f24887bfc912c 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -4,7 +4,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::LangItem; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::mir; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; @@ -162,7 +162,7 @@ impl Qualif for NeedsNonConstDrop { ); let infcx = cx.tcx.infer_ctxt().build(); - let mut selcx = SelectionContext::new(&infcx); + let mut selcx = SelectionContext::new(&infcx, DefiningAnchor::Error); let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { // If we couldn't select a const destruct candidate, then it's bad return true; @@ -184,7 +184,12 @@ impl Qualif for NeedsNonConstDrop { } // If we had any errors, then it's bad - !traits::fully_solve_obligations(&infcx, impl_src.nested_obligations()).is_empty() + !traits::fully_solve_obligations( + &infcx, + impl_src.nested_obligations(), + rustc_infer::infer::DefiningAnchor::Error, + ) + .is_empty() } fn in_adt_inherently<'tcx>( diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs index f5f3d5de6b5a2..21ed134cb5fca 100644 --- a/compiler/rustc_const_eval/src/util/compare_types.rs +++ b/compiler/rustc_const_eval/src/util/compare_types.rs @@ -41,10 +41,9 @@ pub fn is_subtype<'tcx>( return true; } - let mut builder = - tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble); + let mut builder = tcx.infer_ctxt().ignoring_regions(); let infcx = builder.build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Bubble); let cause = ObligationCause::dummy(); let src = ocx.normalize(&cause, param_env, src); let dest = ocx.normalize(&cause, param_env, dest); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3cd4c4afe866e..ca36f3c62e263 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -27,7 +27,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::middle::stability::AllowUnstable; @@ -2230,7 +2230,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .iter() .filter_map(|&(impl_, (assoc_item, def_scope))| { infcx.probe(|_| { - let ocx = ObligationCtxt::new_in_snapshot(&infcx); + let ocx = ObligationCtxt::new_in_snapshot(&infcx, DefiningAnchor::Error); let impl_ty = tcx.type_of(impl_); let impl_substs = infcx.fresh_item_substs(impl_); diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index ba2d4319af6e2..7b994d1c0fdf9 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -2,7 +2,7 @@ use crate::errors::AutoDerefReachedRecursionLimit; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::NormalizeExt; use crate::traits::{self, TraitEngine, TraitEngineExt}; -use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::{DefiningAnchor, InferCtxt}; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::Limit; @@ -30,6 +30,7 @@ pub struct Autoderef<'a, 'tcx> { span: Span, body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, + defining_use_anchor: DefiningAnchor, // Current state: state: AutoderefSnapshot<'tcx>, @@ -99,6 +100,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { body_def_id: LocalDefId, span: Span, base_ty: Ty<'tcx>, + defining_use_anchor: DefiningAnchor, ) -> Autoderef<'a, 'tcx> { Autoderef { infcx, @@ -114,6 +116,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { }, include_raw_pointers: false, silence_errors: false, + defining_use_anchor, } } @@ -140,9 +143,9 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { let normalized_ty = self .infcx - .at(&cause, self.param_env) + .at(&cause, self.param_env, DefiningAnchor::Error) .normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs)); - let mut fulfillcx = >::new_in_snapshot(tcx); + let mut fulfillcx = >::new_in_snapshot(tcx, self.defining_use_anchor); let normalized_ty = normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx); let errors = fulfillcx.select_where_possible(&self.infcx); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 14dc9d8918000..f10d81d891f49 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -402,11 +402,8 @@ fn check_opaque_meets_bounds<'tcx>( }; let param_env = tcx.param_env(defining_use_anchor); - let infcx = tcx - .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)) - .build(); - let ocx = ObligationCtxt::new(&infcx); + let infcx = tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx, defining_use_anchor); let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); // `ReErased` regions appear in the "parent_substs" of closures/generators. @@ -1533,15 +1530,14 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { // typeck writeback gives us predicates with their regions erased. // As borrowck already has checked lifetimes, we do not need to do it again. .ignoring_regions() - // Bind opaque types to `def_id` as they should have been checked by borrowck. - .with_opaque_type_inference(DefiningAnchor::Bind(def_id)) .build(); - let mut fulfillment_cx = >::new(infcx.tcx); + let mut fulfillment_cx = >::new(infcx.tcx, DefiningAnchor::Bind(def_id)); for (predicate, cause) in generator_interior_predicates { let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate); fulfillment_cx.register_predicate_obligation(&infcx, obligation); } + // Bind opaque types to `def_id` as they should have been checked by borrowck. let errors = fulfillment_cx.select_all_or_error(&infcx); debug!(?errors); if !errors.is_empty() { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 6e6f8c1533bfe..0503a779950a8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -11,7 +11,7 @@ use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{self, DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::util::ExplicitSelf; @@ -202,7 +202,7 @@ fn compare_method_predicate_entailment<'tcx>( let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(infcx, DefiningAnchor::Error); debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds()); @@ -237,8 +237,6 @@ fn compare_method_predicate_entailment<'tcx>( // type. // Compute placeholder form of impl and trait method tys. - let tcx = infcx.tcx; - let mut wf_tys = FxIndexSet::default(); let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars( @@ -620,7 +618,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs); let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(infcx, DefiningAnchor::Error); // Normalize the impl signature with fresh variables for lifetime inference. let norm_cause = ObligationCause::misc(return_span, impl_m_def_id); @@ -1653,7 +1651,7 @@ pub(super) fn compare_impl_const_raw( let infcx = tcx.infer_ctxt().build(); let param_env = tcx.param_env(impl_const_item_def.to_def_id()); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); // The below is for the most part highly similar to the procedure // for methods above. It is simpler in many respects, especially @@ -1807,7 +1805,7 @@ fn compare_type_predicate_entailment<'tcx>( ); let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds()); @@ -1993,7 +1991,7 @@ pub(super) fn check_type_bounds<'tcx>( let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs); let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the // span for an impl's associated type. Instead, for these, use the def_span for the synthesized diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 71050864ce0c5..ad2e45d5e8b6f 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -11,7 +11,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs}; use rustc_infer::infer::outlives::obligations::TypeOutlives; -use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{self, DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::query::Providers; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -97,7 +97,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( { let param_env = tcx.param_env(body_def_id); let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(infcx, DefiningAnchor::Error); let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env }; @@ -1674,7 +1674,14 @@ fn receiver_is_valid<'tcx>( return true; } - let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty); + let mut autoderef = Autoderef::new( + infcx, + wfcx.param_env, + wfcx.body_def_id, + span, + receiver_ty, + wfcx.ocx.defining_use_anchor(), + ); // The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`. if arbitrary_self_types_enabled { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 5e8f69677cf3d..4ccd003bc25a0 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -9,8 +9,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::{self, RegionResolutionError}; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -235,7 +235,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef use rustc_type_ir::sty::TyKind::*; match (source.kind(), target.kind()) { (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) - if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {} + if infcx.at(&cause, param_env, DefiningAnchor::Error).eq(r_a, *r_b).is_ok() + && mutbl_a == *mutbl_b => {} (&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (), (&Adt(def_a, substs_a), &Adt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => @@ -278,7 +279,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } } - if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) { + if let Ok(ok) = + infcx.at(&cause, param_env, DefiningAnchor::Error).eq(ty_a, ty_b) + { if ok.obligations.is_empty() { create_err( "the trait `DispatchFromDyn` may only be implemented \ @@ -343,6 +346,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef [field.ty(tcx, substs_a), field.ty(tcx, substs_b)], ) }), + infer::DefiningAnchor::Error, ); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors); @@ -504,7 +508,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // we may have to evaluate constraint // expressions in the course of execution.) // See e.g., #41936. - if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) { + if let Ok(ok) = infcx.at(&cause, param_env, DefiningAnchor::Error).eq(a, b) { if ok.obligations.is_empty() { return None; } @@ -583,7 +587,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn let cause = traits::ObligationCause::misc(span, impl_did); let predicate = predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]); - let errors = traits::fully_solve_obligation(&infcx, predicate); + let errors = traits::fully_solve_obligation(&infcx, predicate, infer::DefiningAnchor::Error); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors); } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 604d54cafb532..8e1b0d6cf879e 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -25,7 +25,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::ty::query::Providers; @@ -1320,7 +1320,7 @@ fn suggest_impl_trait<'tcx>( { continue; } - let ocx = ObligationCtxt::new_in_snapshot(&infcx); + let ocx = ObligationCtxt::new_in_snapshot(&infcx, DefiningAnchor::Error); let item_ty = ocx.normalize( &ObligationCause::misc(span, def_id), param_env, diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index e330fcc785770..da9a7a674e17f 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -80,6 +80,7 @@ fn diagnostic_hir_wf_check<'tcx>( self.param_env, ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())), ), + rustc_infer::infer::DefiningAnchor::Error, ); if !errors.is_empty() { debug!("Wf-check got errors for {:?}: {:?}", ty, errors); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 58dd03811f78c..235e3087f4ba1 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -72,7 +72,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_infer::traits::specialization_graph::Node; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -162,7 +162,7 @@ fn get_impl_substs( impl2_node: Node, ) -> Option<(SubstsRef<'_>, SubstsRef<'_>)> { let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(infcx, DefiningAnchor::Error); let param_env = tcx.param_env(impl1_def_id); let assumed_wf_types = diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 62abcbbdc9f6e..37e1eb89ff944 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -102,7 +102,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_hir as hir; use rustc_hir::Node; -use rustc_infer::infer::{InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{DefiningAnchor, InferOk, TyCtxtInferExt}; use rustc_macros::fluent_messages; use rustc_middle::middle; use rustc_middle::ty::query::Providers; @@ -165,8 +165,12 @@ fn require_same_types<'tcx>( ) -> bool { let infcx = &tcx.infer_ctxt().build(); let param_env = ty::ParamEnv::empty(); - let errors = match infcx.at(cause, param_env).eq(expected, actual) { - Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations), + let errors = match infcx.at(cause, param_env, DefiningAnchor::Error).eq(expected, actual) { + Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations( + infcx, + obligations, + rustc_infer::infer::DefiningAnchor::Error, + ), Err(err) => { infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit(); return false; @@ -313,7 +317,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { main_diagnostics_def_id, ObligationCauseCode::MainFunctionType, ); - let ocx = traits::ObligationCtxt::new(&infcx); + let ocx = traits::ObligationCtxt::new(&infcx, DefiningAnchor::Error); let norm_return_ty = ocx.normalize(&cause, param_env, return_ty); ocx.register_bound(cause, param_env, norm_return_ty, term_did); let errors = ocx.select_all_or_error(); diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 7873257c4e3d1..430f272c96362 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -12,7 +12,14 @@ use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { - Autoderef::new(self, self.param_env, self.body_id, span, base_ty) + Autoderef::new( + self, + self.param_env, + self.body_id, + span, + base_ty, + self.defining_use_anchor(), + ) } pub fn try_overloaded_deref( diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index bf8259ff70fa9..291b7759c3013 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -46,6 +46,7 @@ pub(super) fn check_fn<'a, 'tcx>( fn_def_id, decl.output.span(), fcx.param_env, + fcx.defining_use_anchor(), )); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 773ac0e40c571..17288e8a1b468 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -564,8 +564,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check that E' = S'. let cause = self.misc(hir_ty.span); let InferOk { value: (), obligations } = self - .at(&cause, self.param_env) - .define_opaque_types(true) + .at(&cause) + .define_opaque_types(self.defining_use_anchor()) .eq(*expected_ty, supplied_ty)?; all_obligations.extend(obligations); } @@ -577,8 +577,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let cause = &self.misc(decl.output.span()); let InferOk { value: (), obligations } = self - .at(cause, self.param_env) - .define_opaque_types(true) + .at(cause) + .define_opaque_types(self.defining_use_anchor()) .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?; all_obligations.extend(obligations); @@ -735,6 +735,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { body_def_id, self.tcx.def_span(expr_def_id), self.param_env, + self.defining_use_anchor(), ); self.register_predicates(obligations); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 00b86890b33f4..232d85a4038bb 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -44,8 +44,9 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Expr; use rustc_hir_analysis::astconv::AstConv; +use rustc_infer::infer::at::At; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{Coercion, InferOk, InferResult}; +use rustc_infer::infer::{Coercion, DefiningAnchor, InferOk, InferResult}; use rustc_infer::traits::Obligation; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ @@ -140,10 +141,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Coerce { fcx, cause, allow_two_phase, use_lub: false } } + pub fn at(&self) -> At<'_, 'tcx> { + self.fcx.at(&self.cause) + } + fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub); self.commit_if_ok(|_| { - let at = self.at(&self.cause, self.fcx.param_env).define_opaque_types(true); + let at = self.at().define_opaque_types(self.defining_use_anchor()); if self.use_lub { at.lub(b, a) } else { @@ -175,7 +180,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // so this will have the side-effect of making sure we have no ambiguities // due to `[type error]` and `_` not coercing together. let _ = self.commit_if_ok(|_| { - self.at(&self.cause, self.param_env).define_opaque_types(true).eq(a, b) + self.at().define_opaque_types(self.defining_use_anchor()).eq(a, b) }); return success(vec![], self.fcx.tcx.ty_error(guar), vec![]); } @@ -581,7 +586,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } })?; - let mut selcx = traits::SelectionContext::new(self); + let mut selcx = traits::SelectionContext::new(self, self.defining_use_anchor()); // Create an obligation for `Source: CoerceUnsized`. let cause = ObligationCause::new( @@ -839,8 +844,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { //! into a closure or a `proc`. let b = self.shallow_resolve(b); - let InferOk { value: b, mut obligations } = - self.at(&self.cause, self.param_env).normalize(b); + let InferOk { value: b, mut obligations } = self.at().normalize(b); debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b); match b.kind() { @@ -861,8 +865,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } - let InferOk { value: a_sig, obligations: o1 } = - self.at(&self.cause, self.param_env).normalize(a_sig); + let InferOk { value: a_sig, obligations: o1 } = self.at().normalize(a_sig); obligations.extend(o1); let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig); @@ -1015,7 +1018,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(ok) = coerce.coerce(source, target) else { return false; }; - let ocx = ObligationCtxt::new_in_snapshot(self); + let ocx = ObligationCtxt::new_in_snapshot(self, DefiningAnchor::Error); ocx.register_obligations(ok.obligations); ocx.select_where_possible().is_empty() }) @@ -1101,9 +1104,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::FnDef(..), ty::FnDef(..)) => { // Don't reify if the function types have a LUB, i.e., they // are the same function and their parameters have a LUB. - match self - .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) - { + match self.commit_if_ok(|_| self.at(cause).lub(prev_ty, new_ty)) { // We have a LUB of prev_ty and new_ty, just return it. Ok(ok) => return Ok(self.register_infer_ok_obligations(ok)), Err(_) => { @@ -1151,7 +1152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The signature must match. let (a_sig, b_sig) = self.normalize(new.span, (a_sig, b_sig)); let sig = self - .at(cause, self.param_env) + .at(cause) .trace(prev_ty, new_ty) .lub(a_sig, b_sig) .map(|ok| self.register_infer_ok_obligations(ok))?; @@ -1237,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); return self - .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) + .commit_if_ok(|_| self.at(cause).lub(prev_ty, new_ty)) .map(|ok| self.register_infer_ok_obligations(ok)); } } @@ -1248,7 +1249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(e) = first_error { Err(e) } else { - self.commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) + self.commit_if_ok(|_| self.at(cause).lub(prev_ty, new_ty)) .map(|ok| self.register_infer_ok_obligations(ok)) } } @@ -1485,9 +1486,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // // Another example is `break` with no argument expression. assert!(expression_ty.is_unit(), "if let hack without unit type"); - fcx.at(cause, fcx.param_env) + fcx.at(cause) // needed for tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs - .define_opaque_types(true) + .define_opaque_types(fcx.defining_use_anchor()) .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty()) .map(|infer_ok| { fcx.register_infer_ok_obligations(infer_ok); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 7ba57b3b7a266..d2c60e38cff92 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Option> { - match self.at(cause, self.param_env).define_opaque_types(true).sup(expected, actual) { + match self.at(cause).define_opaque_types(self.defining_use_anchor()).sup(expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); None @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Option> { - match self.at(cause, self.param_env).define_opaque_types(true).eq(expected, actual) { + match self.at(cause).define_opaque_types(self.defining_use_anchor()).eq(expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); None diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7fc4ccb04ee0b..4c258cd246bbc 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1683,7 +1683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(_) = remaining_fields.remove(&ident) { let target_ty = self.field_ty(base_expr.span, f, substs); let cause = self.misc(base_expr.span); - match self.at(&cause, self.param_env).sup(target_ty, fru_ty) { + match self.at(&cause).sup(target_ty, fru_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 2075537cad71f..11751f5f3dc5d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -313,9 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { where T: TypeFoldable>, { - self.register_infer_ok_obligations( - self.at(&self.misc(span), self.param_env).normalize(value), - ) + self.register_infer_ok_obligations(self.at(&self.misc(span)).normalize(value)) } pub fn require_type_meets( @@ -557,7 +555,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unify `interior` with `witness` and collect all the resulting obligations. let span = self.tcx.hir().body(body_id).value.span; let ok = self - .at(&self.misc(span), self.param_env) + .at(&self.misc(span)) .eq(interior, witness) .expect("Failed to unify generator interior type"); let mut obligations = ok.obligations; @@ -734,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::subst::GenericArgKind::Type(ty) = ty.unpack() && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind() && let Some(def_id) = def_id.as_local() - && self.opaque_type_origin(def_id).is_some() { + && self.opaque_type_origin(def_id, self.defining_use_anchor()).is_some() { return None; } } @@ -742,7 +740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expect_args = self .fudge_inference_if_ok(|| { - let ocx = ObligationCtxt::new_in_snapshot(self); + let ocx = ObligationCtxt::new_in_snapshot(self, self.defining_use_anchor()); // Attempt to apply a subtyping relationship between the formal // return type (likely containing type variables if the function @@ -1315,7 +1313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This also occurs for an enum variant on a type alias. let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).subst(tcx, substs)); let self_ty = self.normalize(span, self_ty); - match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) { + match self.at(&self.misc(span)).eq(impl_ty, self_ty) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { self.tcx.sess.delay_span_bug( @@ -1456,6 +1454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.param_env, original_values, query_result, + self.defining_use_anchor(), ) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index ea54b76bdec96..c53b9792d204f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -301,9 +301,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 3. Check if the formal type is a supertype of the checked one // and register any such obligations for future type checks - let supertype_error = self - .at(&self.misc(provided_arg.span), self.param_env) - .sup(formal_input_ty, coerced_ty); + let supertype_error = + self.at(&self.misc(provided_arg.span)).sup(formal_input_ty, coerced_ty); let subtyping_error = match supertype_error { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); @@ -584,9 +583,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Using probe here, since we don't want this subtyping to affect inference. - let subtyping_error = self.probe(|_| { - self.at(&self.misc(arg_span), self.param_env).sup(formal_input_ty, coerced_ty).err() - }); + let subtyping_error = self + .probe(|_| self.at(&self.misc(arg_span)).sup(formal_input_ty, coerced_ty).err()); // Same as above: if either the coerce type or the checked type is an error type, // consider them *not* compatible. @@ -1898,7 +1896,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.param_env, ty::Binder::dummy(trait_ref), ); - match SelectionContext::new(&self).select(&obligation) { + match SelectionContext::new(&self,self.defining_use_anchor()).select(&obligation) { Ok(Some(traits::ImplSource::UserDefined(impl_source))) => { Some(impl_source.impl_def_id) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 1dea3e6f900d4..1e06c077f850c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -6,6 +6,7 @@ mod suggestions; pub use _impl::*; use rustc_errors::ErrorGuaranteed; +use rustc_infer::infer::at::At; pub use suggestions::*; use crate::coercion::DynamicCoerceMany; @@ -13,9 +14,9 @@ use crate::{Diverges, EnclosingBreakables, Inherited}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir_analysis::astconv::AstConv; -use rustc_infer::infer; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{self, DefiningAnchor}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; @@ -145,6 +146,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.cause(span, ObligationCauseCode::MiscObligation) } + pub fn at(&'a self, cause: &'a ObligationCause<'tcx>) -> At<'a, 'tcx> { + self.infcx.at(cause, self.param_env, self.defining_use_anchor()) + } + pub fn sess(&self) -> &Session { &self.tcx.sess } @@ -164,7 +169,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return fn_sig; } self.probe(|_| { - let ocx = ObligationCtxt::new_in_snapshot(self); + let ocx = ObligationCtxt::new_in_snapshot(self, DefiningAnchor::Error); let normalized_fn_sig = ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig); if ocx.select_all_or_error().is_empty() { diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 2e41c2041f888..8efb097b9376a 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -327,7 +327,7 @@ pub fn resolve_interior<'a, 'tcx>( ); // Unify the type variable inside the generator with the new witness - match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(interior, witness) { + match fcx.at(&fcx.misc(body.value.span)).eq(interior, witness) { Ok(ok) => fcx.register_infer_ok_obligations(ok), _ => bug!("failed to relate {interior} and {witness}"), } diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index 4110b176b41b1..75e2ff599eb9a 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -76,17 +76,14 @@ impl<'tcx> Inherited<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner; - let infcx = tcx - .infer_ctxt() - .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)) - .build(); + let infcx = tcx.infer_ctxt().ignoring_regions().build(); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); + let defining_use_anchor = DefiningAnchor::Bind(def_id); Inherited { typeck_results, infcx, - fulfillment_cx: RefCell::new(>::new(tcx)), + fulfillment_cx: RefCell::new(>::new(tcx, defining_use_anchor)), locals: RefCell::new(Default::default()), deferred_sized_obligations: RefCell::new(Vec::new()), deferred_call_resolutions: RefCell::new(Default::default()), @@ -99,6 +96,10 @@ impl<'tcx> Inherited<'tcx> { } } + pub fn defining_use_anchor(&self) -> DefiningAnchor { + self.fulfillment_cx.borrow().defining_use_anchor() + } + #[instrument(level = "debug", skip(self))] pub(super) fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) { if obligation.has_escaping_bound_vars() { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 169f128e0a003..dc8b398205565 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -478,7 +478,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { substs, })), ); - match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) { + match self.at(&cause).sup(method_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); } diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 0456dd56c340e..acc80e0f5229f 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -409,8 +409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fn_sig = self.instantiate_binder_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig); - let InferOk { value, obligations: o } = - self.at(&obligation.cause, self.param_env).normalize(fn_sig); + let InferOk { value, obligations: o } = self.at(&obligation.cause).normalize(fn_sig); let fn_sig = { obligations.extend(o); value @@ -426,8 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // any late-bound regions appearing in its bounds. let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); - let InferOk { value, obligations: o } = - self.at(&obligation.cause, self.param_env).normalize(bounds); + let InferOk { value, obligations: o } = self.at(&obligation.cause).normalize(bounds); let bounds = { obligations.extend(o); value diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 562dd2caae341..ef9749038e3d1 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -508,10 +508,16 @@ fn method_autoderef_steps<'tcx>( let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal); let ParamEnvAnd { param_env, value: self_ty } = goal; - let mut autoderef = - Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty) - .include_raw_pointers() - .silence_errors(); + let mut autoderef = Autoderef::new( + infcx, + param_env, + hir::def_id::CRATE_DEF_ID, + DUMMY_SP, + self_ty, + infer::DefiningAnchor::Error, + ) + .include_raw_pointers() + .silence_errors(); let mut reached_raw_pointer = false; let mut steps: Vec<_> = autoderef .by_ref() @@ -749,7 +755,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // see issue #89650 let cause = traits::ObligationCause::misc(self.span, self.body_id); let InferOk { value: xform_self_ty, obligations } = - self.fcx.at(&cause, self.param_env).normalize(xform_self_ty); + self.fcx.at(&cause).normalize(xform_self_ty); debug!( "assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}", @@ -928,11 +934,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty); if let Some(self_ty) = self_ty { - if self - .at(&ObligationCause::dummy(), self.param_env) - .sup(fty.inputs()[0], self_ty) - .is_err() - { + if self.at(&ObligationCause::dummy()).sup(fty.inputs()[0], self_ty).is_err() { return false; } } @@ -1423,7 +1425,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let cause = traits::ObligationCause::misc(self.span, self.body_id); let predicate = ty::Binder::dummy(trait_ref); let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, predicate); - traits::SelectionContext::new(self).select(&obligation) + traits::SelectionContext::new(self, self.defining_use_anchor()).select(&obligation) } fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource { @@ -1435,9 +1437,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref) => self.probe(|_| { - let _ = self - .at(&ObligationCause::dummy(), self.param_env) - .sup(candidate.xform_self_ty, self_ty); + let _ = self.at(&ObligationCause::dummy()).sup(candidate.xform_self_ty, self_ty); match self.select_trait_candidate(trait_ref) { Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => { // If only a single impl matches, make the error message point @@ -1464,16 +1464,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.probe(|_| { // First check that the self type can be related. - let sub_obligations = match self - .at(&ObligationCause::dummy(), self.param_env) - .sup(probe.xform_self_ty, self_ty) - { - Ok(InferOk { obligations, value: () }) => obligations, - Err(err) => { - debug!("--> cannot relate self-types {:?}", err); - return ProbeResult::NoMatch; - } - }; + let sub_obligations = + match self.at(&ObligationCause::dummy()).sup(probe.xform_self_ty, self_ty) { + Ok(InferOk { obligations, value: () }) => obligations, + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); + return ProbeResult::NoMatch; + } + }; let mut result = ProbeResult::Match; let mut xform_ret_ty = probe.xform_ret_ty; @@ -1495,7 +1493,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let InferOk { value: normalized_xform_ret_ty, obligations: normalization_obligations, - } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); + } = self.fcx.at(&cause).normalize(xform_ret_ty); xform_ret_ty = normalized_xform_ret_ty; debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); @@ -1505,7 +1503,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let impl_bounds = impl_bounds.instantiate(self.tcx, substs); let InferOk { value: impl_bounds, obligations: norm_obligations } = - self.fcx.at(&cause, self.param_env).normalize(impl_bounds); + self.fcx.at(&cause).normalize(impl_bounds); // Convert the bounds into obligations. let impl_obligations = traits::predicates_for_generics( @@ -1658,7 +1656,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let InferOk { value: normalized_xform_ret_ty, obligations: normalization_obligations, - } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); + } = self.fcx.at(&cause).normalize(xform_ret_ty); xform_ret_ty = normalized_xform_ret_ty; debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); // Evaluate those obligations to see if they might possibly hold. @@ -1681,7 +1679,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ); if let ProbeResult::Match = result && self - .at(&ObligationCause::dummy(), self.param_env) + .at(&ObligationCause::dummy()) .sup(return_ty, xform_ret_ty) .is_err() { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 37783bc91bb8c..b57774b1c4873 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -776,7 +776,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (None, Some(trait_did)) => { let (obligation, _) = self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types)); - Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation)) + Err(rustc_trait_selection::traits::fully_solve_obligation( + self, + obligation, + self.defining_use_anchor(), + )) } } } diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 7d9bae735e55d..e4259c34fa98a 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -36,10 +36,7 @@ pub struct At<'a, 'tcx> { pub param_env: ty::ParamEnv<'tcx>, /// Whether we should define opaque types /// or just treat them opaquely. - /// Currently only used to prevent predicate - /// matching from matching anything against opaque - /// types. - pub define_opaque_types: bool, + pub define_opaque_types: DefiningAnchor, } pub struct Trace<'a, 'tcx> { @@ -54,8 +51,9 @@ impl<'tcx> InferCtxt<'tcx> { &'a self, cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, + define_opaque_types: impl Into, ) -> At<'a, 'tcx> { - At { infcx: self, cause, param_env, define_opaque_types: false } + At { infcx: self, cause, param_env, define_opaque_types: define_opaque_types.into() } } /// Forks the inference context, creating a new inference context with the same inference @@ -64,7 +62,6 @@ impl<'tcx> InferCtxt<'tcx> { pub fn fork(&self) -> Self { Self { tcx: self.tcx, - defining_use_anchor: self.defining_use_anchor, considering_regions: self.considering_regions, inner: self.inner.clone(), skip_leak_check: self.skip_leak_check.clone(), @@ -93,7 +90,7 @@ pub trait ToTrace<'tcx>: Relate<'tcx> + Copy { } impl<'a, 'tcx> At<'a, 'tcx> { - pub fn define_opaque_types(self, define_opaque_types: bool) -> Self { + pub fn define_opaque_types(self, define_opaque_types: DefiningAnchor) -> Self { Self { define_opaque_types, ..self } } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 436d29c2449e4..dffb5b04dd214 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -14,7 +14,7 @@ use crate::infer::canonical::{ }; use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; -use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; +use crate::infer::{DefiningAnchor, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::traits::query::{Fallible, NoSolution}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt}; @@ -116,7 +116,7 @@ impl<'tcx> InferCtxt<'tcx> { if !true_errors.is_empty() { // FIXME -- we don't indicate *why* we failed to solve - debug!("make_query_response: true_errors={:#?}", true_errors); + debug!("true_errors={:#?}", true_errors); return Err(NoSolution); } @@ -188,12 +188,18 @@ impl<'tcx> InferCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, original_values: &OriginalQueryValues<'tcx>, query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>, + defining_use_anchor: DefiningAnchor, ) -> InferResult<'tcx, R> where R: Debug + TypeFoldable>, { - let InferOk { value: result_subst, mut obligations } = - self.query_response_substitution(cause, param_env, original_values, query_response)?; + let InferOk { value: result_subst, mut obligations } = self.query_response_substitution( + cause, + param_env, + original_values, + query_response, + defining_use_anchor, + )?; obligations.extend(self.query_outlives_constraints_into_obligations( cause, @@ -250,12 +256,19 @@ impl<'tcx> InferCtxt<'tcx> { original_values: &OriginalQueryValues<'tcx>, query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>, output_query_region_constraints: &mut QueryRegionConstraints<'tcx>, + defining_use_anchor: DefiningAnchor, ) -> InferResult<'tcx, R> where R: Debug + TypeFoldable>, { let InferOk { value: result_subst, mut obligations } = self - .query_response_substitution_guess(cause, param_env, original_values, query_response)?; + .query_response_substitution_guess( + cause, + param_env, + original_values, + query_response, + defining_use_anchor, + )?; // Compute `QueryOutlivesConstraint` values that unify each of // the original values `v_o` that was canonicalized into a @@ -364,6 +377,7 @@ impl<'tcx> InferCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, original_values: &OriginalQueryValues<'tcx>, query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>, + defining_use_anchor: DefiningAnchor, ) -> InferResult<'tcx, CanonicalVarValues<'tcx>> where R: Debug + TypeFoldable>, @@ -378,6 +392,7 @@ impl<'tcx> InferCtxt<'tcx> { param_env, original_values, query_response, + defining_use_anchor, )?; value.obligations.extend( @@ -410,6 +425,7 @@ impl<'tcx> InferCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, original_values: &OriginalQueryValues<'tcx>, query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>, + defining_use_anchor: DefiningAnchor, ) -> InferResult<'tcx, CanonicalVarValues<'tcx>> where R: Debug + TypeFoldable>, @@ -510,7 +526,7 @@ impl<'tcx> InferCtxt<'tcx> { let b = substitute_value(self.tcx, &result_subst, b); debug!(?a, ?b, "constrain opaque type"); obligations - .extend(self.at(cause, param_env).define_opaque_types(true).eq(a, b)?.obligations); + .extend(self.at(cause, param_env, defining_use_anchor).eq(a, b)?.obligations); } Ok(InferOk { value: result_subst, obligations }) @@ -603,8 +619,11 @@ impl<'tcx> InferCtxt<'tcx> { match (value1.unpack(), value2.unpack()) { (GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => { - obligations - .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations()); + obligations.extend( + self.at(cause, param_env, DefiningAnchor::Error) + .eq(v1, v2)? + .into_obligations(), + ); } (GenericArgKind::Lifetime(re1), GenericArgKind::Lifetime(re2)) if re1.is_erased() && re2.is_erased() => @@ -612,11 +631,14 @@ impl<'tcx> InferCtxt<'tcx> { // no action needed } (GenericArgKind::Lifetime(v1), GenericArgKind::Lifetime(v2)) => { - obligations - .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations()); + obligations.extend( + self.at(cause, param_env, DefiningAnchor::Error) + .eq(v1, v2)? + .into_obligations(), + ); } (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => { - let ok = self.at(cause, param_env).eq(v1, v2)?; + let ok = self.at(cause, param_env, DefiningAnchor::Error).eq(v1, v2)?; obligations.extend(ok.into_obligations()); } _ => { @@ -687,6 +709,10 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { self.param_env } + fn defining_use_anchor(&self) -> DefiningAnchor { + DefiningAnchor::Bubble + } + fn create_next_universe(&mut self) -> ty::UniverseIndex { self.infcx.create_next_universe() } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index a2332797e8680..1fd052f20d9b8 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -27,7 +27,7 @@ use super::glb::Glb; use super::lub::Lub; use super::sub::Sub; use super::type_variable::TypeVariableValue; -use super::{InferCtxt, MiscVariable, TypeTrace}; +use super::{DefiningAnchor, InferCtxt, MiscVariable, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; @@ -54,10 +54,7 @@ pub struct CombineFields<'infcx, 'tcx> { pub obligations: PredicateObligations<'tcx>, /// Whether we should define opaque types /// or just treat them opaquely. - /// Currently only used to prevent predicate - /// matching from matching anything against opaque - /// types. - pub define_opaque_types: bool, + pub define_opaque_types: DefiningAnchor, } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 54a62326ef7bd..d5719342ccd21 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -110,7 +110,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.fields.define_opaque_types && def_id.is_local() => + if def_id.is_local() => { self.fields.obligations.extend( infcx @@ -120,6 +120,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { self.a_is_expected(), &self.fields.trace.cause, self.param_env(), + self.fields.define_opaque_types, )? .obligations, ); diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 49df393d83b3e..55e4a62edbb92 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -2,8 +2,8 @@ use super::combine::{CombineFields, ObligationEmittingRelation}; use super::lattice::{self, LatticeDir}; -use super::InferCtxt; use super::Subtype; +use super::{DefiningAnchor, InferCtxt}; use crate::traits::{ObligationCause, PredicateObligations}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -142,7 +142,7 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, Ok(()) } - fn define_opaque_types(&self) -> bool { + fn define_opaque_types(&self) -> DefiningAnchor { self.fields.define_opaque_types } } diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index f377ac1d19e9c..125de378671bc 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -19,7 +19,7 @@ use super::combine::ObligationEmittingRelation; use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use super::InferCtxt; +use super::{DefiningAnchor, InferCtxt}; use crate::traits::ObligationCause; use rustc_middle::ty::relate::RelateResult; @@ -36,7 +36,7 @@ pub trait LatticeDir<'f, 'tcx>: ObligationEmittingRelation<'tcx> { fn cause(&self) -> &ObligationCause<'tcx>; - fn define_opaque_types(&self) -> bool; + fn define_opaque_types(&self) -> DefiningAnchor; // Relates the type `v` to `a` and `b` such that `v` represents // the LUB/GLB of `a` and `b` as appropriate. @@ -110,11 +110,18 @@ where ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b), (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if this.define_opaque_types() && def_id.is_local() => + if def_id.is_local() => { this.register_obligations( infcx - .handle_opaque_type(a, b, this.a_is_expected(), this.cause(), this.param_env())? + .handle_opaque_type( + a, + b, + this.a_is_expected(), + this.cause(), + this.param_env(), + this.define_opaque_types(), + )? .obligations, ); Ok(a) diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index c871ccb21f8de..44712ba90c9b6 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -2,8 +2,8 @@ use super::combine::{CombineFields, ObligationEmittingRelation}; use super::lattice::{self, LatticeDir}; -use super::InferCtxt; use super::Subtype; +use super::{DefiningAnchor, InferCtxt}; use crate::traits::{ObligationCause, PredicateObligations}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -142,7 +142,7 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, Ok(()) } - fn define_opaque_types(&self) -> bool { + fn define_opaque_types(&self) -> DefiningAnchor { self.fields.define_opaque_types } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4a834957959db..c5af01bc95274 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -231,21 +231,15 @@ pub enum DefiningAnchor { Error, } +impl From for DefiningAnchor { + fn from(v: LocalDefId) -> Self { + Self::Bind(v) + } +} + pub struct InferCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, - /// The `DefId` of the item in whose context we are performing inference or typeck. - /// It is used to check whether an opaque type use is a defining use. - /// - /// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up - /// the obligation. This frequently happens for - /// short lived InferCtxt within queries. The opaque type obligations are forwarded - /// to the outside until the end up in an `InferCtxt` for typeck or borrowck. - /// - /// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that - /// might come up during inference or typeck. - pub defining_use_anchor: DefiningAnchor, - /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during hir typeck as region /// solving is left to borrowck instead. @@ -540,7 +534,6 @@ impl<'tcx> fmt::Display for FixupError<'tcx> { /// Used to configure inference contexts before their creation. pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, - defining_use_anchor: DefiningAnchor, considering_regions: bool, /// Whether we are in coherence mode. intercrate: bool, @@ -552,27 +545,11 @@ pub trait TyCtxtInferExt<'tcx> { impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { - InferCtxtBuilder { - tcx: self, - defining_use_anchor: DefiningAnchor::Error, - considering_regions: true, - intercrate: false, - } + InferCtxtBuilder { tcx: self, considering_regions: true, intercrate: false } } } impl<'tcx> InferCtxtBuilder<'tcx> { - /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types, - /// you need to call this function. Otherwise the opaque type will be treated opaquely. - /// - /// It is only meant to be called in two places, for typeck - /// (via `Inherited::build`) and for the inference context used - /// in mir borrowck. - pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self { - self.defining_use_anchor = defining_use_anchor; - self - } - pub fn intercrate(mut self) -> Self { self.intercrate = true; self @@ -604,10 +581,9 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn build(&mut self) -> InferCtxt<'tcx> { - let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self; + let InferCtxtBuilder { tcx, considering_regions, intercrate } = *self; InferCtxt { tcx, - defining_use_anchor, considering_regions, inner: RefCell::new(InferCtxtInner::new()), lexical_region_resolutions: RefCell::new(None), @@ -729,7 +705,7 @@ impl<'tcx> InferCtxt<'tcx> { &'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, - define_opaque_types: bool, + define_opaque_types: DefiningAnchor, ) -> CombineFields<'a, 'tcx> { CombineFields { infcx: self, @@ -864,7 +840,7 @@ impl<'tcx> InferCtxt<'tcx> { T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); - self.probe(|_| self.at(origin, param_env).sub(a, b).is_ok()) + self.probe(|_| self.at(origin, param_env, DefiningAnchor::Error).sub(a, b).is_ok()) } pub fn can_eq(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool @@ -872,7 +848,7 @@ impl<'tcx> InferCtxt<'tcx> { T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); - self.probe(|_| self.at(origin, param_env).eq(a, b).is_ok()) + self.probe(|_| self.at(origin, param_env, DefiningAnchor::Error).eq(a, b).is_ok()) } #[instrument(skip(self), level = "debug")] @@ -967,7 +943,8 @@ impl<'tcx> InferCtxt<'tcx> { let ty::SubtypePredicate { a_is_expected, a, b } = self.instantiate_binder_with_placeholders(predicate); - let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; + let ok = + self.at(cause, param_env, DefiningAnchor::Error).sub_exp(a_is_expected, a, b)?; Ok(ok.unit()) })) @@ -1321,7 +1298,6 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self), ret)] pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> { - debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error); std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types) } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 573cd91a2a2a6..f4169b1de9485 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -36,6 +36,7 @@ use std::fmt::Debug; use std::ops::ControlFlow; use super::combine::ObligationEmittingRelation; +use super::DefiningAnchor; pub struct TypeRelating<'me, 'tcx, D> where @@ -74,6 +75,7 @@ where pub trait TypeRelatingDelegate<'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx>; + fn defining_use_anchor(&self) -> DefiningAnchor; fn span(&self) -> Span; /// Push a constraint `sup: sub` -- this constraint must be @@ -373,7 +375,14 @@ where let cause = ObligationCause::dummy_with_span(self.delegate.span()); let obligations = self .infcx - .handle_opaque_type(a, b, true, &cause, self.delegate.param_env())? + .handle_opaque_type( + a, + b, + true, + &cause, + self.delegate.param_env(), + self.delegate.defining_use_anchor(), + )? .obligations; self.delegate.register_obligations(obligations); trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d5c824d4c41c8..eb6aea3310f05 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -51,13 +51,16 @@ impl<'tcx> InferCtxt<'tcx> { body_id: LocalDefId, span: Span, param_env: ty::ParamEnv<'tcx>, + defining_use_anchor: DefiningAnchor, ) -> InferOk<'tcx, T> { if !value.has_opaque_types() { return InferOk { value, obligations: vec![] }; } let mut obligations = vec![]; let replace_opaque_type = |def_id: DefId| { - def_id.as_local().map_or(false, |def_id| self.opaque_type_origin(def_id).is_some()) + def_id.as_local().map_or(false, |def_id| { + self.opaque_type_origin(def_id, defining_use_anchor).is_some() + }) }; let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, @@ -79,9 +82,16 @@ impl<'tcx> InferCtxt<'tcx> { span, }); obligations.extend( - self.handle_opaque_type(ty, ty_var, true, &cause, param_env) - .unwrap() - .obligations, + self.handle_opaque_type( + ty, + ty_var, + true, + &cause, + param_env, + defining_use_anchor, + ) + .unwrap() + .obligations, ); ty_var } @@ -98,6 +108,7 @@ impl<'tcx> InferCtxt<'tcx> { a_is_expected: bool, cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, + defining_use_anchor: DefiningAnchor, ) -> InferResult<'tcx, ()> { if a.references_error() || b.references_error() { return Ok(InferOk { value: (), obligations: vec![] }); @@ -106,7 +117,7 @@ impl<'tcx> InferCtxt<'tcx> { let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => { let def_id = def_id.expect_local(); - let origin = match self.defining_use_anchor { + let origin = match defining_use_anchor { DefiningAnchor::Bind(_) => { // Check that this is `impl Trait` type is // declared by `parent_def_id` -- i.e., one whose @@ -142,7 +153,7 @@ impl<'tcx> InferCtxt<'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - self.opaque_type_origin(def_id)? + self.opaque_type_origin(def_id, defining_use_anchor)? } DefiningAnchor::Bubble => self.opaque_type_origin_unchecked(def_id), DefiningAnchor::Error => return None, @@ -153,8 +164,9 @@ impl<'tcx> InferCtxt<'tcx> { // no one encounters it in practice. // It does occur however in `fn fut() -> impl Future { async { 42 } }`, // where it is of no concern, so we only check for TAITs. - if let Some(OpaqueTyOrigin::TyAlias) = - b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id)) + if let Some(OpaqueTyOrigin::TyAlias) = b_def_id + .as_local() + .and_then(|b_def_id| self.opaque_type_origin(b_def_id, defining_use_anchor)) { self.tcx.sess.emit_err(OpaqueHiddenTypeDiag { span: cause.span, @@ -170,6 +182,7 @@ impl<'tcx> InferCtxt<'tcx> { b, origin, a_is_expected, + defining_use_anchor, )) } _ => None, @@ -371,9 +384,13 @@ impl<'tcx> InferCtxt<'tcx> { /// Returns the origin of the opaque type `def_id` if we're currently /// in its defining scope. #[instrument(skip(self), level = "trace", ret)] - pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { + pub fn opaque_type_origin( + &self, + def_id: LocalDefId, + defining_use_anchor: DefiningAnchor, + ) -> Option { let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let parent_def_id = match self.defining_use_anchor { + let parent_def_id = match defining_use_anchor { DefiningAnchor::Bubble | DefiningAnchor::Error => return None, DefiningAnchor::Bind(bind) => bind, }; @@ -527,6 +544,7 @@ impl<'tcx> InferCtxt<'tcx> { hidden_ty: Ty<'tcx>, origin: hir::OpaqueTyOrigin, a_is_expected: bool, + defining_use_anchor: DefiningAnchor, ) -> InferResult<'tcx, ()> { let tcx = self.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; @@ -546,8 +564,7 @@ impl<'tcx> InferCtxt<'tcx> { ); if let Some(prev) = prev { obligations = self - .at(&cause, param_env) - .define_opaque_types(true) + .at(&cause, param_env, defining_use_anchor) .eq_exp(a_is_expected, prev, hidden_ty)? .obligations; } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 3e8c2052de89d..2ef96c6a40768 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -138,7 +138,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.fields.define_opaque_types && def_id.is_local() => + if def_id.is_local() => { self.fields.obligations.extend( infcx @@ -148,6 +148,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { self.a_is_expected, &self.fields.trace.cause, self.param_env(), + self.fields.define_opaque_types, )? .obligations, ); diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index f75344f20b6d9..0e4e9e0cfd8c4 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,4 +1,4 @@ -use crate::infer::InferCtxt; +use crate::infer::{DefiningAnchor, InferCtxt}; use crate::traits::Obligation; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, ToPredicate, Ty}; @@ -49,6 +49,8 @@ pub trait TraitEngine<'tcx>: 'tcx { &mut self, infcx: &InferCtxt<'tcx>, ) -> Vec>; + + fn defining_use_anchor(&self) -> DefiningAnchor; } pub trait TraitEngineExt<'tcx> { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 9b47c7299bb7b..65b4d55bd08a1 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -138,7 +138,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { { let (infcx, key, canonical_inference_vars) = self.build_with_canonical(DUMMY_SP, canonical_key); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); let value = operation(&ocx, key)?; ocx.make_canonicalized_query_response(canonical_inference_vars, value) } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index ca438a103cf34..537cccf5ab848 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -2,7 +2,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; +use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, LateBoundRegionConversionTime}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; @@ -16,7 +16,7 @@ use std::ops::ControlFlow; use super::search_graph::SearchGraph; use super::Goal; -pub struct EvalCtxt<'a, 'tcx> { +pub(super) struct EvalCtxt<'a, 'tcx> { // FIXME: should be private. pub(super) infcx: &'a InferCtxt<'tcx>, pub(super) var_values: CanonicalVarValues<'tcx>, @@ -35,7 +35,7 @@ pub struct EvalCtxt<'a, 'tcx> { /// This field is used by a debug assertion in [`EvalCtxt::evaluate_goal`], /// see the comment in that method for more details. - pub in_projection_eq_hack: bool, + pub(super) in_projection_eq_hack: bool, } impl<'tcx> EvalCtxt<'_, 'tcx> { @@ -143,7 +143,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { rhs: T, ) -> Result>>, NoSolution> { self.infcx - .at(&ObligationCause::dummy(), param_env) + .at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error) .eq(lhs, rhs) .map(|InferOk { value: (), obligations }| { obligations.into_iter().map(|o| o.into()).collect() diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 38120b9760f3d..16d36ed6f4385 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -1,6 +1,6 @@ use std::mem; -use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::{DefiningAnchor, InferCtxt}; use rustc_infer::traits::{ query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, PredicateObligation, SelectionError, TraitEngine, @@ -26,7 +26,9 @@ pub struct FulfillmentCtxt<'tcx> { } impl<'tcx> FulfillmentCtxt<'tcx> { - pub fn new() -> FulfillmentCtxt<'tcx> { + pub fn new(defining_use_anchor: impl Into) -> FulfillmentCtxt<'tcx> { + // FIXME: add opaque types support to the new solver. + let _: DefiningAnchor = defining_use_anchor.into(); FulfillmentCtxt { obligations: Vec::new() } } } @@ -151,4 +153,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ) -> Vec> { std::mem::take(&mut self.obligations) } + + fn defining_use_anchor(&self) -> DefiningAnchor { + // FIXME: opaque type support + DefiningAnchor::Error + } } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 55d361b120441..42d60a9290d83 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -19,7 +19,7 @@ use std::mem; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{ CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData, @@ -31,6 +31,7 @@ use rustc_middle::ty::{ }; use rustc_span::DUMMY_SP; +use crate::solve::eval_ctxt::EvalCtxt; use crate::solve::search_graph::OverflowHandler; use crate::traits::ObligationCause; @@ -42,7 +43,6 @@ mod project_goals; mod search_graph; mod trait_goals; -pub use eval_ctxt::EvalCtxt; pub use fulfill::FulfillmentCtxt; trait CanonicalResponseExt { @@ -267,7 +267,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } else { let InferOk { value: (), obligations } = self .infcx - .at(&ObligationCause::dummy(), goal.param_env) + .at(&ObligationCause::dummy(), goal.param_env, DefiningAnchor::Error) .sub(goal.predicate.a, goal.predicate.b)?; self.evaluate_all_and_make_canonical_response( obligations.into_iter().map(|pred| pred.into()).collect(), diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs index d7d93377cf164..31681a9eb24b9 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs @@ -269,7 +269,7 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>( /// additional step of eagerly folding the associated types in the where /// clauses of the impl. In this example, that means replacing /// `::Bar` with `Ty` in the first impl. -pub(crate) fn predicates_for_object_candidate<'tcx>( +pub(in super::super) fn predicates_for_object_candidate<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, trait_ref: ty::TraitRef<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 1fb8659bb27d3..47760189520da 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -89,7 +89,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let trait_ref = tcx.mk_trait_ref(trait_did, [ty]); let infcx = tcx.infer_ctxt().build(); - let mut selcx = SelectionContext::new(&infcx); + let mut selcx = SelectionContext::new(&infcx, DefiningAnchor::Error); for polarity in [true, false] { let result = selcx.select(&Obligation::new( tcx, @@ -256,7 +256,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { fresh_preds.insert(self.clean_pred(infcx, predicate)); } - let mut select = SelectionContext::new(&infcx); + let mut select = SelectionContext::new(&infcx, DefiningAnchor::Error); let mut already_visited = FxHashSet::default(); let mut predicates = VecDeque::new(); @@ -814,7 +814,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) + match selcx.infcx.at(&obligation.cause, obligation.param_env, DefiningAnchor::Error).eq(c1, c2) { Ok(_) => (), Err(_) => return false, diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index b42a49eb47b90..e244fb5cd1695 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -8,21 +8,28 @@ use crate::traits::{ SelectionError, TraitEngine, }; use rustc_data_structures::fx::FxIndexSet; +use rustc_infer::infer::DefiningAnchor; use rustc_middle::ty::TypeVisitableExt; pub struct FulfillmentContext<'tcx> { obligations: FxIndexSet>, usable_in_snapshot: bool, + + defining_use_anchor: DefiningAnchor, } impl FulfillmentContext<'_> { - pub(super) fn new() -> Self { - FulfillmentContext { obligations: FxIndexSet::default(), usable_in_snapshot: false } + pub(super) fn new(defining_use_anchor: impl Into) -> Self { + FulfillmentContext { + obligations: FxIndexSet::default(), + usable_in_snapshot: false, + defining_use_anchor: defining_use_anchor.into(), + } } - pub(crate) fn new_in_snapshot() -> Self { - FulfillmentContext { usable_in_snapshot: true, ..Self::new() } + pub(crate) fn new_in_snapshot(defining_use_anchor: impl Into) -> Self { + FulfillmentContext { usable_in_snapshot: true, ..Self::new(defining_use_anchor) } } } @@ -90,6 +97,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { obligation.param_env, &orig_values, &response, + self.defining_use_anchor, ) { Ok(infer_ok) => next_round.extend( infer_ok.obligations.into_iter().map(|obligation| { @@ -145,4 +153,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { fn pending_obligations(&self) -> Vec> { self.obligations.iter().cloned().collect() } + + fn defining_use_anchor(&self) -> DefiningAnchor { + self.defining_use_anchor + } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 96a4b76af550f..68031f4886a78 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -95,9 +95,8 @@ pub fn overlapping_impls( return None; } - let infcx = - tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build(); - let selcx = &mut SelectionContext::new(&infcx); + let infcx = tcx.infer_ctxt().intercrate().build(); + let selcx = &mut SelectionContext::new(&infcx, DefiningAnchor::Error); let overlaps = overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some(); if !overlaps { @@ -107,9 +106,8 @@ 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().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build(); - let selcx = &mut SelectionContext::new(&infcx); + let infcx = tcx.infer_ctxt().intercrate().build(); + let selcx = &mut SelectionContext::new(&infcx, DefiningAnchor::Error); selcx.enable_tracking_intercrate_ambiguity_causes(); Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap()) } @@ -129,8 +127,10 @@ fn with_fresh_ty_vars<'cx, 'tcx>( predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates, }; - let InferOk { value: mut header, obligations } = - selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(header); + let InferOk { value: mut header, obligations } = selcx + .infcx + .at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error) + .normalize(header); header.predicates.extend(obligations.into_iter().map(|o| o.predicate)); header @@ -216,8 +216,8 @@ fn equate_impl_headers<'cx, 'tcx>( debug!("equate_impl_headers(impl1_header={:?}, impl2_header={:?}", impl1_header, impl2_header); selcx .infcx - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .define_opaque_types(true) + .at(&ObligationCause::dummy(), ty::ParamEnv::empty(), DefiningAnchor::Error) + .define_opaque_types(DefiningAnchor::Bubble) .eq_impl_headers(impl1_header, impl2_header) .map(|infer_ok| infer_ok.obligations) .ok() @@ -307,7 +307,7 @@ fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> b }; // Attempt to prove that impl2 applies, given all of the above. - let selcx = &mut SelectionContext::new(&infcx); + let selcx = &mut SelectionContext::new(&infcx, DefiningAnchor::Error); let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id); let (subject2, obligations) = impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs); @@ -325,7 +325,7 @@ fn equate<'tcx>( ) -> bool { // do the impls unify? If not, not disjoint. let Ok(InferOk { obligations: more_obligations, .. }) = - infcx.at(&ObligationCause::dummy(), impl_env).eq(subject1, subject2) + infcx.at(&ObligationCause::dummy(), impl_env, DefiningAnchor::Error).eq(subject1, subject2) else { debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2); return true; @@ -378,13 +378,13 @@ fn resolve_negative_obligation<'tcx>( }; let param_env = o.param_env; - if !super::fully_solve_obligation(&infcx, o).is_empty() { + if !super::fully_solve_obligation(&infcx, o, DefiningAnchor::Error).is_empty() { return false; } let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id); let outlives_env = OutlivesEnvironment::with_bounds( param_env, diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 345e84990ed03..62ed955575bfb 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -9,7 +9,7 @@ //! `thir_abstract_const` which can then be checked for structural equality with other //! generic constants mentioned in the `caller_bounds` of the current environment. use rustc_hir::def::DefKind; -use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::{DefiningAnchor, InferCtxt}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::traits::ObligationCause; @@ -176,7 +176,7 @@ fn satisfied_from_param_env<'tcx>( fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { debug!("is_const_evaluatable: candidate={:?}", c); if self.infcx.probe(|_| { - let ocx = ObligationCtxt::new_in_snapshot(self.infcx); + let ocx = ObligationCtxt::new_in_snapshot(self.infcx, DefiningAnchor::Error); ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()).is_ok() && ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok() && ocx.select_all_or_error().is_empty() @@ -219,7 +219,7 @@ fn satisfied_from_param_env<'tcx>( } if let Some(Ok(c)) = single_match { - let ocx = ObligationCtxt::new_in_snapshot(infcx); + let ocx = ObligationCtxt::new_in_snapshot(infcx, DefiningAnchor::Error); assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok()); assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok()); assert!(ocx.select_all_or_error().is_empty()); diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 62d5e50dbc548..fb68da8314c67 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; -use rustc_infer::infer::{InferCtxt, InferOk}; +use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk}; use rustc_infer::traits::query::Fallible; use rustc_infer::traits::{ FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _, @@ -25,24 +25,34 @@ use rustc_session::config::TraitSolver; use rustc_span::Span; pub trait TraitEngineExt<'tcx> { - fn new(tcx: TyCtxt<'tcx>) -> Box; - fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box; + fn new(tcx: TyCtxt<'tcx>, defining_use_anchor: impl Into) -> Box; + fn new_in_snapshot( + tcx: TyCtxt<'tcx>, + defining_use_anchor: impl Into, + ) -> Box; } impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { - fn new(tcx: TyCtxt<'tcx>) -> Box { + fn new(tcx: TyCtxt<'tcx>, defining_use_anchor: impl Into) -> Box { 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()), + TraitSolver::Classic => Box::new(FulfillmentContext::new(defining_use_anchor)), + TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new(defining_use_anchor)), + TraitSolver::Next => Box::new(NextFulfillmentCtxt::new(defining_use_anchor)), } } - fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box { + fn new_in_snapshot( + tcx: TyCtxt<'tcx>, + defining_use_anchor: impl Into, + ) -> Box { 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()), + TraitSolver::Classic => { + Box::new(FulfillmentContext::new_in_snapshot(defining_use_anchor)) + } + TraitSolver::Chalk => { + Box::new(ChalkFulfillmentContext::new_in_snapshot(defining_use_anchor)) + } + TraitSolver::Next => Box::new(NextFulfillmentCtxt::new(defining_use_anchor)), } } } @@ -55,12 +65,24 @@ pub struct ObligationCtxt<'a, 'tcx> { } impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - Self { infcx, engine: RefCell::new(>::new(infcx.tcx)) } + pub fn new(infcx: &'a InferCtxt<'tcx>, defining_use_anchor: impl Into) -> Self { + Self { + infcx, + engine: RefCell::new(>::new(infcx.tcx, defining_use_anchor)), + } } - pub fn new_in_snapshot(infcx: &'a InferCtxt<'tcx>) -> Self { - Self { infcx, engine: RefCell::new(>::new_in_snapshot(infcx.tcx)) } + pub fn new_in_snapshot( + infcx: &'a InferCtxt<'tcx>, + defining_use_anchor: impl Into, + ) -> Self { + Self { + infcx, + engine: RefCell::new(>::new_in_snapshot( + infcx.tcx, + defining_use_anchor, + )), + } } pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) { @@ -110,7 +132,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, value: T, ) -> T { - let infer_ok = self.infcx.at(&cause, param_env).normalize(value); + let infer_ok = self.infcx.at(&cause, param_env, DefiningAnchor::Error).normalize(value); self.register_infer_ok_obligations(infer_ok) } @@ -127,8 +149,8 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { T: ToTrace<'tcx>, { self.infcx - .at(cause, param_env) - .define_opaque_types(true) + .at(cause, param_env, DefiningAnchor::Error) + .define_opaque_types(self.defining_use_anchor()) .eq_exp(a_is_expected, a, b) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -141,8 +163,8 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { actual: T, ) -> Result<(), TypeError<'tcx>> { self.infcx - .at(cause, param_env) - .define_opaque_types(true) + .at(cause, param_env, DefiningAnchor::Error) + .define_opaque_types(self.defining_use_anchor()) .eq(expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -156,8 +178,8 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { actual: T, ) -> Result<(), TypeError<'tcx>> { self.infcx - .at(cause, param_env) - .define_opaque_types(true) + .at(cause, param_env, DefiningAnchor::Error) + .define_opaque_types(self.defining_use_anchor()) .sub(expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -171,8 +193,8 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { actual: T, ) -> Result<(), TypeError<'tcx>> { self.infcx - .at(cause, param_env) - .define_opaque_types(true) + .at(cause, param_env, DefiningAnchor::Error) + .define_opaque_types(self.defining_use_anchor()) .sup(expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -229,4 +251,8 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { &mut **self.engine.borrow_mut(), ) } + + pub fn defining_use_anchor(&self) -> DefiningAnchor { + self.engine.borrow().defining_use_anchor() + } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 84045c4d0edea..ca80d50f83bc9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -1,5 +1,5 @@ use rustc_hir::def_id::DefId; -use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; +use rustc_infer::infer::{DefiningAnchor, InferCtxt, LateBoundRegionConversionTime}; use rustc_infer::traits::util::elaborate_predicates_with_span; use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation}; use rustc_middle::ty; @@ -20,7 +20,7 @@ pub fn recompute_applicable_impls<'tcx>( let param_env = obligation.param_env; let impl_may_apply = |impl_def_id| { - let ocx = ObligationCtxt::new_in_snapshot(infcx); + let ocx = ObligationCtxt::new_in_snapshot(infcx, DefiningAnchor::Error); let placeholder_obligation = infcx.instantiate_binder_with_placeholders(obligation.predicate); let obligation_trait_ref = @@ -45,7 +45,7 @@ pub fn recompute_applicable_impls<'tcx>( }; let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| { - let ocx = ObligationCtxt::new_in_snapshot(infcx); + let ocx = ObligationCtxt::new_in_snapshot(infcx, DefiningAnchor::Error); let placeholder_obligation = infcx.instantiate_binder_with_placeholders(obligation.predicate); let obligation_trait_ref = diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 41ffaeeac1c11..fe26e8f3747e9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -28,7 +28,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{GenericParam, Item, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; -use rustc_infer::infer::{InferOk, TypeTrace}; +use rustc_infer::infer::{DefiningAnchor, InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -365,7 +365,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { param_env, ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }), ); - let ocx = ObligationCtxt::new_in_snapshot(self); + let ocx = ObligationCtxt::new_in_snapshot(self, DefiningAnchor::Error); ocx.register_obligation(obligation); if ocx.select_all_or_error().is_empty() { return Ok(( @@ -1703,7 +1703,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } self.probe(|_| { - let ocx = ObligationCtxt::new_in_snapshot(self); + let ocx = ObligationCtxt::new_in_snapshot(self, DefiningAnchor::Error); // try to find the mismatched types to report the error with. // @@ -2131,7 +2131,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .map(|ImplCandidate { trait_ref, similarity }| { // FIXME(compiler-errors): This should be using `NormalizeExt::normalize` let normalized = self - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) + .at(&ObligationCause::dummy(), ty::ParamEnv::empty(), DefiningAnchor::Error) .query_normalize(trait_ref) .map_or(trait_ref, |normalized| normalized.value); (similarity, normalized) @@ -2312,7 +2312,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }; let obligation = obligation.with(self.tcx, trait_ref); - let mut selcx = SelectionContext::new(&self); + let mut selcx = SelectionContext::new(&self, DefiningAnchor::Bubble); match selcx.select_from_obligation(&obligation) { Ok(None) => { let ambiguities = @@ -2712,8 +2712,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let cleaned_pred = pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); - let InferOk { value: cleaned_pred, .. } = - self.infcx.at(&ObligationCause::dummy(), param_env).normalize(cleaned_pred); + let InferOk { value: cleaned_pred, .. } = self + .infcx + .at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error) + .normalize(cleaned_pred); let obligation = Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 11567ff39ddcb..f4173b100952a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -25,7 +25,7 @@ use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_hir::{Expr, HirId}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime}; +use rustc_infer::infer::{DefiningAnchor, InferOk, LateBoundRegionConversionTime}; use rustc_middle::hir::map; use rustc_middle::ty::error::TypeError::{self, Sorts}; use rustc_middle::ty::relate::TypeRelation; @@ -1219,7 +1219,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // implied by wf, but also because that would possibly result in // erroneous errors later on. let InferOk { value: output, obligations: _ } = - self.at(&ObligationCause::dummy(), param_env).normalize(output); + self.at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error).normalize(output); if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) } } @@ -3396,8 +3396,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { [trait_pred.self_ty()], ) }); - let InferOk { value: projection_ty, .. } = - self.at(&obligation.cause, obligation.param_env).normalize(projection_ty); + let InferOk { value: projection_ty, .. } = self + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) + .normalize(projection_ty); debug!( normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty) @@ -3778,7 +3779,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, ) -> Vec))>> { - let ocx = ObligationCtxt::new_in_snapshot(self.infcx); + let ocx = ObligationCtxt::new_in_snapshot(self.infcx, DefiningAnchor::Error); let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len()); for diff in type_diffs { let Sorts(expected_found) = diff else { continue; }; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 944436ab82f91..d10b07d4ee2c2 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -2,6 +2,7 @@ use crate::infer::{InferCtxt, TyOrConstInferVar}; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; +use rustc_infer::infer::DefiningAnchor; use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation}; use rustc_middle::mir::interpret::ErrorHandled; @@ -63,6 +64,7 @@ pub struct FulfillmentContext<'tcx> { // a snapshot (they don't *straddle* a snapshot, so there // is no trouble there). usable_in_snapshot: bool, + defining_use_anchor: DefiningAnchor, } #[derive(Clone, Debug)] @@ -81,12 +83,22 @@ static_assert_size!(PendingPredicateObligation<'_>, 72); impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. - pub(super) fn new() -> FulfillmentContext<'tcx> { - FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: false } + pub(super) fn new(defining_use_anchor: impl Into) -> FulfillmentContext<'tcx> { + FulfillmentContext { + predicates: ObligationForest::new(), + usable_in_snapshot: false, + defining_use_anchor: defining_use_anchor.into(), + } } - pub(super) fn new_in_snapshot() -> FulfillmentContext<'tcx> { - FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: true } + pub(super) fn new_in_snapshot( + defining_use_anchor: impl Into, + ) -> FulfillmentContext<'tcx> { + FulfillmentContext { + predicates: ObligationForest::new(), + usable_in_snapshot: true, + defining_use_anchor: defining_use_anchor.into(), + } } /// Attempts to select obligations using `selcx`. @@ -137,7 +149,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { } fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { - let selcx = SelectionContext::new(infcx); + let selcx = SelectionContext::new(infcx, self.defining_use_anchor); self.select(selcx) } @@ -193,6 +205,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { fn pending_obligations(&self) -> Vec> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } + + fn defining_use_anchor(&self) -> DefiningAnchor { + self.defining_use_anchor + } } struct FulfillProcessor<'a, 'tcx> { @@ -513,7 +529,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { && tcx.def_kind(a.def.did) == DefKind::AssocConst => { if let Ok(new_obligations) = infcx - .at(&obligation.cause, obligation.param_env) + .at( + &obligation.cause, + obligation.param_env, + DefiningAnchor::Error, + ) .trace(c1, c2) .eq(a.substs, b.substs) { @@ -524,8 +544,13 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } (_, Unevaluated(_)) | (Unevaluated(_), _) => (), (_, _) => { - if let Ok(new_obligations) = - infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) + if let Ok(new_obligations) = infcx + .at( + &obligation.cause, + obligation.param_env, + DefiningAnchor::Error, + ) + .eq(c1, c2) { return ProcessResult::Changed(mk_pending( new_obligations.into_obligations(), @@ -568,7 +593,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { match self .selcx .infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .eq(c1, c2) { Ok(inf_ok) => { @@ -613,7 +638,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { match self .selcx .infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .eq(ct.ty(), ty) { Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 336db4fee6ced..1c167243a7e17 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -5,7 +5,7 @@ use crate::traits::{self, ObligationCause, ObligationCtxt}; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_infer::infer::canonical::Canonical; -use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; +use rustc_infer::infer::{DefiningAnchor, RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; @@ -59,7 +59,7 @@ pub fn type_allowed_to_implement_copy<'tcx>( for field in &variant.fields { // Do this per-field to get better error messages. let infcx = tcx.infer_ctxt().build(); - let ocx = traits::ObligationCtxt::new(&infcx); + let ocx = traits::ObligationCtxt::new(&infcx, DefiningAnchor::Error); let unnormalized_ty = field.ty(tcx, substs); if unnormalized_ty.references_error() { @@ -146,7 +146,7 @@ pub fn check_tys_might_be_eq<'tcx>( ) -> Result<(), NoSolution> { let (infcx, (param_env, ty_a, ty_b), _) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); let result = ocx.eq(&ObligationCause::dummy(), param_env, ty_a, ty_b); // use `select_where_possible` instead of `select_all_or_error` so that diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index bfeda88a6d40c..78e3a98050143 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -26,6 +26,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_errors::ErrorGuaranteed; +use rustc_infer::infer::DefiningAnchor; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeSuperVisitable}; @@ -171,7 +172,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>( // The handling of regions in this area of the code is terrible, // see issue #29149. We should be able to improve on this with // NLL. - let errors = fully_solve_obligation(infcx, obligation); + let errors = fully_solve_obligation(infcx, obligation, DefiningAnchor::Error); match &errors[..] { [] => true, @@ -374,7 +375,7 @@ pub fn fully_normalize<'tcx, T>( where T: TypeFoldable>, { - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(infcx, DefiningAnchor::Error); debug!(?value); let normalized_value = ocx.normalize(&cause, param_env, value); debug!(?normalized_value); @@ -394,8 +395,9 @@ where pub fn fully_solve_obligation<'tcx>( infcx: &InferCtxt<'tcx>, obligation: PredicateObligation<'tcx>, + defining_use_anchor: DefiningAnchor, ) -> Vec> { - fully_solve_obligations(infcx, [obligation]) + fully_solve_obligations(infcx, [obligation], defining_use_anchor) } /// Process a set of obligations (and any nested obligations that come from them) @@ -403,8 +405,9 @@ pub fn fully_solve_obligation<'tcx>( pub fn fully_solve_obligations<'tcx>( infcx: &InferCtxt<'tcx>, obligations: impl IntoIterator>, + defining_use_anchor: DefiningAnchor, ) -> Vec> { - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(infcx, defining_use_anchor); ocx.register_obligations(obligations); ocx.select_all_or_error() } @@ -423,7 +426,7 @@ pub fn fully_solve_bound<'tcx>( let trait_ref = tcx.mk_trait_ref(bound, [ty]); let obligation = Obligation::new(tcx, cause, param_env, ty::Binder::dummy(trait_ref)); - fully_solve_obligation(infcx, obligation) + fully_solve_obligation(infcx, obligation, DefiningAnchor::Error) } /// Normalizes the predicates and checks whether they hold in an empty environment. If this @@ -437,7 +440,7 @@ pub fn impossible_predicates<'tcx>( let infcx = tcx.infer_ctxt().build(); let param_env = ty::ParamEnv::reveal_all(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&infcx, DefiningAnchor::Error); let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates); for predicate in predicates { let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate); diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 6cb64ad574f5b..331429a1f6a33 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { let span = self.tcx.def_span(body_id); let result = param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) - .fully_perform(self); + .fully_perform(self, rustc_infer::infer::DefiningAnchor::Error); let result = match result { Ok(r) => r, Err(NoSolution) => { @@ -83,6 +83,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { param_env, ) }), + rustc_infer::infer::DefiningAnchor::Error, ); if !constraints.member_constraints.is_empty() { span_bug!(span, "{:#?}", constraints.member_constraints); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 01075d7c55aee..2d44b843bd1fe 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -28,6 +28,7 @@ use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::at::At; use rustc_infer::infer::resolve::OpportunisticRegionResolver; +use rustc_infer::infer::DefiningAnchor; use rustc_infer::traits::ImplSourceBuiltinData; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -57,7 +58,7 @@ pub trait NormalizeExt<'tcx> { impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { fn normalize>>(&self, value: T) -> InferOk<'tcx, T> { - let mut selcx = SelectionContext::new(self.infcx); + let mut selcx = SelectionContext::new(self.infcx, DefiningAnchor::Error); let Normalized { value, obligations } = normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); InferOk { value, obligations } @@ -282,13 +283,13 @@ fn project_and_unify_type<'cx, 'tcx>( obligation.cause.body_id, obligation.cause.span, obligation.param_env, + selcx.defining_use_anchor(), ); obligations.extend(new); match infcx - .at(&obligation.cause, obligation.param_env) - // This is needed to support nested opaque types like `impl Fn() -> impl Trait` - .define_opaque_types(true) + // This anchor is needed to support nested opaque types like `impl Fn() -> impl Trait` + .at(&obligation.cause, obligation.param_env, selcx.defining_use_anchor()) .eq(normalized, actual) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { @@ -2064,7 +2065,10 @@ fn confirm_param_env_candidate<'cx, 'tcx>( debug!(?cache_projection, ?obligation_projection); - match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) { + match infcx + .at(cause, param_env, DefiningAnchor::Error) + .eq(cache_projection, obligation_projection) + { Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index f84b2f4428d1a..1c3920d48824c 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -1,3 +1,4 @@ +use rustc_infer::infer::DefiningAnchor; use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause}; use rustc_middle::ty; @@ -126,7 +127,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { match self.evaluate_obligation(obligation) { Ok(result) => result, Err(OverflowError::Canonical) => { - let mut selcx = SelectionContext::new(&self); + let mut selcx = SelectionContext::new(&self, DefiningAnchor::Error); selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| match r { OverflowError::Canonical => { span_bug!( diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index b0cec3ce7a3ea..acb0adba94395 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -10,6 +10,7 @@ use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderR use crate::traits::{ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_infer::infer::DefiningAnchor; use rustc_infer::traits::Normalized; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; @@ -72,6 +73,7 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { cache: SsoHashMap::new(), anon_depth: 0, universes: vec![], + defining_use_anchor: self.define_opaque_types, }; // This is actually a consequence by the way `normalize_erasing_regions` works currently. @@ -168,6 +170,7 @@ struct QueryNormalizer<'cx, 'tcx> { cache: SsoHashMap, Ty<'tcx>>, anon_depth: usize, universes: Vec>, + defining_use_anchor: DefiningAnchor, } impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> { @@ -282,6 +285,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> self.param_env, &orig_values, result, + self.defining_use_anchor, )?; debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); @@ -333,6 +337,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> self.param_env, &orig_values, result, + self.defining_use_anchor, )?; debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 6bf3ed0d0e29a..ffbf04afd8529 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -4,6 +4,7 @@ use crate::traits; use crate::traits::query::type_op::TypeOpOutput; use crate::traits::query::Fallible; use rustc_infer::infer::region_constraints::RegionConstraintData; +use rustc_infer::infer::DefiningAnchor; use rustc_span::source_map::DUMMY_SP; use std::fmt; @@ -36,12 +37,16 @@ where /// Processes the operation and all resulting obligations, /// returning the final result along with any region constraints /// (they will be given over to the NLL region solver). - fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible> { + fn fully_perform( + self, + infcx: &InferCtxt<'tcx>, + defining_use_anchor: DefiningAnchor, + ) -> Fallible> { if cfg!(debug_assertions) { info!("fully_perform({:?})", self); } - Ok(scrape_region_constraints(infcx, || (self.closure)(infcx))?.0) + Ok(scrape_region_constraints(infcx, defining_use_anchor, || (self.closure)(infcx))?.0) } } @@ -58,6 +63,7 @@ where /// constraints that result, creating query-region-constraints. pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( infcx: &InferCtxt<'tcx>, + defining_use_anchor: DefiningAnchor, op: impl FnOnce() -> Fallible>, ) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> { // During NLL, we expect that nobody will register region @@ -73,7 +79,7 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( ); let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?; - let errors = traits::fully_solve_obligations(infcx, obligations); + let errors = traits::fully_solve_obligations(infcx, obligations, defining_use_anchor); if !errors.is_empty() { infcx.tcx.sess.diagnostic().delay_span_bug( DUMMY_SP, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index 9e8bc8bce9a8f..b5a6bf4b139fc 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -5,6 +5,7 @@ use crate::infer::{InferCtxt, InferOk}; use crate::traits::query::Fallible; use crate::traits::ObligationCause; use rustc_infer::infer::canonical::Certainty; +use rustc_infer::infer::DefiningAnchor; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::PredicateObligations; use rustc_middle::ty::fold::TypeFoldable; @@ -32,7 +33,11 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug { /// Processes the operation and all resulting obligations, /// returning the final result along with any region constraints /// (they will be given over to the NLL region solver). - fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible>; + fn fully_perform( + self, + infcx: &InferCtxt<'tcx>, + defining_use_anchor: DefiningAnchor, + ) -> Fallible>; } /// The output from performing a type op @@ -80,6 +85,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 't query_key: ParamEnvAnd<'tcx, Self>, infcx: &InferCtxt<'tcx>, output_query_region_constraints: &mut QueryRegionConstraints<'tcx>, + defining_use_anchor: DefiningAnchor, ) -> Fallible<( Self::QueryResponse, Option>>, @@ -107,6 +113,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 't &canonical_var_values, canonical_result, output_query_region_constraints, + defining_use_anchor, )?; Ok((value, Some(canonical_self), obligations, canonical_result.value.certainty)) @@ -120,10 +127,14 @@ where type Output = Q::QueryResponse; type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>; - fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible> { + fn fully_perform( + self, + infcx: &InferCtxt<'tcx>, + defining_use_anchor: DefiningAnchor, + ) -> Fallible> { let mut region_constraints = QueryRegionConstraints::default(); let (output, error_info, mut obligations, _) = - Q::fully_perform_into(self, infcx, &mut region_constraints)?; + Q::fully_perform_into(self, infcx, &mut region_constraints, defining_use_anchor)?; // Typically, instantiating NLL query results does not // create obligations. However, in some cases there @@ -139,6 +150,7 @@ where obligation.param_env.and(ProvePredicate::new(obligation.predicate)), infcx, &mut region_constraints, + defining_use_anchor, ) { Ok(((), _, new, certainty)) => { obligations.extend(new); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ee41d840bae92..31337f0086c6e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,8 +8,8 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; +use rustc_infer::infer::{DefiningAnchor, InferOk}; use rustc_middle::ty::{ self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt, @@ -176,7 +176,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .sup(placeholder_trait_predicate, candidate) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) @@ -461,7 +461,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested.extend(self.infcx.commit_if_ok(|_| { self.infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .sup(obligation_trait_ref, upcast_trait_ref) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) @@ -828,9 +828,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); self.infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs - .define_opaque_types(true) + .define_opaque_types(self.defining_use_anchor()) .sup(obligation_trait_ref, expected_trait_ref) .map(|InferOk { mut obligations, .. }| { obligations.extend(nested); @@ -895,7 +895,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // only the **lifetime bound** is changed. let InferOk { obligations, .. } = self .infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .sup(target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -994,7 +994,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // only the **lifetime bound** is changed. let InferOk { obligations, .. } = self .infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .sup(target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -1065,7 +1065,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (&ty::Array(a, _), &ty::Slice(b)) => { let InferOk { obligations, .. } = self .infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .eq(b, a) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -1113,7 +1113,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let new_struct = tcx.mk_adt(def, substs); let InferOk { obligations, .. } = self .infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .eq(target, new_struct) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -1143,7 +1143,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tcx.mk_tup_from_iter(a_mid.iter().copied().chain(iter::once(b_last))); let InferOk { obligations, .. } = self .infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .eq(target, new_tuple) .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 38cdaddc1e707..e255e04cdbf5b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -38,6 +38,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::DefiningAnchor; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::traits::TraitEngine; use rustc_infer::traits::TraitEngineExt; @@ -126,6 +127,8 @@ pub struct SelectionContext<'cx, 'tcx> { /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. query_mode: TraitQueryMode, + + defining_use_anchor: DefiningAnchor, } // A stack that walks back up the stack frame. @@ -207,21 +210,26 @@ enum BuiltinImplConditions<'tcx> { } impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { - pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> { + pub fn new( + infcx: &'cx InferCtxt<'tcx>, + defining_use_anchor: impl Into, + ) -> SelectionContext<'cx, 'tcx> { SelectionContext { infcx, freshener: infcx.freshener_keep_static(), intercrate_ambiguity_causes: None, query_mode: TraitQueryMode::Standard, + defining_use_anchor: defining_use_anchor.into(), } } - pub fn with_query_mode( - infcx: &'cx InferCtxt<'tcx>, - query_mode: TraitQueryMode, - ) -> SelectionContext<'cx, 'tcx> { - debug!(?query_mode, "with_query_mode"); - SelectionContext { query_mode, ..SelectionContext::new(infcx) } + pub fn new_in_canonical_query(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> { + SelectionContext { + query_mode: TraitQueryMode::Canonical, + // This bubble is required for this tests to pass: + // impl-trait/issue99642.rs + ..SelectionContext::new(infcx, DefiningAnchor::Bubble) + } } /// Enables tracking of intercrate ambiguity causes. See @@ -613,7 +621,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, predicates: impl IntoIterator>, ) -> Result { - let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(); + let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(DefiningAnchor::Bubble); fulfill_cx.register_predicate_obligations(self.infcx, predicates); // True errors if !fulfill_cx.select_where_possible(self.infcx).is_empty() { @@ -910,7 +918,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { if let Ok(new_obligations) = self .infcx - .at(&obligation.cause, obligation.param_env) + .at( + &obligation.cause, + obligation.param_env, + DefiningAnchor::Error, + ) .trace(c1, c2) .eq(a.substs, b.substs) { @@ -929,7 +941,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (_, _) => { if let Ok(new_obligations) = self .infcx - .at(&obligation.cause, obligation.param_env) + .at( + &obligation.cause, + obligation.param_env, + DefiningAnchor::Error, + ) .eq(c1, c2) { let mut obligations = new_obligations.obligations; @@ -964,7 +980,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match self.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) + match self + .infcx + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) + .eq(c1, c2) { Ok(inf_ok) => self.evaluate_predicates_recursively( previous_stack, @@ -993,7 +1012,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { - match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) { + match self + .infcx + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) + .eq(ct.ty(), ty) + { Ok(inf_ok) => self.evaluate_predicates_recursively( previous_stack, inf_ok.into_obligations(), @@ -1750,7 +1773,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); self.infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .map(|InferOk { obligations: _, value: () }| { // This method is called within a probe, so we can't have @@ -1812,7 +1835,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let is_match = self .infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .sup(obligation.predicate, infer_projection) .map_or(false, |InferOk { obligations, value: () }| { self.evaluate_predicates_recursively( @@ -2533,7 +2556,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let InferOk { obligations, .. } = self .infcx - .at(&cause, obligation.param_env) + .at(&cause, obligation.param_env, DefiningAnchor::Error) .eq(placeholder_obligation_trait_ref, impl_trait_ref) .map_err(|e| { debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx())) @@ -2583,7 +2606,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result>, ()> { self.infcx - .at(&obligation.cause, obligation.param_env) + .at(&obligation.cause, obligation.param_env, DefiningAnchor::Error) .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| ()) @@ -2706,6 +2729,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligations } + + pub fn defining_use_anchor(&self) -> DefiningAnchor { + self.defining_use_anchor + } } impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index fcfb60b26030f..4c5b6c96a6858 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -10,6 +10,7 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html pub mod specialization_graph; +use rustc_infer::infer::DefiningAnchor; use specialization_graph::GraphExt; use crate::errors::NegativePositiveConflict; @@ -186,14 +187,14 @@ fn fulfill_implication<'tcx>( let source_trait = ImplSubject::Trait(source_trait_ref); - let selcx = &mut SelectionContext::new(&infcx); + let selcx = &mut SelectionContext::new(&infcx, DefiningAnchor::Error); let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); let (target_trait, obligations) = util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs); // do the impls unify? If not, no specialization. let Ok(InferOk { obligations: more_obligations, .. }) = - infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait, target_trait) + infcx.at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error).eq(source_trait, target_trait) else { debug!( "fulfill_implication: {:?} does not unify with {:?}", @@ -204,7 +205,7 @@ fn fulfill_implication<'tcx>( // Needs to be `in_snapshot` because this function is used to rebase // substitutions, which may happen inside of a select within a probe. - let ocx = ObligationCtxt::new_in_snapshot(infcx); + let ocx = ObligationCtxt::new_in_snapshot(infcx, DefiningAnchor::Error); // attempt to prove all of the predicates for impl2 given those for impl1 // (which are packed up in penv) ocx.register_obligations(obligations.chain(more_obligations)); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index bcf63d5a6f628..666d07003fd2a 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::{GenericArg, SubstsRef}; use super::NormalizeExt; use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext}; -use rustc_infer::infer::InferOk; +use rustc_infer::infer::{DefiningAnchor, InferOk}; pub use rustc_infer::traits::{self, util::*}; /////////////////////////////////////////////////////////////////////////// @@ -201,13 +201,17 @@ pub fn impl_subject_and_oblig<'a, 'tcx>( ) -> (ImplSubject<'tcx>, impl Iterator>) { let subject = selcx.tcx().bound_impl_subject(impl_def_id); let subject = subject.subst(selcx.tcx(), impl_substs); - let InferOk { value: subject, obligations: normalization_obligations1 } = - selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(subject); + let InferOk { value: subject, obligations: normalization_obligations1 } = selcx + .infcx + .at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error) + .normalize(subject); let predicates = selcx.tcx().predicates_of(impl_def_id); let predicates = predicates.instantiate(selcx.tcx(), impl_substs); - let InferOk { value: predicates, obligations: normalization_obligations2 } = - selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(predicates); + let InferOk { value: predicates, obligations: normalization_obligations2 } = selcx + .infcx + .at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error) + .normalize(predicates); let impl_obligations = super::predicates_for_generics(|_, _| ObligationCause::dummy(), param_env, predicates); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d498af359c584..0cc7385c2ead7 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -2,6 +2,7 @@ use crate::infer::InferCtxt; use crate::traits; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; +use rustc_infer::infer::DefiningAnchor; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; @@ -314,7 +315,7 @@ impl<'tcx> WfPredicates<'tcx> { let mut obligations = Vec::with_capacity(self.out.len()); for mut obligation in self.out { assert!(!obligation.has_escaping_bound_vars()); - let mut selcx = traits::SelectionContext::new(infcx); + let mut selcx = traits::SelectionContext::new(infcx, DefiningAnchor::Error); // Don't normalize the whole obligation, the param env is either // already normalized, or we're currently normalizing the // param_env. Either way we should only normalize the predicate. diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 6f81d343e0fd8..2743e85cfcfc0 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -29,14 +29,10 @@ pub fn codegen_select_candidate<'tcx>( // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - let infcx = tcx - .infer_ctxt() - .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::Bubble) - .build(); - //~^ HACK `Bubble` is required for + let infcx = tcx.infer_ctxt().ignoring_regions().build(); + // HACK `Bubble` is required for // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs - let mut selcx = SelectionContext::new(&infcx); + let mut selcx = SelectionContext::new(&infcx, DefiningAnchor::Bubble); let obligation_cause = ObligationCause::dummy(); let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref); @@ -55,7 +51,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 = >::new(tcx); + let mut fulfill_cx = >::new(tcx, DefiningAnchor::Bubble); let impl_source = selection.map(|predicate| { fulfill_cx.register_predicate_obligation(&infcx, predicate); }); diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index b5924e949146b..3c3e0b8e94c77 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -1,7 +1,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt}; @@ -100,7 +100,7 @@ fn dropck_outlives<'tcx>( // to push them onto the stack to be expanded. for ty in constraints.dtorck_types.drain(..) { let Normalized { value: ty, obligations } = - ocx.infcx.at(&cause, param_env).query_normalize(ty)?; + ocx.infcx.at(&cause, param_env, DefiningAnchor::Error).query_normalize(ty)?; ocx.register_obligations(obligations); debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index e94c8efe69a92..f02e93e67530b 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -1,10 +1,10 @@ -use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_span::source_map::DUMMY_SP; use rustc_trait_selection::traits::query::CanonicalPredicateGoal; use rustc_trait_selection::traits::{ - EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, + EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, }; pub(crate) fn provide(p: &mut Providers) { @@ -16,16 +16,12 @@ fn evaluate_obligation<'tcx>( canonical_goal: CanonicalPredicateGoal<'tcx>, ) -> Result { debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal); - // HACK This bubble is required for this tests to pass: - // impl-trait/issue99642.rs - let (ref infcx, goal, _canonical_inference_vars) = tcx - .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::Bubble) - .build_with_canonical(DUMMY_SP, &canonical_goal); + let (ref infcx, goal, _canonical_inference_vars) = + tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal); debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate } = goal; - let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical); + let mut selcx = SelectionContext::new_in_canonical_query(&infcx); let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate); selcx.evaluate_root_obligation(&obligation) diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index f0597f19225c8..94fab0a334ea8 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -1,4 +1,4 @@ -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt}; @@ -29,7 +29,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par let ParamEnvAnd { param_env, value } = goal; let infcx = tcx.infer_ctxt().build(); let cause = ObligationCause::dummy(); - match infcx.at(&cause, param_env).query_normalize(value) { + match infcx.at(&cause, param_env, DefiningAnchor::Error).query_normalize(value) { Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => { // We don't care about the `obligations`; they are // always only region relations, and we are about to diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index e805eb4282119..7334f0c19face 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -1,5 +1,5 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_trait_selection::infer::InferCtxtBuilderExt; @@ -23,7 +23,7 @@ fn normalize_projection_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, |ocx, ParamEnvAnd { param_env, value: goal }| { - let selcx = &mut SelectionContext::new(ocx.infcx); + let selcx = &mut SelectionContext::new(ocx.infcx, DefiningAnchor::Error); let cause = ObligationCause::dummy(); let mut obligations = vec![]; let answer = traits::normalize_projection_type( diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index e0fd487b3d37f..98f485961bc07 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -164,8 +164,10 @@ where T: fmt::Debug + TypeFoldable> + Lift<'tcx>, { let (param_env, Normalize { value }) = key.into_parts(); - let Normalized { value, obligations } = - ocx.infcx.at(&ObligationCause::dummy(), param_env).query_normalize(value)?; + let Normalized { value, obligations } = ocx + .infcx + .at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error) + .query_normalize(value)?; ocx.register_obligations(obligations); Ok(value) } @@ -212,15 +214,10 @@ fn type_op_prove_predicate<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - // HACK This bubble is required for this test to pass: - // impl-trait/issue-99642.rs - tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter_canonical_trait_query( - &canonicalized, - |ocx, key| { - type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy()); - Ok(()) - }, - ) + tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { + type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy()); + Ok(()) + }) } /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors, diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs index a55bb7e7e904d..4944ce6be48e1 100644 --- a/compiler/rustc_ty_utils/src/structural_match.rs +++ b/compiler/rustc_ty_utils/src/structural_match.rs @@ -2,7 +2,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; /// This method returns true if and only if `adt_ty` itself has been marked as @@ -16,7 +16,7 @@ fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool { let ref infcx = tcx.infer_ctxt().build(); let cause = ObligationCause::dummy(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(infcx, DefiningAnchor::Error); // require `#[derive(PartialEq)]` let structural_peq_def_id = infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span)); diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index bcdbbcacc4bcd..ebe73363eb418 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -48,9 +48,9 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { // Require the type the impl is implemented on to match // our type, and ignore the impl if there was a mismatch. let cause = traits::ObligationCause::dummy(); - let Ok(eq_result) = infcx.at(&cause, param_env).eq(impl_trait_ref.self_ty(), impl_ty) else { - continue - }; + let Ok(eq_result) = infcx.at(&cause, param_env, DefiningAnchor::Error).eq(impl_trait_ref.self_ty(), impl_ty) else { + continue + }; let InferOk { value: (), obligations } = eq_result; // FIXME(eddyb) ignoring `obligations` might cause false positives. drop(obligations); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 29c3afe0d9560..eaa7e6a68766a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -21,6 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::PredicateOrigin; use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; +use rustc_infer::infer::DefiningAnchor; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::InternalSubsts; @@ -1682,7 +1683,7 @@ fn normalize<'tcx>( // Try to normalize `::T` to a type let infcx = cx.tcx.infer_ctxt().build(); let normalized = infcx - .at(&ObligationCause::dummy(), cx.param_env) + .at(&ObligationCause::dummy(), cx.param_env, DefiningAnchor::Error) .query_normalize(ty) .map(|resolved| infcx.resolve_vars_if_possible(resolved.value)); match normalized { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index e0ea3952785bb..0d692d9e914e9 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety}; use rustc_infer::infer::{ type_variable::{TypeVariableOrigin, TypeVariableOriginKind}, - TyCtxtInferExt, + TyCtxtInferExt, DefiningAnchor, }; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; @@ -312,7 +312,7 @@ fn is_normalizable_helper<'tcx>( cache.insert(ty, false); let infcx = cx.tcx.infer_ctxt().build(); let cause = rustc_middle::traits::ObligationCause::dummy(); - let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() { + let result = if infcx.at(&cause, param_env, DefiningAnchor::Error).query_normalize(ty).is_ok() { match ty.kind() { ty::Adt(def, substs) => def.variants().iter().all(|variant| { variant diff --git a/tests/ui/impl-trait/issues/issue-70877.stderr b/tests/ui/impl-trait/issues/issue-70877.stderr index 8813bff3c353e..a15d0d7ec0cd3 100644 --- a/tests/ui/impl-trait/issues/issue-70877.stderr +++ b/tests/ui/impl-trait/issues/issue-70877.stderr @@ -1,19 +1,16 @@ -error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/issue-70877.rs:31:12 +error[E0282]: type annotations needed + --> $DIR/issue-70877.rs:30:9 | +LL | let func = bar.next().unwrap(); + | ^^^^ LL | return func(&"oof"); - | ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope + | ------------ type must be known at this point | -note: opaque type whose hidden type is being assigned - --> $DIR/issue-70877.rs:28:13 +help: consider giving `func` an explicit type | -LL | fn oof() -> impl std::fmt::Debug { - | ^^^^^^^^^^^^^^^^^^^^ -note: opaque type being used as hidden type - --> $DIR/issue-70877.rs:4:15 - | -LL | type FooRet = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ +LL | let func: /* Type */ = bar.next().unwrap(); + | ++++++++++++ error: aborting due to previous error +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr index 0a34e8486a551..00c682b21939c 100644 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr @@ -1,11 +1,8 @@ -error[E0275]: overflow evaluating the requirement `Foo: Sized` +error[E0275]: overflow evaluating the requirement ` Foo {foo} as FnOnce<()>>::Output == fn() -> Foo {foo}` --> $DIR/issue-53398-cyclic-types.rs:5:13 | LL | fn foo() -> Foo { | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`) - = note: required because it appears within the type `fn() -> Foo {foo}` error: aborting due to previous error From c8731e2c477c4b420361763ebdbc71021b57b581 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 14 Mar 2023 11:35:47 +0100 Subject: [PATCH 2/4] nll --- compiler/rustc_borrowck/src/consumers.rs | 6 ++---- compiler/rustc_borrowck/src/lib.rs | 15 ++------------- compiler/rustc_borrowck/src/nll.rs | 3 --- .../rustc_borrowck/src/type_check/canonical.rs | 2 +- .../src/type_check/liveness/trace.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 9 ++++----- .../rustc_borrowck/src/type_check/relate_tys.rs | 2 +- 7 files changed, 11 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index bee58e4ad9e88..36e17cc193419 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_index::vec::IndexVec; -use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::Body; use rustc_middle::ty::{self, TyCtxt}; @@ -36,7 +36,5 @@ pub fn get_body_with_borrowck_facts( let infcx = tcx.infer_ctxt().build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); - *super::do_mir_borrowck(&infcx, input_body, promoted, true, DefiningAnchor::Bind(def.did)) - .1 - .unwrap() + *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap() } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index fe3a2c77c9354..1aaefbdc6a614 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -26,7 +26,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::ChunkedBitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::{ - DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, + InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, }; use rustc_macros::fluent_messages; use rustc_middle::mir::{ @@ -149,19 +149,10 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> &Bor return tcx.arena.alloc(result); } - let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner; - let infcx = tcx.infer_ctxt().build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); - let opt_closure_req = do_mir_borrowck( - &infcx, - input_body, - promoted, - false, - DefiningAnchor::Bind(hir_owner.def_id), - ) - .0; + let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0; debug!("mir_borrowck done"); tcx.arena.alloc(opt_closure_req) @@ -178,7 +169,6 @@ fn do_mir_borrowck<'tcx>( input_body: &Body<'tcx>, input_promoted: &IndexVec>, return_body_with_facts: bool, - defining_use_anchor: DefiningAnchor, ) -> (BorrowCheckResult<'tcx>, Option>>) { let def = input_body.source.with_opt_param().as_local().unwrap(); debug!(?def); @@ -281,7 +271,6 @@ fn do_mir_borrowck<'tcx>( &borrow_set, &upvars, use_polonius, - defining_use_anchor, ); // Dump MIR results into a file, if that is enabled. This let us diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 5028984dc6592..96228338a4c22 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -5,7 +5,6 @@ use rustc_data_structures::vec_map::VecMap; use rustc_hir::def_id::LocalDefId; use rustc_index::vec::IndexVec; -use rustc_infer::infer::DefiningAnchor; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, @@ -167,7 +166,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( borrow_set: &BorrowSet<'tcx>, upvars: &[Upvar<'tcx>], use_polonius: bool, - defining_use_anchor: DefiningAnchor, ) -> NllOutput<'tcx> { let mut all_facts = (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default()); @@ -192,7 +190,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( elements, upvars, use_polonius, - defining_use_anchor, ); if let Some(all_facts) = &mut all_facts { diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 459d4eb0a147b..7983a8305d118 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let old_universe = self.infcx.universe(); let TypeOpOutput { output, constraints, error_info } = - op.fully_perform(self.infcx, self.defining_use_anchor)?; + op.fully_perform(self.infcx, self.defining_use_anchor())?; debug!(?output, ?constraints); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index dd4123b8977d7..0ab714c75e5d5 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -571,7 +571,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { let param_env = typeck.param_env; let TypeOpOutput { output, constraints, .. } = param_env .and(DropckOutlives::new(dropped_ty)) - .fully_perform(typeck.infcx, typeck.defining_use_anchor) + .fully_perform(typeck.infcx, typeck.defining_use_anchor()) .unwrap(); DropData { dropck_result: output, region_constraint_data: constraints } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8b3cd0d5cc17d..566cf4f73f561 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -137,7 +137,6 @@ pub(crate) fn type_check<'mir, 'tcx>( elements: &Rc, upvars: &[Upvar<'tcx>], use_polonius: bool, - defining_use_anchor: DefiningAnchor, ) -> MirTypeckResults<'tcx> { let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body); let mut constraints = MirTypeckRegionConstraints { @@ -184,7 +183,6 @@ pub(crate) fn type_check<'mir, 'tcx>( ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, - defining_use_anchor, ); let errors_reported = { @@ -882,7 +880,6 @@ struct TypeChecker<'a, 'tcx> { implicit_region_bound: ty::Region<'tcx>, reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, - defining_use_anchor: DefiningAnchor, } struct BorrowCheckContext<'a, 'tcx> { @@ -1031,7 +1028,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, - defining_use_anchor: DefiningAnchor, ) -> Self { let mut checker = Self { infcx, @@ -1043,7 +1039,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { implicit_region_bound, borrowck_context, reported_errors: Default::default(), - defining_use_anchor, }; checker.check_user_type_annotations(); checker @@ -1053,6 +1048,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.body } + fn defining_use_anchor(&self) -> DefiningAnchor { + DefiningAnchor::Bind(self.body.source.def_id().expect_local()) + } + fn unsized_feature_enabled(&self) -> bool { let features = self.tcx().features(); features.unsized_locals || features.unsized_fn_params diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 30803e6fd8e91..16a4838ff37d9 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -88,7 +88,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> } fn defining_use_anchor(&self) -> rustc_infer::infer::DefiningAnchor { - self.type_checker.defining_use_anchor + self.type_checker.defining_use_anchor() } fn param_env(&self) -> ty::ParamEnv<'tcx> { From d6f578c7b21d55b8876fd0b84deb1668769eebab Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 14 Mar 2023 11:58:45 +0100 Subject: [PATCH 3/4] w --- .../src/type_check/free_region_relations.rs | 6 +++--- .../src/transform/check_consts/qualifs.rs | 2 +- compiler/rustc_hir_analysis/src/hir_wf_check.rs | 4 ++-- compiler/rustc_hir_analysis/src/lib.rs | 8 +++----- .../src/traits/outlives_bounds.rs | 5 +++-- tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr | 12 ++++-------- .../impl-trait/impl-fn-predefined-lifetimes.stderr | 14 +------------- 7 files changed, 17 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 957857dd00f91..72736be1d1bfe 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -1,7 +1,7 @@ use rustc_data_structures::frozen::Frozen; use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder}; use rustc_infer::infer::canonical::QueryRegionConstraints; -use rustc_infer::infer::outlives; +use rustc_infer::infer::{outlives, DefiningAnchor}; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::InferCtxt; @@ -243,7 +243,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) - .fully_perform(self.infcx, rustc_infer::infer::DefiningAnchor::Error) + .fully_perform(self.infcx, DefiningAnchor::Error) .unwrap_or_else(|_| { let guar = self .infcx @@ -324,7 +324,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let TypeOpOutput { output: bounds, constraints, .. } = self .param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) - .fully_perform(self.infcx, rustc_infer::infer::DefiningAnchor::Error) + .fully_perform(self.infcx, DefiningAnchor::Error) .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty)); debug!(?bounds, ?constraints); self.add_outlives_bounds(bounds); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index f24887bfc912c..1c9569fe20501 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -187,7 +187,7 @@ impl Qualif for NeedsNonConstDrop { !traits::fully_solve_obligations( &infcx, impl_src.nested_obligations(), - rustc_infer::infer::DefiningAnchor::Error, + DefiningAnchor::Error, ) .is_empty() } diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index da9a7a674e17f..68584b3f3ab7f 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -2,7 +2,7 @@ use crate::collect::ItemCtxt; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ForeignItem, ForeignItemKind}; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{TyCtxtInferExt, DefiningAnchor}; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder}; @@ -80,7 +80,7 @@ fn diagnostic_hir_wf_check<'tcx>( self.param_env, ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())), ), - rustc_infer::infer::DefiningAnchor::Error, + DefiningAnchor::Error, ); if !errors.is_empty() { debug!("Wf-check got errors for {:?}: {:?}", ty, errors); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 37e1eb89ff944..64cec4428c49b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -166,11 +166,9 @@ fn require_same_types<'tcx>( let infcx = &tcx.infer_ctxt().build(); let param_env = ty::ParamEnv::empty(); let errors = match infcx.at(cause, param_env, DefiningAnchor::Error).eq(expected, actual) { - Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations( - infcx, - obligations, - rustc_infer::infer::DefiningAnchor::Error, - ), + Ok(InferOk { obligations, .. }) => { + traits::fully_solve_obligations(infcx, obligations, DefiningAnchor::Error) + } Err(err) => { infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit(); return false; diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 331429a1f6a33..59fe8c091998a 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -3,6 +3,7 @@ use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput}; use crate::traits::query::NoSolution; use crate::traits::ObligationCause; use rustc_data_structures::fx::FxIndexSet; +use rustc_infer::infer::DefiningAnchor; use rustc_middle::ty::{self, ParamEnv, Ty}; use rustc_span::def_id::LocalDefId; @@ -55,7 +56,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { let span = self.tcx.def_span(body_id); let result = param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) - .fully_perform(self, rustc_infer::infer::DefiningAnchor::Error); + .fully_perform(self, DefiningAnchor::Error); let result = match result { Ok(r) => r, Err(NoSolution) => { @@ -83,7 +84,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { param_env, ) }), - rustc_infer::infer::DefiningAnchor::Error, + DefiningAnchor::Error, ); if !constraints.member_constraints.is_empty() { span_bug!(span, "{:#?}", constraints.member_constraints); diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr index d56e1273f2410..d3092763076cd 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -1,13 +1,9 @@ -error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds - --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9 +error[E0720]: cannot resolve opaque type + --> $DIR/impl-fn-hrtb-bounds-2.rs:4:27 | LL | fn a() -> impl Fn(&u8) -> impl Debug { - | ---------- opaque type defined here -LL | |x| x - | --- ^ - | | - | hidden type `&u8` captures the anonymous lifetime #1 defined here + | ^^^^^^^^^^ cannot resolve opaque type error: aborting due to previous error -For more information about this error, try `rustc --explain E0700`. +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index c19420bbb0ceb..d3de0528923b3 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -1,21 +1,9 @@ -error: concrete type differs from previous defining opaque type use - --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 - | -LL | |x| x - | ^ expected `impl Debug + '_`, got `&u8` - | -note: previous use here - --> $DIR/impl-fn-predefined-lifetimes.rs:7:5 - | -LL | |x| x - | ^^^^^ - error[E0720]: cannot resolve opaque type --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | ^^^^^^^^^^^^^^^ cannot resolve opaque type -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0720`. From 3cf06373fcb66c634eccfd5677f44ce2711336cd Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 14 Mar 2023 12:56:55 +0100 Subject: [PATCH 4/4] w --- compiler/rustc_borrowck/src/type_check/relate_tys.rs | 4 ++-- compiler/rustc_hir_analysis/src/coherence/builtin.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 16a4838ff37d9..b606d8a3d35c5 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,5 +1,5 @@ use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; -use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_infer::infer::{NllRegionVariableOrigin, DefiningAnchor}; use rustc_infer::traits::PredicateObligations; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::relate::TypeRelation; @@ -87,7 +87,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> self.locations.span(self.type_checker.body) } - fn defining_use_anchor(&self) -> rustc_infer::infer::DefiningAnchor { + fn defining_use_anchor(&self) -> DefiningAnchor { self.type_checker.defining_use_anchor() } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 4ccd003bc25a0..67e7ade0b555b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{self, RegionResolutionError}; +use rustc_infer::infer::{self, RegionResolutionError, DefiningAnchor}; use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; @@ -346,7 +346,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef [field.ty(tcx, substs_a), field.ty(tcx, substs_b)], ) }), - infer::DefiningAnchor::Error, + DefiningAnchor::Error, ); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors); @@ -587,7 +587,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn let cause = traits::ObligationCause::misc(span, impl_did); let predicate = predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]); - let errors = traits::fully_solve_obligation(&infcx, predicate, infer::DefiningAnchor::Error); + let errors = traits::fully_solve_obligation(&infcx, predicate, DefiningAnchor::Error); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors); }