Skip to content

Commit 03c0e58

Browse files
committed
Revert "Auto merge of #79637 - spastorino:revert-trait-inheritance-self, r=Mark-Simulacrum"
This reverts commit b4def89, reversing changes made to 7dc1e85.
1 parent 68ec332 commit 03c0e58

28 files changed

+498
-151
lines changed

compiler/rustc_infer/src/traits/util.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use smallvec::smallvec;
22

33
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
4-
use rustc_data_structures::fx::FxHashSet;
4+
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
55
use rustc_middle::ty::outlives::Component;
66
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
7+
use rustc_span::symbol::Ident;
78

89
pub fn anonymize_predicate<'tcx>(
910
tcx: TyCtxt<'tcx>,
@@ -287,6 +288,37 @@ pub fn transitive_bounds<'tcx>(
287288
elaborate_trait_refs(tcx, bounds).filter_to_traits()
288289
}
289290

291+
/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
292+
/// define the given associated type `assoc_name`. It uses the
293+
/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
294+
/// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or
295+
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
296+
pub fn transitive_bounds_that_define_assoc_type<'tcx>(
297+
tcx: TyCtxt<'tcx>,
298+
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
299+
assoc_name: Ident,
300+
) -> FxIndexSet<ty::PolyTraitRef<'tcx>> {
301+
let mut stack: Vec<_> = bounds.collect();
302+
let mut trait_refs = FxIndexSet::default();
303+
304+
while let Some(trait_ref) = stack.pop() {
305+
if trait_refs.insert(trait_ref) {
306+
let super_predicates =
307+
tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), Some(assoc_name)));
308+
for (super_predicate, _) in super_predicates.predicates {
309+
let bound_predicate = super_predicate.bound_atom();
310+
let subst_predicate = super_predicate
311+
.subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
312+
if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
313+
stack.push(binder.value);
314+
}
315+
}
316+
}
317+
}
318+
319+
trait_refs
320+
}
321+
290322
///////////////////////////////////////////////////////////////////////////
291323
// Other
292324
///////////////////////////////////////////////////////////////////////////

compiler/rustc_middle/src/query/mod.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,23 @@ rustc_queries! {
448448
/// full predicates are available (note that supertraits have
449449
/// additional acyclicity requirements).
450450
query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
451-
desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) }
451+
desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) }
452+
}
453+
454+
/// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
455+
/// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
456+
/// subset of super-predicates that reference traits that define the given associated type.
457+
/// This is used to avoid cycles in resolving types like `T::Item`.
458+
query super_predicates_that_define_assoc_type(key: (DefId, Option<rustc_span::symbol::Ident>)) -> ty::GenericPredicates<'tcx> {
459+
desc { |tcx| "computing the super traits of `{}`{}",
460+
tcx.def_path_str(key.0),
461+
if let Some(assoc_name) = key.1 { format!(" with associated type name `{}`", assoc_name) } else { "".to_string() },
462+
}
452463
}
453464

