From b2c1919a3d1f0e77a64168c079caaa9610316f02 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 29 Jul 2021 15:59:59 +0000 Subject: [PATCH] Store the `DefId` of the currently typechecked item in `InferCtxt` This allows opaque type inference to check for defining uses without having to pass down that def id via function arguments to every method that could possibly cause an opaque type to be compared with a concrete type --- compiler/rustc_infer/src/infer/mod.rs | 23 +++++++++++++++++-- compiler/rustc_mir/src/borrow_check/mod.rs | 2 +- .../src/borrow_check/type_check/mod.rs | 1 - .../rustc_trait_selection/src/opaque_types.rs | 23 ++++++------------- compiler/rustc_typeck/src/check/_match.rs | 4 ++-- compiler/rustc_typeck/src/check/check.rs | 4 ++-- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 9 +------- 7 files changed, 34 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 62bfe03427e1c..e3836f667a9e9 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -9,6 +9,7 @@ pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine}; +use hir::def_id::CRATE_DEF_ID; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; @@ -292,6 +293,10 @@ impl<'tcx> InferCtxtInner<'tcx> { pub struct InferCtxt<'a, '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. + pub defining_use_anchor: LocalDefId, + /// During type-checking/inference of a body, `in_progress_typeck_results` /// contains a reference to the typeck results being built up, which are /// used for reading closure kinds/signatures as they are inferred, @@ -550,6 +555,7 @@ impl<'tcx> fmt::Display for FixupError<'tcx> { pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, fresh_typeck_results: Option>>, + defining_use_anchor: LocalDefId, } pub trait TyCtxtInferExt<'tcx> { @@ -558,15 +564,27 @@ pub trait TyCtxtInferExt<'tcx> { impl TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { - InferCtxtBuilder { tcx: self, fresh_typeck_results: None } + InferCtxtBuilder { + tcx: self, + defining_use_anchor: CRATE_DEF_ID, + fresh_typeck_results: None, + } } } impl<'tcx> InferCtxtBuilder<'tcx> { /// Used only by `rustc_typeck` during body type-checking/inference, /// will initialize `in_progress_typeck_results` with fresh `TypeckResults`. + /// Will also change the scope for opaque type defining use checks to the given owner. pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self { self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner))); + self.with_opaque_type_inference(table_owner) + } + + /// 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. + pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) -> Self { + self.defining_use_anchor = defining_use_anchor; self } @@ -594,10 +612,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn enter(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R { - let InferCtxtBuilder { tcx, ref fresh_typeck_results } = *self; + let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self; let in_progress_typeck_results = fresh_typeck_results.as_ref(); f(InferCtxt { tcx, + defining_use_anchor, in_progress_typeck_results, inner: RefCell::new(InferCtxtInner::new()), lexical_region_resolutions: RefCell::new(None), diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 36eb8a4baa830..2bfa51f27bbb6 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -105,7 +105,7 @@ fn mir_borrowck<'tcx>( let (input_body, promoted) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id())); - let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { + let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); do_mir_borrowck(&infcx, input_body, promoted) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index d4edd8da7cc41..f69d08a6d5942 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1305,7 +1305,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // (Note that the key of the map is both the def-id of `Foo` along with // any generic parameters.) let output_ty = obligations.add(infcx.instantiate_opaque_types( - mir_def_id, dummy_body_id, param_env, anon_ty, diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 70360f176bf6b..c24e738a7df03 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -32,7 +32,6 @@ pub enum GenerateMemberConstraints { pub trait InferCtxtExt<'tcx> { fn instantiate_opaque_types>( &self, - parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: T, @@ -94,25 +93,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// - `value_span` -- the span where the value came from, used in error reporting fn instantiate_opaque_types>( &self, - parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: T, value_span: Span, ) -> InferOk<'tcx, T> { debug!( - "instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \ + "instantiate_opaque_types(value={:?}, body_id={:?}, \ param_env={:?}, value_span={:?})", - value, parent_def_id, body_id, param_env, value_span, + value, body_id, param_env, value_span, ); - let mut instantiator = Instantiator { - infcx: self, - parent_def_id, - body_id, - param_env, - value_span, - obligations: vec![], - }; + let mut instantiator = + Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] }; let value = instantiator.instantiate_opaque_types_in_map(value); InferOk { value, obligations: instantiator.obligations } } @@ -857,7 +849,6 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { struct Instantiator<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, - parent_def_id: LocalDefId, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value_span: Span, @@ -910,7 +901,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // ``` if let Some(def_id) = def_id.as_local() { let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let parent_def_id = self.parent_def_id; + let parent_def_id = self.infcx.defining_use_anchor; let def_scope_default = || { let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) @@ -922,14 +913,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { impl_trait_fn: Some(parent), origin, .. - }) => (parent == self.parent_def_id.to_def_id(), origin), + }) => (parent == parent_def_id.to_def_id(), origin), // Named `type Foo = impl Bar;` hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, origin, .. }) => ( - may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id), + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), origin, ), _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index db88174551679..10c3a97e73a5a 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -593,11 +593,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { orig_expected: Expectation<'tcx>, ) -> Option { match (orig_expected, self.ret_coercion_impl_trait.map(|ty| (self.body_id.owner, ty))) { - (Expectation::ExpectHasType(expected), Some((id, ty))) + (Expectation::ExpectHasType(expected), Some((_id, ty))) if self.in_tail_expr && self.can_coerce(outer_ty, expected) => { let impl_trait_ret_ty = - self.infcx.instantiate_opaque_types(id, self.body_id, self.param_env, ty, span); + self.infcx.instantiate_opaque_types(self.body_id, self.param_env, ty, span); assert!( impl_trait_ret_ty.obligations.is_empty(), "we should never get new obligations here" diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 2496747c0619d..8b5b7e3e52c80 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -95,7 +95,7 @@ pub(super) fn check_fn<'a, 'tcx>( let declared_ret_ty = fn_sig.output(); let revealed_ret_ty = - fcx.instantiate_opaque_types_from_value(fn_id, declared_ret_ty, decl.output.span()); + fcx.instantiate_opaque_types_from_value(declared_ret_ty, decl.output.span()); debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty))); fcx.ret_type_span = Some(decl.output.span()); @@ -651,7 +651,7 @@ fn check_opaque_meets_bounds<'tcx>( let misc_cause = traits::ObligationCause::misc(span, hir_id); let _ = inh.register_infer_ok_obligations( - infcx.instantiate_opaque_types(def_id, hir_id, param_env, opaque_ty, span), + infcx.instantiate_opaque_types(hir_id, param_env, opaque_ty, span), ); let opaque_type_map = infcx.inner.borrow().opaque_types.clone(); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index ba235c142692d..b84a79b768c9a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -362,20 +362,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Replaces the opaque types from the given value with type variables, /// and records the `OpaqueTypeMap` for later use during writeback. See /// `InferCtxt::instantiate_opaque_types` for more details. + #[instrument(skip(self, value_span), level = "debug")] pub(in super::super) fn instantiate_opaque_types_from_value>( &self, - parent_id: hir::HirId, value: T, value_span: Span, ) -> T { - let parent_def_id = self.tcx.hir().local_def_id(parent_id); - debug!( - "instantiate_opaque_types_from_value(parent_def_id={:?}, value={:?})", - parent_def_id, value - ); - self.register_infer_ok_obligations(self.instantiate_opaque_types( - parent_def_id, self.body_id, self.param_env, value,