Skip to content

Commit f09d6ba

Browse files
committed
Make DefiningAnchor::Bind only store the opaque types that may be constrained, instead of the current infcx root item.
This makes `Bind` almost always be empty, so we can start forwarding it to queries, allowing us to remove `Bubble` entirely
1 parent ef32456 commit f09d6ba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+320
-230
lines changed

compiler/rustc_borrowck/src/consumers.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ pub fn get_body_with_borrowck_facts(
106106
options: ConsumerOptions,
107107
) -> BodyWithBorrowckFacts<'_> {
108108
let (input_body, promoted) = tcx.mir_promoted(def);
109-
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
109+
let infcx = tcx
110+
.infer_ctxt()
111+
.with_opaque_type_inference(DefiningAnchor::Bind(tcx.opaque_types_defined_by(def)))
112+
.build();
110113
let input_body: &Body<'_> = &input_body.borrow();
111114
let promoted: &IndexSlice<_, _> = &promoted.borrow();
112115
*super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()

compiler/rustc_borrowck/src/lib.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,12 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
127127

128128
let hir_owner = tcx.local_def_id_to_hir_id(def).owner;
129129

130-
let infcx =
131-
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
130+
let infcx = tcx
131+
.infer_ctxt()
132+
.with_opaque_type_inference(DefiningAnchor::Bind(
133+
tcx.opaque_types_defined_by(hir_owner.def_id),
134+
))
135+
.build();
132136
let promoted: &IndexSlice<_, _> = &promoted.borrow();
133137
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
134138
debug!("mir_borrowck done");

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,9 @@ fn check_opaque_type_well_formed<'tcx>(
317317
let infcx = tcx
318318
.infer_ctxt()
319319
.with_next_trait_solver(next_trait_solver)
320-
.with_opaque_type_inference(DefiningAnchor::Bind(parent_def_id))
320+
.with_opaque_type_inference(DefiningAnchor::Bind(
321+
tcx.opaque_types_defined_by(parent_def_id),
322+
))
321323
.build();
322324
let ocx = ObligationCtxt::new(&infcx);
323325
let identity_args = GenericArgs::identity_for_item(tcx, def_id);

compiler/rustc_hir_analysis/src/check/check.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,9 @@ fn check_opaque_meets_bounds<'tcx>(
346346

347347
let infcx = tcx
348348
.infer_ctxt()
349-
.with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor))
349+
.with_opaque_type_inference(DefiningAnchor::Bind(
350+
tcx.opaque_types_defined_by(defining_use_anchor),
351+
))
350352
.build();
351353
let ocx = ObligationCtxt::new(&infcx);
352354

@@ -1570,7 +1572,9 @@ pub(super) fn check_coroutine_obligations(
15701572
.ignoring_regions()
15711573
// Bind opaque types to type checking root, as they should have been checked by borrowck,
15721574
// but may show up in some cases, like when (root) obligations are stalled in the new solver.
1573-
.with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id))
1575+
.with_opaque_type_inference(DefiningAnchor::Bind(
1576+
tcx.opaque_types_defined_by(typeck.hir_owner.def_id),
1577+
))
15741578
.build();
15751579

15761580
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);