454465
/// To avoid cycles within the predicates of a single item we compute
455466
/// per-type-parameter predicates for resolving `T::AssocTy`.
456-
query type_param_predicates(key: (DefId, LocalDefId)) -> ty::GenericPredicates<'tcx> {
467+
query type_param_predicates(key: (DefId, LocalDefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
457468
desc { |tcx| "computing the bounds for type parameter `{}`", {
458469
let id = tcx.hir().local_def_id_to_hir_id(key.1);
459470
tcx.hir().ty_param_name(id)

compiler/rustc_middle/src/ty/context.rs

+37-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
5151
use rustc_session::lint::{Level, Lint};
5252
use rustc_session::Session;
5353
use rustc_span::source_map::MultiSpan;
54-
use rustc_span::symbol::{kw, sym, Symbol};
54+
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5555
use rustc_span::{Span, DUMMY_SP};
5656
use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
5757
use rustc_target::spec::abi;
@@ -2081,6 +2081,42 @@ impl<'tcx> TyCtxt<'tcx> {
20812081
self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
20822082
}
20832083

2084+
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
2085+
/// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
2086+
pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
2087+
self.super_traits_of(trait_def_id).any(|trait_did| {
2088+
self.associated_items(trait_did)
2089+
.find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
2090+
.is_some()
2091+
})
2092+
}
2093+
2094+
/// Computes the def-ids of the transitive super-traits of `trait_def_id`. This (intentionally)
2095+
/// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
2096+
/// to identify which traits may define a given associated type to help avoid cycle errors.
2097+
/// Returns a `DefId` iterator.
2098+
fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
2099+
let mut set = FxHashSet::default();
2100+
let mut stack = vec![trait_def_id];
2101+
2102+
set.insert(trait_def_id);
2103+
2104+
iter::from_fn(move || -> Option<DefId> {
2105+
let trait_did = stack.pop()?;
2106+
let generic_predicates = self.super_predicates_of(trait_did);
2107+
2108+
for (predicate, _) in generic_predicates.predicates {
2109+
if let ty::PredicateAtom::Trait(data, _) = predicate.skip_binders() {
2110+
if set.insert(data.def_id()) {
2111+
stack.push(data.def_id());
2112+
}
2113+
}
2114+
}
2115+
2116+
Some(trait_did)
2117+
})
2118+
}
2119+
20842120
/// Given a closure signature, returns an equivalent fn signature. Detuples
20852121
/// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
20862122
/// you would get a `fn(u32, i32)`.

compiler/rustc_middle/src/ty/query/keys.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::ty::subst::{GenericArg, SubstsRef};
77
use crate::ty::{self, Ty, TyCtxt};
88
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
99
use rustc_query_system::query::DefaultCacheSelector;
10-
use rustc_span::symbol::Symbol;
10+
use rustc_span::symbol::{Ident, Symbol};
1111
use rustc_span::{Span, DUMMY_SP};
1212

1313
/// The `Key` trait controls what types can legally be used as the key
@@ -149,6 +149,28 @@ impl Key for (LocalDefId, DefId) {
149149
}
150150
}
151151

152+
impl Key for (DefId, Option<Ident>) {
153+
type CacheSelector = DefaultCacheSelector;
154+
155+
fn query_crate(&self) -> CrateNum {
156+
self.0.krate
157+
}
158+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
159+
tcx.def_span(self.0)
160+
}
161+
}
162+
163+
impl Key for (DefId, LocalDefId, Ident) {
164+
type CacheSelector = DefaultCacheSelector;
165+
166+
fn query_crate(&self) -> CrateNum {
167+
self.0.krate
168+
}
169+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
170+
self.1.default_span(tcx)
171+
}
172+
}
173+
152174
impl Key for (CrateNum, DefId) {
153175
type CacheSelector = DefaultCacheSelector;
154176

compiler/rustc_trait_selection/src/traits/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ pub use self::util::{
6565
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
6666
};
6767
pub use self::util::{
68-
supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
68+
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
69+
SupertraitDefIds, Supertraits,
6970
};
7071

7172
pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;

compiler/rustc_typeck/src/astconv/mod.rs

+57-11
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ pub trait AstConv<'tcx> {
4949

5050
fn default_constness_for_trait_bounds(&self) -> Constness;
5151

52-
/// Returns predicates in scope of the form `X: Foo`, where `X` is
53-
/// a type parameter `X` with the given id `def_id`. This is a
54-
/// subset of the full set of predicates.
52+
/// Returns predicates in scope of the form `X: Foo<T>`, where `X`
53+
/// is a type parameter `X` with the given id `def_id` and T
54+
/// matches `assoc_name`. This is a subset of the full set of
55+
/// predicates.
5556
///
5657
/// This is used for one specific purpose: resolving "short-hand"
5758
/// associated type references like `T::Item`. In principle, we
@@ -60,7 +61,12 @@ pub trait AstConv<'tcx> {
6061
/// but this can lead to cycle errors. The problem is that we have
6162
/// to do this resolution *in order to create the predicates in
6263
/// the first place*. Hence, we have this "special pass".
63-
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>;
64+
fn get_type_parameter_bounds(
65+
&self,
66+
span: Span,
67+
def_id: DefId,
68+
assoc_name: Ident,
69+
) -> ty::GenericPredicates<'tcx>;
6470

6571
/// Returns the lifetime to use when a lifetime is omitted (and not elided).
6672
fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
@@ -764,7 +770,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
764770
}
765771

