Skip to content

Commit c20083e

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 1b2c53a commit c20083e

Some content is hidden

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

47 files changed

+293
-228
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

+1-4
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
125125
return tcx.arena.alloc(result);
126126
}
127127

128-
let hir_owner = tcx.local_def_id_to_hir_id(def).owner;
129-
130-
let infcx =
131-
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
128+
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
132129
let promoted: &IndexSlice<_, _> = &promoted.borrow();
133130
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
134131
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
@@ -347,7 +347,7 @@ fn check_opaque_meets_bounds<'tcx>(
347347

348348
let infcx = tcx
349349
.infer_ctxt()
350-
.with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor))
350+
.with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor))
351351
.build();
352352
let ocx = ObligationCtxt::new(&infcx);
353353

@@ -1558,7 +1558,7 @@ pub(super) fn check_coroutine_obligations(
15581558
.ignoring_regions()
15591559
// Bind opaque types to type checking root, as they should have been checked by borrowck,
15601560
// but may show up in some cases, like when (root) obligations are stalled in the new solver.
1561-
.with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id))
1561+
.with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id))
15621562
.build();
15631563

15641564
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
@@ -244,7 +244,7 @@ pub struct InferCtxt<'tcx> {
244244
///
245245
/// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
246246
/// might come up during inference or typeck.
247-
pub defining_use_anchor: DefiningAnchor,
247+
pub defining_use_anchor: DefiningAnchor<'tcx>,
248248

249249
/// Whether this inference context should care about region obligations in
250250
/// the root universe. Most notably, this is used during hir typeck as region
@@ -605,7 +605,7 @@ impl fmt::Display for FixupError {
605605
/// Used to configure inference contexts before their creation.
606606
pub struct InferCtxtBuilder<'tcx> {
607607
tcx: TyCtxt<'tcx>,
608-
defining_use_anchor: DefiningAnchor,
608+
defining_use_anchor: DefiningAnchor<'tcx>,
609609
considering_regions: bool,
610610
skip_leak_check: bool,
611611
/// Whether we are in coherence mode.
@@ -636,7 +636,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
636636
/// It is only meant to be called in two places, for typeck
637637
/// (via `Inherited::build`) and for the inference context used
638638
/// in mir borrowck.
639-
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
639+
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self {
640640
self.defining_use_anchor = defining_use_anchor;
641641
self
642642
}

compiler/rustc_infer/src/infer/opaque_types/mod.rs

+3-57
Original file line numberDiff line numberDiff line change
@@ -378,28 +378,14 @@ impl<'tcx> InferCtxt<'tcx> {
378378
/// in its defining scope.
379379
#[instrument(skip(self), level = "trace", ret)]
380380
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
381-
let opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id);
382-
let parent_def_id = match self.defining_use_anchor {
381+
let defined_opaque_types = match self.defining_use_anchor {
383382
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
384383
DefiningAnchor::Bind(bind) => bind,
385384
};
386385

387386
let origin = self.tcx.opaque_type_origin(def_id);
388-
let in_definition_scope = match origin {
389-
// Async `impl Trait`
390-
hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
391-
// Anonymous `impl Trait`
392-
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
393-
// Named `type Foo = impl Bar;`
394-
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
395-
if in_assoc_ty {
396-
self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
397-
} else {
398-
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
399-
}
400-
}
401-
};
402-
in_definition_scope.then_some(origin)
387+
388+
defined_opaque_types.contains(&def_id).then_some(origin)
403389
}
404390
}
405391

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

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 ty::List<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 ty::List<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
@@ -114,7 +114,7 @@ impl MaybeCause {
114114
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
115115
pub struct QueryInput<'tcx, T> {
116116
pub goal: Goal<'tcx, T>,
117-
pub anchor: DefiningAnchor,
117+
pub anchor: DefiningAnchor<'tcx>,
118118
pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
119119
}
120120

compiler/rustc_middle/src/ty/codec.rs

