Skip to content

Commit 04461ee

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 da35734 commit 04461ee

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

+281
-227
lines changed

compiler/rustc_borrowck/src/consumers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ 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.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
110110
let input_body: &Body<'_> = &input_body.borrow();
111111
let promoted: &IndexSlice<_, _> = &promoted.borrow();
112112
*super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()

compiler/rustc_borrowck/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,10 @@ 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(tcx, hir_owner.def_id))
133+
.build();
132134
let promoted: &IndexSlice<_, _> = &promoted.borrow();
133135
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
134136
debug!("mir_borrowck done");

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ 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(tcx, parent_def_id))
321321
.build();
322322
let ocx = ObligationCtxt::new(&infcx);
323323
let identity_args = GenericArgs::identity_for_item(tcx, def_id);

compiler/rustc_hir_analysis/src/check/check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ 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(tcx, defining_use_anchor))
350350
.build();
351351
let ocx = ObligationCtxt::new(&infcx);
352352

@@ -1569,7 +1569,7 @@ pub(super) fn check_coroutine_obligations(
15691569
.ignoring_regions()
15701570
// Bind opaque types to type checking root, as they should have been checked by borrowck,
15711571
// but may show up in some cases, like when (root) obligations are stalled in the new solver.
1572-
.with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id))
1572+
.with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id))
15731573
.build();
15741574

15751575
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, 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
@@ -613,7 +613,7 @@ impl fmt::Display for FixupError {
613613
/// Used to configure inference contexts before their creation.
614614
pub struct InferCtxtBuilder<'tcx> {
615615
tcx: TyCtxt<'tcx>,
616-
defining_use_anchor: DefiningAnchor,
616+
defining_use_anchor: DefiningAnchor<'tcx>,
617617
considering_regions: bool,
618618
skip_leak_check: bool,
619619
/// Whether we are in coherence mode.
@@ -644,7 +644,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
644644
/// It is only meant to be called in two places, for typeck
645645
/// (via `Inherited::build`) and for the inference context used
646646
/// in mir borrowck.
647-
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
647+
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self {
648648
self.defining_use_anchor = defining_use_anchor;
649649
self
650650
}

compiler/rustc_infer/src/infer/opaque_types.rs

+3-57
Original file line numberDiff line numberDiff line change
@@ -368,28 +368,14 @@ impl<'tcx> InferCtxt<'tcx> {
368368
/// in its defining scope.
369369
#[instrument(skip(self), level = "trace", ret)]
370370
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
371-
let opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id);
372-
let parent_def_id = match self.defining_use_anchor {
371+
let defined_opaque_types = match self.defining_use_anchor {
373372
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
374373
DefiningAnchor::Bind(bind) => bind,
375374
};
376375

377376
let origin = self.tcx.opaque_type_origin(def_id);
378-
let in_definition_scope = match origin {
379-
// Async `impl Trait`
380-
hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
381-
// Anonymous `impl Trait`
382-
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
383-
// Named `type Foo = impl Bar;`
384-
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
385-
if in_assoc_ty {
386-
self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
387-
} else {
388-
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
389-
}
390-
}
391-
};
392-
in_definition_scope.then_some(origin)
377+
378+
defined_opaque_types.contains(&def_id).then_some(origin)
393379
}
394380
}
395381

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

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

+11-5
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ pub mod util;
1212
use crate::infer::canonical::Canonical;
1313
use crate::mir::ConstraintCategory;
1414
use crate::ty::abstract_const::NotConstEvaluatable;
15-
use crate::ty::GenericArgsRef;
1615
use crate::ty::{self, AdtKind, Ty};
16+
use crate::ty::{GenericArgsRef, TyCtxt};
1717

1818
use rustc_data_structures::sync::Lrc;
1919
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
@@ -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
@@ -1018,3 +1018,9 @@ pub enum DefiningAnchor {
10181018
/// otherwise reveal opaques (such as [`Reveal::All`] reveal mode).
10191019
Error,
10201020
}
1021+
1022+
impl<'tcx> DefiningAnchor<'tcx> {
1023+
pub fn bind(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
1024+
Self::Bind(tcx.opaque_types_defined_by(item))
1025+
}
1026+
}

compiler/rustc_middle/src/traits/solve.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl MaybeCause {
115115
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
116116
pub struct QueryInput<'tcx, T> {
117117
pub goal: Goal<'tcx, T>,
118-
pub anchor: DefiningAnchor,
118+
pub anchor: DefiningAnchor<'tcx>,
119119
pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
120120
}
121121

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