766772
// Returns `true` if a bounds list includes `?Sized`.
767-
pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
773+
pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> bool {
768774
let tcx = self.tcx();
769775

770776
// Try to find an unbound in bounds.
@@ -822,7 +828,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
822828
fn add_bounds(
823829
&self,
824830
param_ty: Ty<'tcx>,
825-
ast_bounds: &[hir::GenericBound<'_>],
831+
ast_bounds: &[&hir::GenericBound<'_>],
826832
bounds: &mut Bounds<'tcx>,
827833
) {
828834
let constness = self.default_constness_for_trait_bounds();
@@ -837,7 +843,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
837843
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
838844
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
839845
.instantiate_lang_item_trait_ref(
840-
lang_item, span, hir_id, args, param_ty, bounds,
846+
*lang_item, *span, *hir_id, args, param_ty, bounds,
841847
),
842848
hir::GenericBound::Outlives(ref l) => bounds
843849
.region_bounds
@@ -868,6 +874,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
868874
ast_bounds: &[hir::GenericBound<'_>],
869875
sized_by_default: SizedByDefault,
870876
span: Span,
877+
) -> Bounds<'tcx> {
878+
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
879+
self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
880+
}
881+
882+
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
883+
/// named `assoc_name` into ty::Bounds. Ignore the rest.
884+
pub fn compute_bounds_that_match_assoc_type(
885+
&self,
886+
param_ty: Ty<'tcx>,
887+
ast_bounds: &[hir::GenericBound<'_>],
888+
sized_by_default: SizedByDefault,
889+
span: Span,
890+
assoc_name: Ident,
891+
) -> Bounds<'tcx> {
892+
let mut result = Vec::new();
893+
894+
for ast_bound in ast_bounds {
895+
if let Some(trait_ref) = ast_bound.trait_ref() {
896+
if let Some(trait_did) = trait_ref.trait_def_id() {
897+
if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) {
898+
result.push(ast_bound);
899+
}
900+
}
901+
}
902+
}
903+
904+
self.compute_bounds_inner(param_ty, &result, sized_by_default, span)
905+
}
906+
907+
fn compute_bounds_inner(
908+
&self,
909+
param_ty: Ty<'tcx>,
910+
ast_bounds: &[&hir::GenericBound<'_>],
911+
sized_by_default: SizedByDefault,
912+
span: Span,
871913
) -> Bounds<'tcx> {
872914
let mut bounds = Bounds::default();
873915

@@ -1037,7 +1079,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10371079
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
10381080
// parameter to have a skipped binder.
10391081
let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
1040-
self.add_bounds(param_ty, ast_bounds, bounds);
1082+
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
1083+
self.add_bounds(param_ty, &ast_bounds, bounds);
10411084
}
10421085
}
10431086
Ok(())
@@ -1354,21 +1397,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13541397
ty_param_def_id, assoc_name, span,
13551398
);
13561399

1357-
let predicates =
1358-
&self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
1400+
let predicates = &self
1401+
.get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name)
1402+
.predicates;
13591403

13601404
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
13611405

13621406
let param_hir_id = tcx.hir().local_def_id_to_hir_id(ty_param_def_id);
13631407
let param_name = tcx.hir().ty_param_name(param_hir_id);
13641408
self.one_bound_for_assoc_type(
13651409
|| {
1366-
traits::transitive_bounds(
1410+
traits::transitive_bounds_that_define_assoc_type(
13671411
tcx,
13681412
predicates.iter().filter_map(|(p, _)| {
13691413
p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value)
13701414
}),
1415+
assoc_name,
13711416
)
1417+
.into_iter()
13721418
},
13731419
|| param_name.to_string(),
13741420
assoc_name,

compiler/rustc_typeck/src/check/fn_ctxt/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_middle::ty::fold::TypeFoldable;
2020
use rustc_middle::ty::subst::GenericArgKind;
2121
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
2222
use rustc_session::Session;
23+
use rustc_span::symbol::Ident;
2324
use rustc_span::{self, Span};
2425
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
2526

@@ -183,7 +184,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
183184
}
184185
}
185186

186-
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
187+
fn get_type_parameter_bounds(
188+
&self,
189+
_: Span,
190+
def_id: DefId,
191+
_: Ident,
192+
) -> ty::GenericPredicates<'tcx> {
187193
let tcx = self.tcx;
188194
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
189195
let item_id = tcx.hir().ty_param_owner(hir_id);

0 commit comments

Comments
 (0)