compiler/rustc_hir_typeck/src/inherited.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl<'tcx> Inherited<'tcx> {
7979
let infcx = tcx
8080
.infer_ctxt()
8181
.ignoring_regions()
82-
.with_opaque_type_inference(DefiningAnchor::Bind(def_id))
82+
.with_opaque_type_inference(DefiningAnchor::Bind(tcx.opaque_types_defined_by(def_id)))
8383
.build();
8484
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
8585

compiler/rustc_infer/src/infer/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ pub struct InferCtxt<'tcx> {
252252
///
253253
/// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
254254
/// might come up during inference or typeck.
255-
pub defining_use_anchor: DefiningAnchor,
255+
pub defining_use_anchor: DefiningAnchor<'tcx>,
256256

257257
/// Whether this inference context should care about region obligations in
258258
/// the root universe. Most notably, this is used during hir typeck as region
@@ -619,7 +619,7 @@ impl fmt::Display for FixupError {
619619
/// Used to configure inference contexts before their creation.
620620
pub struct InferCtxtBuilder<'tcx> {
621621
tcx: TyCtxt<'tcx>,
622-
defining_use_anchor: DefiningAnchor,
622+
defining_use_anchor: DefiningAnchor<'tcx>,
623623
considering_regions: bool,
624624
skip_leak_check: bool,
625625
/// Whether we are in coherence mode.
@@ -650,7 +650,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
650650
/// It is only meant to be called in two places, for typeck
651651
/// (via `Inherited::build`) and for the inference context used
652652
/// in mir borrowck.
653-
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
653+
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self {
654654
self.defining_use_anchor = defining_use_anchor;
655655
self
656656
}

compiler/rustc_infer/src/infer/opaque_types.rs

+3-57
Original file line numberDiff line numberDiff line change
@@ -373,28 +373,14 @@ impl<'tcx> InferCtxt<'tcx> {
373373
/// in its defining scope.
374374
#[instrument(skip(self), level = "trace", ret)]
375375
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
376-
let opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id);
377-
let parent_def_id = match self.defining_use_anchor {
376+
let defined_opaque_types = match self.defining_use_anchor {
378377
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
379378
DefiningAnchor::Bind(bind) => bind,
380379
};
381380

382381
let origin = self.tcx.opaque_type_origin(def_id);
383-
let in_definition_scope = match origin {
384-
// Async `impl Trait`
385-
hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
386-
// Anonymous `impl Trait`
387-
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
388-
// Named `type Foo = impl Bar;`
389-
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
390-
if in_assoc_ty {
391-
self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
392-
} else {
393-
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
394-
}
395-
}
396-
};
397-
in_definition_scope.then_some(origin)
382+
383+
defined_opaque_types.contains(&def_id).then_some(origin)
398384
}
399385
}
400386

@@ -652,43 +638,3 @@ impl<'tcx> InferCtxt<'tcx> {
652638
}
653639
}
654640
}
655-
656-
/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`.
657-
///
658-
/// Example:
659-
/// ```ignore UNSOLVED (is this a bug?)
660-
/// # #![feature(type_alias_impl_trait)]
661-
/// pub mod foo {
662-
/// pub mod bar {
663-
/// pub trait Bar { /* ... */ }
664-
/// pub type Baz = impl Bar;
665-
///
666-
/// # impl Bar for () {}
667-
/// fn f1() -> Baz { /* ... */ }
668-
/// }
669-
/// fn f2() -> bar::Baz { /* ... */ }
670-
/// }
671-
/// ```
672-
///
673-
/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
674-
/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
675-
/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
676-
fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
677-
let mut hir_id = tcx.local_def_id_to_hir_id(def_id);
678-
679-
// Named opaque types can be defined by any siblings or children of siblings.
680-
let scope = tcx.hir().get_defining_scope(opaque_hir_id);
681-
// We walk up the node tree until we hit the root or the scope of the opaque type.
682-
while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
683-
hir_id = tcx.hir().get_parent_item(hir_id).into();
684-
}
685-
// Syntactically, we are allowed to define the concrete type if:
686-
let res = hir_id == scope;
687-
trace!(
688-
"may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
689-
tcx.hir_node(hir_id),
690-
tcx.hir_node(opaque_hir_id),
691-
res
692-
);
693-
res
694-
}

compiler/rustc_middle/src/mir/type_foldable.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! `TypeFoldable` implementations for MIR types
22
33
use rustc_ast::InlineAsmTemplatePiece;
4+
use rustc_hir::def_id::LocalDefId;
45

56
use super::*;
67

@@ -44,6 +45,15 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] {
4445
}
4546
}
4647

48+
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [LocalDefId] {
49+
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
50+
self,
51+
_folder: &mut F,
52+
) -> Result<Self, F::Error> {
53+
Ok(self)
54+
}
55+
}
56+
4757
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
4858
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
4959
self,