+10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::traits;
1717
use crate::ty::GenericArgsRef;
1818
use crate::ty::{self, AdtDef, Ty};
1919
use rustc_data_structures::fx::FxHashMap;
20+
use rustc_hir::def_id::LocalDefId;
2021
use rustc_middle::ty::TyCtxt;
2122
use rustc_serialize::{Decodable, Encodable};
2223
use rustc_span::Span;
@@ -431,6 +432,15 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Fi
431432
}
432433
}
433434

435+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<LocalDefId> {
436+
fn decode(decoder: &mut D) -> &'tcx Self {
437+
let len = decoder.read_usize();
438+
decoder.interner().mk_local_def_ids_from_iter(
439+
(0..len).map::<LocalDefId, _>(|_| Decodable::decode(decoder)),
440+
)
441+
}
442+
}
443+
434444
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
435445
for ty::List<(VariantIdx, FieldIdx)>
436446
{

compiler/rustc_middle/src/ty/context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2014,6 +2014,14 @@ impl<'tcx> TyCtxt<'tcx> {
20142014
self.intern_local_def_ids(clauses)
20152015
}
20162016

2017+
pub fn mk_local_def_ids_from_iter<I, T>(self, iter: I) -> T::Output
2018+
where
2019+
I: Iterator<Item = T>,
2020+
T: CollectAndApply<LocalDefId, &'tcx List<LocalDefId>>,
2021+
{
2022+
T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs))
2023+
}
2024+
20172025
pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
20182026
where
20192027
I: Iterator<Item = T>,

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};
@@ -3391,19 +3391,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
33913391
obligation.cause.span,
33923392
format!("cannot check whether the hidden type of {name} satisfies auto traits"),
33933393
);
3394+
3395+
err.note(
3396+
"fetching the hidden types of an opaque inside of the defining scope is not supported. \
3397+
You can try moving the opaque type and the item that actually registers a hidden type into a new submodule",
3398+
);
33943399
err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
3395-
match self.defining_use_anchor {
3396-
DefiningAnchor::Bubble | DefiningAnchor::Error => {}
3397-
DefiningAnchor::Bind(bind) => {
3398-
err.span_note(
3399-
self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
3400-
"this item depends on auto traits of the hidden type, \
3401-
but may also be registering the hidden type. \
3402-
This is not supported right now. \
3403-
You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
3404-
);
3405-
}
3406-
};
34073400

34083401
self.note_obligation_cause(&mut err, &obligation);
34093402
self.point_at_returns_when_relevant(&mut err, &obligation);

compiler/rustc_ty_utils/src/opaque_types.rs

+12
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
210210
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
211211
self.visit_opaque_ty(alias_ty);
212212
}
213+
// Skips type aliases, as they are meant to be transparent.
213214
ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
214215
self.tcx
215216
.type_of(alias_ty.def_id)
216217
.instantiate(self.tcx, alias_ty.args)
217218
.visit_with(self);
218219
}
220+
// RPITIT are encoded as projections, not opaque types, make sure to handle these special
221+
// projections independently of the projection handling below.
222+
ty::Alias(ty::Projection, alias_ty)
223+
if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
224+
self.tcx.opt_rpitit_info(alias_ty.def_id)
225+
&& fn_def_id == self.item.into() =>
226+
{
227+
let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args);
228+
let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") };
229+
self.visit_opaque_ty(alias_ty);
230+
}
219231
ty::Alias(ty::Projection, alias_ty) => {
220232
// This avoids having to do normalization of `Self::AssocTy` by only
221233
// 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
@@ -39,6 +39,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
3939
// Walk over the type of the item
4040
DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
4141
if let Some(ty) = tcx.hir_node_by_def_id(item).ty() {
42+
// If the type of the item uses `_`, we're gonna error out anyway, but
43+
// typeck (which type_of invokes below), will call back into opaque_types_defined_by
44+
// causing a cycle. So we just bail out in this case.
45+
if ty.is_suggestable_infer_ty() {
46+
return V::Result::output();
47+
}
4248
// Associated types in traits don't necessarily have a type that we can visit
4349
try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity()));
4450
}

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)