Skip to content

Commit d72008e

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 d72008e

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

+312
-225
lines changed

Diff for: 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()

Diff for: 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");

Diff for: 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);

Diff for: 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);

Diff for: 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

Diff for: 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
}

Diff for: 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-
}

Diff for: 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,

Diff for: 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

Diff for: 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

Diff for: 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
{

Diff for: compiler/rustc_ty_utils/src/opaque_types.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -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

Diff for: 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
}

Diff for: 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
}

Diff for: 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

Diff for: 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
|

Diff for: 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
}

Diff for: tests/ui/impl-trait/issues/issue-78722-2.stderr

+11-20
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,21 @@ error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:21}` to be
44
LL | fn concrete_use() -> F {
55
| ^ expected `()`, found `u8`
66

7-
error: item constrains opaque type that is not in its signature
7+
error[E0308]: mismatched types
88
--> $DIR/issue-78722-2.rs:15:20
99
|
10+
LL | type F = impl core::future::Future<Output = u8>;
11+
| -------------------------------------- the expected future
12+
...
1013
LL | let f: F = async { 1 };
11-
| ^^^^^^^^^^^
14+
| - ^^^^^^^^^^^ expected future, found `async` block
15+
| |
16+
| expected due to this
1217
|
13-
= note: this item must mention the opaque type in its signature in order to be able to register hidden types
14-
note: this item must mention the opaque type in its signature in order to be able to register hidden types
15-
--> $DIR/issue-78722-2.rs:15:20
16-
|
17-
LL | let f: F = async { 1 };
18-
| ^^^^^^^^^^^
19-
20-
error[E0658]: `async` blocks are not allowed in constants
21-
--> $DIR/issue-78722-2.rs:15:20
22-
|
23-
LL | let f: F = async { 1 };
24-
| ^^^^^^^^^^^
25-
|
26-
= note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
27-
= help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
28-
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
18+
= note: expected opaque type `F`
19+
found `async` block `{async block@$DIR/issue-78722-2.rs:15:20: 15:31}`
2920

30-
error: aborting due to 3 previous errors
21+
error: aborting due to 2 previous errors
3122

32-
Some errors have detailed explanations: E0271, E0658.
23+
Some errors have detailed explanations: E0271, E0308.
3324
For more information about an error, try `rustc --explain E0271`.

0 commit comments

Comments
 (0)