compiler/rustc_middle/src/traits/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1001,10 +1001,10 @@ pub enum CodegenObligationError {
10011001
/// opaques are replaced with inference vars eagerly in the old solver (e.g.
10021002
/// in projection, and in the signature during function type-checking).
10031003
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
1004-
pub enum DefiningAnchor {
1005-
/// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly
1006-
/// replace opaque types in `replace_opaque_types_with_inference_vars`.
1007-
Bind(LocalDefId),
1004+
pub enum DefiningAnchor<'tcx> {
1005+
/// Define opaques which are in-scope of the current item being analyzed.
1006+
/// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`.
1007+
Bind(&'tcx [LocalDefId]),
10081008
/// In contexts where we don't currently know what opaques are allowed to be
10091009
/// defined, such as (old solver) canonical queries, we will simply allow
10101010
/// opaques to be defined, but "bubble" them up in the canonical response or

compiler/rustc_middle/src/traits/solve.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub enum MaybeCause {
105105
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
106106
pub struct QueryInput<'tcx, T> {
107107
pub goal: Goal<'tcx, T>,
108-
pub anchor: DefiningAnchor,
108+
pub anchor: DefiningAnchor<'tcx>,
109109
pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
110110
}
111111

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+1-13
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_hir::{GenericParam, Item, Node};
3232
use rustc_infer::infer::error_reporting::TypeErrCtxt;
3333
use rustc_infer::infer::{InferOk, TypeTrace};
3434
use rustc_middle::traits::select::OverflowError;
35-
use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData};
35+
use rustc_middle::traits::SignatureMismatchData;
3636
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
3737
use rustc_middle::ty::error::{ExpectedFound, TypeError};
3838
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
@@ -3314,18 +3314,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
33143314
format!("cannot check whether the hidden type of {name} satisfies auto traits"),
33153315
);
33163316
err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
3317-
match self.defining_use_anchor {
3318-
DefiningAnchor::Bubble | DefiningAnchor::Error => {}
3319-
DefiningAnchor::Bind(bind) => {
3320-
err.span_note(
3321-
self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
3322-
"this item depends on auto traits of the hidden type, \
3323-
but may also be registering the hidden type. \
3324-
This is not supported right now. \
3325-
You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
3326-
);
3327-
}
3328-
};
33293317

33303318
if let Some(diag) = self.dcx().steal_diagnostic(self.tcx.def_span(def_id), StashKey::Cycle)
33313319
{

compiler/rustc_ty_utils/src/opaque_types.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
4444

4545
fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
4646
let parent = self.parent()?;
47-
if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
48-
Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity())
49-
} else {
50-
None
47+
match self.tcx.def_kind(parent) {
48+
DefKind::Impl { .. } => Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity()),
49+
DefKind::Trait => Some(ty::TraitRef::identity(self.tcx, parent.into())),
50+
_ => None,
5151
}
5252
}
5353

@@ -96,7 +96,9 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
9696

