Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop handling opaque types in queries and leave it to typeck #107891

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,13 @@ 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);
// HACK This bubble is required for this tests to pass:
// type-alias-impl-trait/issue-67844-nested-opaque.rs
let infcx =
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
let infcx = self
.tcx
.infer_ctxt()
// HACK This bubble is required for this tests to pass:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// HACK This bubble is required for this tests to pass:
// HACK This ignore is required for this tests to pass:

// type-alias-impl-trait/issue-67844-nested-opaque.rs
.with_opaque_type_inference(DefiningAnchor::Ignore)
.build();
let ocx = ObligationCtxt::new(&infcx);
// 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
Expand Down Expand Up @@ -316,10 +319,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
// version.
let errors = ocx.select_all_or_error();

// This is still required for many(half of the tests in ui/type-alias-impl-trait)
// tests to pass
let _ = infcx.take_opaque_types();

if errors.is_empty() {
definition_ty
} else {
Expand Down
17 changes: 9 additions & 8 deletions compiler/rustc_const_eval/src/util/compare_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,15 @@ 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()
// With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
// we would get unification errors because we're unable to look into opaque types,
// even if they're constrained in our current function.
//
// It seems very unlikely that this hides any bugs.
.with_opaque_type_inference(DefiningAnchor::Ignore);
let infcx = builder.build();
let ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy();
Expand All @@ -53,11 +60,5 @@ pub fn is_subtype<'tcx>(
Err(_) => return false,
};
let errors = ocx.select_all_or_error();
// With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
// we would get unification errors because we're unable to look into opaque types,
// even if they're constrained in our current function.
//
// It seems very unlikely that this hides any bugs.
let _ = infcx.take_opaque_types();
errors.is_empty()
}
17 changes: 11 additions & 6 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,12 @@ impl<'tcx> InferCtxtInner<'tcx> {

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DefiningAnchor {
/// `DefId` of the item.
/// `DefId` of the item for which we check whether any opaque types may
/// have their hidden types registered.
Bind(LocalDefId),
/// When opaque types are not resolved, we `Bubble` up, meaning
/// return the opaque/hidden type pair from query, for caller of query to handle it.
Bubble,
/// Used to treat all opaque types as in their defining scope.
/// Used for coherence, codegen and sanity checks.
Ignore,
/// Used to catch type mismatch errors when handling opaque types.
Error,
}
Expand All @@ -259,7 +260,7 @@ pub struct InferCtxt<'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
/// If it is `DefiningAnchor::Ignore`, 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.
Expand Down Expand Up @@ -1340,7 +1341,11 @@ 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);
debug_assert!(
matches!(self.defining_use_anchor, DefiningAnchor::Bind(_)),
"{:?}",
self.defining_use_anchor
);
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
}

Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl<'tcx> InferCtxt<'tcx> {
// ```
self.opaque_type_origin(def_id)?
}
DefiningAnchor::Bubble => self.opaque_type_origin_unchecked(def_id),
DefiningAnchor::Ignore => self.opaque_type_origin_unchecked(def_id),
DefiningAnchor::Error => return None,
};
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
Expand Down Expand Up @@ -374,7 +374,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = match self.defining_use_anchor {
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
DefiningAnchor::Ignore | DefiningAnchor::Error => return None,
DefiningAnchor::Bind(bind) => bind,
};

Expand Down Expand Up @@ -539,14 +539,16 @@ impl<'tcx> InferCtxt<'tcx> {
let span = cause.span;

let mut obligations = vec![];
let prev = self.inner.borrow_mut().opaque_types().register(
OpaqueTypeKey { def_id, substs },
OpaqueHiddenType { ty: hidden_ty, span },
origin,
);
if let Some(prev) = prev {
obligations =
self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations;
if !matches!(self.defining_use_anchor, DefiningAnchor::Ignore) {
let prev = self.inner.borrow_mut().opaque_types().register(
OpaqueTypeKey { def_id, substs },
OpaqueHiddenType { ty: hidden_ty, span },
origin,
);
if let Some(prev) = prev {
obligations =
self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations;
}
}

let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub fn overlapping_impls(
}

let infcx =
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Ignore).intercrate().build();
let selcx = &mut SelectionContext::new(&infcx);
let overlaps =
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
Expand All @@ -108,7 +108,7 @@ pub fn overlapping_impls(
// 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();
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Ignore).intercrate().build();
let selcx = &mut SelectionContext::new(&infcx);
selcx.enable_tracking_intercrate_ambiguity_causes();
Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_traits/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ pub fn codegen_select_candidate<'tcx>(
let infcx = tcx
.infer_ctxt()
.ignoring_regions()
.with_opaque_type_inference(DefiningAnchor::Bubble)
// Opaque types may have gotten their hidden types constrained, but we can ignore them safely
// as they will get constrained elsewhere, too.
// (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
.with_opaque_type_inference(DefiningAnchor::Ignore)
.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 obligation_cause = ObligationCause::dummy();
Expand Down Expand Up @@ -79,10 +80,5 @@ pub fn codegen_select_candidate<'tcx>(
let impl_source = infcx.resolve_vars_if_possible(impl_source);
let impl_source = infcx.tcx.erase_regions(impl_source);

// Opaque types may have gotten their hidden types constrained, but we can ignore them safely
// as they will get constrained elsewhere, too.
// (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
let _ = infcx.take_opaque_types();

Ok(&*tcx.arena.alloc(impl_source))
}