Skip to content

Commit

Permalink
Store the DefId of the currently typechecked item in InferCtxt
Browse files Browse the repository at this point in the history
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
  • Loading branch information
oli-obk committed Aug 6, 2021
1 parent 20371b9 commit b2c1919
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 32 deletions.
23 changes: 21 additions & 2 deletions compiler/rustc_infer/src/infer/mod.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -550,6 +555,7 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
pub struct InferCtxtBuilder<'tcx> {
tcx: TyCtxt<'tcx>,
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
defining_use_anchor: LocalDefId,
}

pub trait TyCtxtInferExt<'tcx> {
Expand All @@ -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
}

Expand Down Expand Up @@ -594,10 +612,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
}

pub fn enter<R>(&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),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/borrow_check/mod.rs
Expand Up @@ -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)
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir/src/borrow_check/type_check/mod.rs
Expand Up @@ -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,
Expand Down
23 changes: 7 additions & 16 deletions compiler/rustc_trait_selection/src/opaque_types.rs
Expand Up @@ -32,7 +32,6 @@ pub enum GenerateMemberConstraints {
pub trait InferCtxtExt<'tcx> {
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
&self,
parent_def_id: LocalDefId,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
value: T,
Expand Down Expand Up @@ -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<T: TypeFoldable<'tcx>>(
&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 }
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand All @@ -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),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/_match.rs
Expand Up @@ -593,11 +593,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
orig_expected: Expectation<'tcx>,
) -> Option<Span> {
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"
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/check.rs
Expand Up @@ -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());
Expand Down Expand Up @@ -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();
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Expand Up @@ -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<T: TypeFoldable<'tcx>>(
&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,
Expand Down

0 comments on commit b2c1919

Please sign in to comment.