+6-13
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use rustc_hir::{GenericParam, Item, Node};
3131
use rustc_infer::infer::error_reporting::TypeErrCtxt;
3232
use rustc_infer::infer::{InferOk, TypeTrace};
3333
use rustc_middle::traits::select::OverflowError;
34-
use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData};
34+
use rustc_middle::traits::SignatureMismatchData;
3535
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
3636
use rustc_middle::ty::error::{ExpectedFound, TypeError};
3737
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
@@ -3373,19 +3373,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
33733373
obligation.cause.span,
33743374
format!("cannot check whether the hidden type of {name} satisfies auto traits"),
33753375
);
3376+
3377+
err.note(
3378+
"fetching the hidden types of an opaque inside of the defining scope is not supported. \
3379+
You can try moving the opaque type and the item that actually registers a hidden type into a new submodule",
3380+
);
33763381
err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
3377-
match self.defining_use_anchor {
3378-
DefiningAnchor::Bubble | DefiningAnchor::Error => {}
3379-
DefiningAnchor::Bind(bind) => {
3380-
err.span_note(
3381-
self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
3382-
"this item depends on auto traits of the hidden type, \
3383-
but may also be registering the hidden type. \
3384-
This is not supported right now. \
3385-
You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
3386-
);
3387-
}
3388-
};
33893382

33903383
self.note_obligation_cause(&mut err, &obligation);
33913384
self.point_at_returns_when_relevant(&mut err, &obligation);

compiler/rustc_ty_utils/src/opaque_types.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
109109

110110
#[instrument(level = "trace", skip(self))]
111111
fn collect_taits_declared_in_body(&mut self) {
112-
let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(self.item)).value;
112+
// Some things not necessarily have bodies, like method declarations in traits.
113+
let Some(body_owner) = self.tcx.hir().maybe_body_owned_by(self.item) else { return };
114+
let body = self.tcx.hir().body(body_owner).value;
113115
struct TaitInBodyFinder<'a, 'tcx> {
114116
collector: &'a mut OpaqueTypeCollector<'tcx>,
115117
}
@@ -212,12 +214,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
212214
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
213215
self.visit_opaque_ty(alias_ty);
214216
}
217+
// Skips type aliases, as they are meant to be transparent.
215218
ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
216219
self.tcx
217220
.type_of(alias_ty.def_id)
218221
.instantiate(self.tcx, alias_ty.args)
219222
.visit_with(self)?;
220223
}
224+
// RPITIT are encoded as projections, not opaque types, make sure to handle these special
225+
// projections independently of the projection handling below.
226+
ty::Alias(ty::Projection, alias_ty)
227+
if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
228+
self.tcx.opt_rpitit_info(alias_ty.def_id)
229+
&& fn_def_id == self.item.into() =>
230+
{
231+
let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args);
232+
let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") };
233+
self.visit_opaque_ty(alias_ty);
234+
}
221235
ty::Alias(ty::Projection, alias_ty) => {
222236
// This avoids having to do normalization of `Self::AssocTy` by only
223237
// supporting the case of a method defining opaque types from assoc types

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 the type of the item uses `_`, 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

+1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ 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
2223
}

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

+15-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,19 @@ 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:35
15+
|
16+
LL | fn a(&'a self) -> Self::B<'a> {}
17+
| ^^
18+
|
19+
note: lifetime used multiple times
20+
--> $DIR/issue-88595.rs:18:6
21+
|
22+
LL | impl<'a> A<'a> for C {
23+
| ^^
24+
LL | type B<'b> = impl Clone;
25+
| ^^
26+
27+
error: aborting due to 2 previous errors
1428

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

+1-5
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,12 @@ LL | send(cycle1().clone());
66
| |
77
| required by a bound introduced by this call
88
|
9+
= note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
910
note: opaque type is declared here
1011
--> $DIR/auto-trait-leak.rs:11:16
1112
|
1213
LL | fn cycle1() -> impl Clone {
1314
| ^^^^^^^^^^
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-
| ^^^^^^
1915
note: required by a bound in `send`
2016
--> $DIR/auto-trait-leak.rs:4:12
2117
|

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ struct Bug {
1212
//~^ ERROR future that resolves to `u8`, but it resolves to `()`
1313
async {}
1414
}
15+
// FIXME(type_alias_impl_trait): inform the user about why `F` is not available here.
1516
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
17+
//~^ ERROR mismatched types
1818
1
1919
}],
2020
}

0 commit comments

Comments
 (0)