9797
#[instrument(level = "trace", skip(self))]
9898
fn collect_taits_declared_in_body(&mut self) {
99-
let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(self.item)).value;
99+
// Some things not necessarily have bodies, like method declarations in traits.
100+
let Some(body_owner) = self.tcx.hir().maybe_body_owned_by(self.item) else { return };
101+
let body = self.tcx.hir().body(body_owner).value;
100102
struct TaitInBodyFinder<'a, 'tcx> {
101103
collector: &'a mut OpaqueTypeCollector<'tcx>,
102104
}
@@ -205,6 +207,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
205207
.instantiate(self.tcx, alias_ty.args)
206208
.visit_with(self)?;
207209
}
210+
ty::Alias(ty::Projection, alias_ty)
211+
if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
212+
self.tcx.opt_rpitit_info(alias_ty.def_id)
213+
&& fn_def_id == self.item.into() =>
214+
{
215+
let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args);
216+
let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") };
217+
self.visit_opaque_ty(alias_ty);
218+
}
208219
ty::Alias(ty::Projection, alias_ty) => {
209220
// This avoids having to do normalization of `Self::AssocTy` by only
210221
// supporting the case of a method defining opaque types from assoc types
@@ -213,7 +224,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
213224
// If the trait ref of the associated item and the impl differs,
214225
// then we can't use the impl's identity args below, so
215226
// just skip.
216-
if alias_ty.trait_ref(self.tcx) == parent_trait_ref {
227+
let trait_ref = alias_ty.trait_ref(self.tcx);
228+
trace!(?trait_ref);
229+
trace!(?parent_trait_ref);
230+
if trait_ref == parent_trait_ref {
217231
let parent = self.parent().expect("we should have a parent here");
218232

219233
for &assoc in self.tcx.associated_items(parent).in_definition_order() {

compiler/rustc_ty_utils/src/sig_types.rs

+6
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
4343
// Walk over the type of the item
4444
DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
4545
if let Some(ty) = tcx.hir_node_by_def_id(item).ty() {
46+
// If there are inference variables, we're gonna error out anyway, but
47+
// typeck (which type_of invokes below), will call back into opaque_types_defined_by
48+
// causing a cycle. So we just bail out in this case.
49+
if ty.is_suggestable_infer_ty() {
50+
return ControlFlow::Continue(());
51+
}
4652
// Associated types in traits don't necessarily have a type that we can visit
4753
visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())?;
4854
}

tests/ui/generic-associated-types/issue-88595.rs

+2
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ impl<'a> A<'a> for C {
1919
type B<'b> = impl Clone;
2020

2121
fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
22+
//~^ ERROR: non-defining opaque type use in defining scope
23+
//~| ERROR: non-defining opaque type use in defining scope
2224
}

tests/ui/generic-associated-types/issue-88595.stderr

+28-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,32 @@ note: for this opaque type
1010
LL | type B<'b> = impl Clone;
1111
| ^^^^^^^^^^
1212

13-
error: aborting due to 1 previous error
13+
error: non-defining opaque type use in defining scope
14+
--> $DIR/issue-88595.rs:21:23
15+
|
16+
LL | fn a(&'a self) -> Self::B<'a> {}
17+
| ^^^^^^^^^^^ generic argument `'a` used twice
18+
|
19+
note: for this opaque type
20+
--> $DIR/issue-88595.rs:19:18
21+
|
22+
LL | type B<'b> = impl Clone;
23+
| ^^^^^^^^^^
24+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25+
26+
error: non-defining opaque type use in defining scope
27+
--> $DIR/issue-88595.rs:21:35
28+
|
29+
LL | fn a(&'a self) -> Self::B<'a> {}
30+
| ^^
31+
|
32+
note: lifetime used multiple times
33+
--> $DIR/issue-88595.rs:18:6
34+
|
35+
LL | impl<'a> A<'a> for C {
36+
| ^^
37+
LL | type B<'b> = impl Clone;
38+
| ^^
39+
40+
error: aborting due to 3 previous errors
1441

tests/ui/impl-trait/auto-trait-leak.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ note: opaque type is declared here
1111
|
1212
LL | fn cycle1() -> impl Clone {
1313
| ^^^^^^^^^^
14-
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
15-
--> $DIR/auto-trait-leak.rs:17:4
16-
|
17-
LL | fn cycle2() -> impl Clone {
18-
| ^^^^^^
1914
note: required by a bound in `send`
2015
--> $DIR/auto-trait-leak.rs:4:12
2116
|

tests/ui/impl-trait/issues/issue-78722-2.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ struct Bug {
1313
async {}
1414
}
1515
let f: F = async { 1 };
16-
//~^ ERROR item constrains opaque type that is not in its signature
17-
//~| ERROR `async` blocks are not allowed in constants
16+
//~^ ERROR mismatched types
1817
1
1918
}],
2019
}

0 commit comments

Comments
 (0)