Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7aa602b

Browse files
committedFeb 5, 2021
Revert "Auto merge of #79637 - spastorino:revert-trait-inheritance-self, r=Mark-Simulacrum"
This reverts commit b4def89, reversing changes made to 7dc1e85.
1 parent 23adf9f commit 7aa602b

28 files changed

+499
-151
lines changed
 

‎compiler/rustc_infer/src/traits/util.rs

Lines changed: 33 additions & 1 deletion
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>,
@@ -282,6 +283,37 @@ pub fn transitive_bounds<'tcx>(
282283
elaborate_trait_refs(tcx, bounds).filter_to_traits()
283284
}
284285

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

‎compiler/rustc_middle/src/query/mod.rs

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

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

‎compiler/rustc_middle/src/ty/context.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
5252
use rustc_session::lint::{Level, Lint};
5353
use rustc_session::Session;
5454
use rustc_span::source_map::MultiSpan;
55-
use rustc_span::symbol::{kw, sym, Symbol};
55+
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5656
use rustc_span::{Span, DUMMY_SP};
5757
use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
5858
use rustc_target::spec::abi;
@@ -2053,6 +2053,42 @@ impl<'tcx> TyCtxt<'tcx> {
20532053
self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
20542054
}
20552055

2056+
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
2057+
/// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
2058+
pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
2059+
self.super_traits_of(trait_def_id).any(|trait_did| {
2060+
self.associated_items(trait_did)
2061+
.find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
2062+
.is_some()
2063+
})
2064+
}
2065+
2066+
/// Computes the def-ids of the transitive super-traits of `trait_def_id`. This (intentionally)
2067+
/// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
2068+
/// to identify which traits may define a given associated type to help avoid cycle errors.
2069+
/// Returns a `DefId` iterator.
2070+
fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
2071+
let mut set = FxHashSet::default();
2072+
let mut stack = vec![trait_def_id];
2073+
2074+
set.insert(trait_def_id);
2075+
2076+
iter::from_fn(move || -> Option<DefId> {
2077+
let trait_did = stack.pop()?;
2078+
let generic_predicates = self.super_predicates_of(trait_did);
2079+
2080+
for (predicate, _) in generic_predicates.predicates {
2081+
if let ty::PredicateAtom::Trait(data, _) = predicate.skip_binders() {
2082+
if set.insert(data.def_id()) {
2083+
stack.push(data.def_id());
2084+
}
2085+
}
2086+
}
2087+
2088+
Some(trait_did)
2089+
})
2090+
}
2091+
20562092
/// Given a closure signature, returns an equivalent fn signature. Detuples
20572093
/// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
20582094
/// you would get a `fn(u32, i32)`.

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

Lines changed: 23 additions & 1 deletion
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
@@ -160,6 +160,28 @@ impl Key for (LocalDefId, DefId) {
160160
}
161161
}
162162

163+
impl Key for (DefId, Option<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+
tcx.def_span(self.0)
171+
}
172+
}
173+
174+
impl Key for (DefId, LocalDefId, Ident) {
175+
type CacheSelector = DefaultCacheSelector;
176+
177+
fn query_crate(&self) -> CrateNum {
178+
self.0.krate
179+
}
180+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
181+
self.1.default_span(tcx)
182+
}
183+
}
184+
163185
impl Key for (CrateNum, DefId) {
164186
type CacheSelector = DefaultCacheSelector;
165187

‎compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 2 additions & 1 deletion
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

Lines changed: 57 additions & 11 deletions
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)
@@ -792,7 +798,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
792798
}
793799

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

798804
// Try to find an unbound in bounds.
@@ -850,7 +856,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
850856
fn add_bounds(
851857
&self,
852858
param_ty: Ty<'tcx>,
853-
ast_bounds: &[hir::GenericBound<'_>],
859+
ast_bounds: &[&hir::GenericBound<'_>],
854860
bounds: &mut Bounds<'tcx>,
855861
) {
856862
let constness = self.default_constness_for_trait_bounds();
@@ -865,7 +871,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
865871
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
866872
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
867873
.instantiate_lang_item_trait_ref(
868-
lang_item, span, hir_id, args, param_ty, bounds,
874+
*lang_item, *span, *hir_id, args, param_ty, bounds,
869875
),
870876
hir::GenericBound::Outlives(ref l) => bounds
871877
.region_bounds
@@ -896,6 +902,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
896902
ast_bounds: &[hir::GenericBound<'_>],
897903
sized_by_default: SizedByDefault,
898904
span: Span,
905+
) -> Bounds<'tcx> {
906+
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
907+
self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
908+
}
909+
910+
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
911+
/// named `assoc_name` into ty::Bounds. Ignore the rest.
912+
pub fn compute_bounds_that_match_assoc_type(
913+
&self,
914+
param_ty: Ty<'tcx>,
915+
ast_bounds: &[hir::GenericBound<'_>],
916+
sized_by_default: SizedByDefault,
917+
span: Span,
918+
assoc_name: Ident,
919+
) -> Bounds<'tcx> {
920+
let mut result = Vec::new();
921+
922+
for ast_bound in ast_bounds {
923+
if let Some(trait_ref) = ast_bound.trait_ref() {
924+
if let Some(trait_did) = trait_ref.trait_def_id() {
925+
if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) {
926+
result.push(ast_bound);
927+
}
928+
}
929+
}
930+
}
931+
932+
self.compute_bounds_inner(param_ty, &result, sized_by_default, span)
933+
}
934+
935+
fn compute_bounds_inner(
936+
&self,
937+
param_ty: Ty<'tcx>,
938+
ast_bounds: &[&hir::GenericBound<'_>],
939+
sized_by_default: SizedByDefault,
940+
span: Span,
899941
) -> Bounds<'tcx> {
900942
let mut bounds = Bounds::default();
901943

@@ -1098,7 +1140,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10981140
// parameter to have a skipped binder.
10991141
let param_ty =
11001142
tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs);
1101-
self.add_bounds(param_ty, ast_bounds, bounds);
1143+
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
1144+
self.add_bounds(param_ty, &ast_bounds, bounds);
11021145
}
11031146
}
11041147
Ok(())
@@ -1413,21 +1456,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14131456
ty_param_def_id, assoc_name, span,
14141457
);
14151458

1416-
let predicates =
1417-
&self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
1459+
let predicates = &self
1460+
.get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name)
1461+
.predicates;
14181462

14191463
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
14201464

14211465
let param_hir_id = tcx.hir().local_def_id_to_hir_id(ty_param_def_id);
14221466
let param_name = tcx.hir().ty_param_name(param_hir_id);
14231467
self.one_bound_for_assoc_type(
14241468
|| {
1425-
traits::transitive_bounds(
1469+
traits::transitive_bounds_that_define_assoc_type(
14261470
tcx,
14271471
predicates.iter().filter_map(|(p, _)| {
14281472
p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value)
14291473
}),
1474+
assoc_name,
14301475
)
1476+
.into_iter()
14311477
},
14321478
|| param_name.to_string(),
14331479
assoc_name,

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

Lines changed: 7 additions & 1 deletion
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);

‎compiler/rustc_typeck/src/collect.rs

Lines changed: 133 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// ignore-tidy-filelength
12
//! "Collection" is the process of determining the type and other external
23
//! details of each item in Rust. Collection is specifically concerned
34
//! with *inter-procedural* things -- for example, for a function
@@ -77,6 +78,7 @@ pub fn provide(providers: &mut Providers) {
7778
projection_ty_from_predicates,
7879
explicit_predicates_of,
7980
super_predicates_of,
81+
super_predicates_that_define_assoc_type,
8082
trait_explicit_predicates_and_bounds,
8183
type_param_predicates,
8284
trait_def,
@@ -308,8 +310,17 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
308310
}
309311
}
310312

311-
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
312-
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id.expect_local()))
313+
fn get_type_parameter_bounds(
314+
&self,
315+
span: Span,
316+
def_id: DefId,
317+
assoc_name: Ident,
318+
) -> ty::GenericPredicates<'tcx> {
319+
self.tcx.at(span).type_param_predicates((
320+
self.item_def_id,
321+
def_id.expect_local(),
322+
assoc_name,
323+
))
313324
}
314325

315326
fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
@@ -490,7 +501,7 @@ fn get_new_lifetime_name<'tcx>(
490501
/// `X: Foo` where `X` is the type parameter `def_id`.
491502
fn type_param_predicates(
492503
tcx: TyCtxt<'_>,
493-
(item_def_id, def_id): (DefId, LocalDefId),
504+
(item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
494505
) -> ty::GenericPredicates<'_> {
495506
use rustc_hir::*;
496507

@@ -515,7 +526,7 @@ fn type_param_predicates(
515526
let mut result = parent
516527
.map(|parent| {
517528
let icx = ItemCtxt::new(tcx, parent);
518-
icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id())
529+
icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name)
519530
})
520531
.unwrap_or_default();
521532
let mut extend = None;
@@ -558,12 +569,18 @@ fn type_param_predicates(
558569

559570
let icx = ItemCtxt::new(tcx, item_def_id);
560571
let extra_predicates = extend.into_iter().chain(
561-
icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
562-
.into_iter()
563-
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
564-
ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
565-
_ => false,
566-
}),
572+
icx.type_parameter_bounds_in_generics(
573+
ast_generics,
574+
param_id,
575+
ty,
576+
OnlySelfBounds(true),
577+
Some(assoc_name),
578+
)
579+
.into_iter()
580+
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
581+
ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index),
582+
_ => false,
583+
}),
567584
);
568585
result.predicates =
569586
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates));
@@ -581,6 +598,7 @@ impl ItemCtxt<'tcx> {
581598
param_id: hir::HirId,
582599
ty: Ty<'tcx>,
583600
only_self_bounds: OnlySelfBounds,
601+
assoc_name: Option<Ident>,
584602
) -> Vec<(ty::Predicate<'tcx>, Span)> {
585603
let constness = self.default_constness_for_trait_bounds();
586604
let from_ty_params = ast_generics
@@ -591,6 +609,10 @@ impl ItemCtxt<'tcx> {
591609
_ => None,
592610
})
593611
.flat_map(|bounds| bounds.iter())
612+
.filter(|b| match assoc_name {
613+
Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
614+
None => true,
615+
})
594616
.flat_map(|b| predicates_from_bound(self, ty, b, constness));
595617

596618
let from_where_clauses = ast_generics
@@ -609,12 +631,34 @@ impl ItemCtxt<'tcx> {
609631
} else {
610632
None
611633
};
612-
bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
634+
bp.bounds
635+
.iter()
636+
.filter(|b| match assoc_name {
637+
Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
638+
None => true,
639+
})
640+
.filter_map(move |b| bt.map(|bt| (bt, b)))
613641
})
614642
.flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness));
615643

616644
from_ty_params.chain(from_where_clauses).collect()
617645
}
646+
647+
fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
648+
debug!("bound_defines_assoc_item(b={:?}, assoc_name={:?})", b, assoc_name);
649+
650+
match b {
651+
hir::GenericBound::Trait(poly_trait_ref, _) => {
652+
let trait_ref = &poly_trait_ref.trait_ref;
653+
if let Some(trait_did) = trait_ref.trait_def_id() {
654+
self.tcx.trait_may_define_assoc_type(trait_did, assoc_name)
655+
} else {
656+
false
657+
}
658+
}
659+
_ => false,
660+
}
661+
}
618662
}
619663

620664
/// Tests whether this is the AST for a reference to the type
@@ -983,54 +1027,91 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
9831027
/// the transitive super-predicates are converted.
9841028
fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> {
9851029
debug!("super_predicates(trait_def_id={:?})", trait_def_id);
986-
let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
1030+
tcx.super_predicates_that_define_assoc_type((trait_def_id, None))
1031+
}
9871032

988-
let item = match tcx.hir().get(trait_hir_id) {
989-
Node::Item(item) => item,
990-
_ => bug!("trait_node_id {} is not an item", trait_hir_id),
991-
};
1033+
/// Ensures that the super-predicates of the trait with a `DefId`
1034+
/// of `trait_def_id` are converted and stored. This also ensures that
1035+
/// the transitive super-predicates are converted.
1036+
fn super_predicates_that_define_assoc_type(
1037+
tcx: TyCtxt<'_>,
1038+
(trait_def_id, assoc_name): (DefId, Option<Ident>),
1039+
) -> ty::GenericPredicates<'_> {
1040+
debug!(
1041+
"super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})",
1042+
trait_def_id, assoc_name
1043+
);
1044+
if trait_def_id.is_local() {
1045+
debug!("super_predicates_that_define_assoc_type: local trait_def_id={:?}", trait_def_id);
1046+
let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
9921047

993-
let (generics, bounds) = match item.kind {
994-
hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
995-
hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
996-
_ => span_bug!(item.span, "super_predicates invoked on non-trait"),
997-
};
1048+
let item = match tcx.hir().get(trait_hir_id) {
1049+
Node::Item(item) => item,
1050+
_ => bug!("trait_node_id {} is not an item", trait_hir_id),
1051+
};
9981052

999-
let icx = ItemCtxt::new(tcx, trait_def_id);
1000-
1001-
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
1002-
let self_param_ty = tcx.types.self_param;
1003-
let superbounds1 =
1004-
AstConv::compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span);
1005-
1006-
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
1007-
1008-
// Convert any explicit superbounds in the where-clause,
1009-
// e.g., `trait Foo where Self: Bar`.
1010-
// In the case of trait aliases, however, we include all bounds in the where-clause,
1011-
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
1012-
// as one of its "superpredicates".
1013-
let is_trait_alias = tcx.is_trait_alias(trait_def_id);
1014-
let superbounds2 = icx.type_parameter_bounds_in_generics(
1015-
generics,
1016-
item.hir_id,
1017-
self_param_ty,
1018-
OnlySelfBounds(!is_trait_alias),
1019-
);
1053+
let (generics, bounds) = match item.kind {
1054+
hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
1055+
hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
1056+
_ => span_bug!(item.span, "super_predicates invoked on non-trait"),
1057+
};
1058+
1059+
let icx = ItemCtxt::new(tcx, trait_def_id);
1060+
1061+
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
1062+
let self_param_ty = tcx.types.self_param;
1063+
let superbounds1 = if let Some(assoc_name) = assoc_name {
1064+
AstConv::compute_bounds_that_match_assoc_type(
1065+
&icx,
1066+
self_param_ty,
1067+
&bounds,
1068+
SizedByDefault::No,
1069+
item.span,
1070+
assoc_name,
1071+
)
1072+
} else {
1073+
AstConv::compute_bounds(&icx, self_param_ty, &bounds, SizedByDefault::No, item.span)
1074+
};
10201075

1021-
// Combine the two lists to form the complete set of superbounds:
1022-
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
1076+
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
1077+
1078+
// Convert any explicit superbounds in the where-clause,
1079+
// e.g., `trait Foo where Self: Bar`.
1080+
// In the case of trait aliases, however, we include all bounds in the where-clause,
1081+
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
1082+
// as one of its "superpredicates".
1083+
let is_trait_alias = tcx.is_trait_alias(trait_def_id);
1084+
let superbounds2 = icx.type_parameter_bounds_in_generics(
1085+
generics,
1086+
item.hir_id,
1087+
self_param_ty,
1088+
OnlySelfBounds(!is_trait_alias),
1089+
assoc_name,
1090+
);
10231091

1024-
// Now require that immediate supertraits are converted,
1025-
// which will, in turn, reach indirect supertraits.
1026-
for &(pred, span) in superbounds {
1027-
debug!("superbound: {:?}", pred);
1028-
if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
1029-
tcx.at(span).super_predicates_of(bound.def_id());
1092+
// Combine the two lists to form the complete set of superbounds:
1093+
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
1094+
1095+
// Now require that immediate supertraits are converted,
1096+
// which will, in turn, reach indirect supertraits.
1097+
if assoc_name.is_none() {
1098+
// Now require that immediate supertraits are converted,
1099+
// which will, in turn, reach indirect supertraits.
1100+
for &(pred, span) in superbounds {
1101+
debug!("superbound: {:?}", pred);
1102+
if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
1103+
tcx.at(span).super_predicates_of(bound.def_id());
1104+
}
1105+
}
10301106
}
1031-
}
10321107

1033-
ty::GenericPredicates { parent: None, predicates: superbounds }
1108+
ty::GenericPredicates { parent: None, predicates: superbounds }
1109+
} else {
1110+
// if `assoc_name` is None, then the query should've been redirected to an
1111+
// external provider
1112+
assert!(assoc_name.is_some());
1113+
tcx.super_predicates_of(trait_def_id)
1114+
}
10341115
}
10351116

10361117
fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {

‎compiler/rustc_typeck/src/collect/item_bounds.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>(
2828
let bounds = AstConv::compute_bounds(
2929
&ItemCtxt::new(tcx, assoc_item_def_id),
3030
item_ty,
31-
bounds,
31+
&bounds,
3232
SizedByDefault::Yes,
3333
span,
3434
);
@@ -69,7 +69,7 @@ fn opaque_type_bounds<'tcx>(
6969
let bounds = AstConv::compute_bounds(
7070
&ItemCtxt::new(tcx, opaque_def_id),
7171
item_ty,
72-
bounds,
72+
&bounds,
7373
SizedByDefault::Yes,
7474
span,
7575
)

‎src/test/incremental/cyclic-trait-hierarchy.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
// revisions: rpass1 cfail2
44

55
#[cfg(rpass1)]
6-
pub trait T2 { }
6+
pub trait T2 {}
77
#[cfg(cfail2)]
8-
pub trait T2: T1 { }
9-
//[cfail2]~^ ERROR cycle detected when computing the supertraits of `T2`
8+
pub trait T2: T1 {}
9+
//[cfail2]~^ ERROR cycle detected when computing the super predicates of `T2`
1010

11-
pub trait T1: T2 { }
11+
pub trait T1: T2 {}
1212

13-
fn main() { }
13+
fn main() {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// ignore-tidy-linelength
2+
3+
trait Foo {
4+
type Item;
5+
}
6+
trait Bar<T> {
7+
type Item;
8+
}
9+
trait Baz: Foo + Bar<Self::Item> {}
10+
//~^ ERROR cycle detected when computing the super traits of `Baz` with associated type name `Item` [E0391]
11+
12+
fn main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0391]: cycle detected when computing the super traits of `Baz` with associated type name `Item`
2+
--> $DIR/ambiguous-associated-type2.rs:9:1
3+
|
4+
LL | trait Baz: Foo + Bar<Self::Item> {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: ...which again requires computing the super traits of `Baz` with associated type name `Item`, completing the cycle
8+
note: cycle used when computing the super traits of `Baz`
9+
--> $DIR/ambiguous-associated-type2.rs:9:1
10+
|
11+
LL | trait Baz: Foo + Bar<Self::Item> {}
12+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0391`.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// check-pass
2+
3+
trait Foo {
4+
type Item;
5+
}
6+
7+
trait Bar
8+
where
9+
Self: Foo,
10+
{
11+
}
12+
13+
#[allow(dead_code)]
14+
fn foo<M>(_m: M)
15+
where
16+
M: Bar,
17+
M::Item: Send,
18+
{
19+
}
20+
21+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// check-pass
2+
3+
trait Foo<T> {}
4+
trait Bar {
5+
type A;
6+
type B;
7+
}
8+
trait Baz: Bar<B = u32> + Foo<Self::A> {}
9+
10+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#[allow(dead_code)]
2+
fn foo<M>(_m: M)
3+
where
4+
M::Item: Temp,
5+
//~^ ERROR cannot find trait `Temp` in this scope [E0405]
6+
//~| ERROR associated type `Item` not found for `M` [E0220]
7+
{
8+
}
9+
10+
fn main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0405]: cannot find trait `Temp` in this scope
2+
--> $DIR/missing-trait-bound-for-assoc-fails.rs:4:14
3+
|
4+
LL | M::Item: Temp,
5+
| ^^^^ not found in this scope
6+
7+
error[E0220]: associated type `Item` not found for `M`
8+
--> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8
9+
|
10+
LL | M::Item: Temp,
11+
| ^^^^ associated type `Item` not found
12+
13+
error: aborting due to 2 previous errors
14+
15+
Some errors have detailed explanations: E0220, E0405.
16+
For more information about an error, try `rustc --explain E0220`.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// check-pass
2+
trait Foo {
3+
type Bar;
4+
}
5+
trait Qux: Foo + AsRef<Self::Bar> {}
6+
trait Foo2 {}
7+
8+
trait Qux2: Foo2 + AsRef<Self::Bar> {
9+
type Bar;
10+
}
11+
12+
fn main() {}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
3+
// The goal of this test is to ensure that T: Bar<T::Item>
4+
// in the where clause does not cycle
5+
6+
trait Foo {
7+
type Item;
8+
}
9+
10+
trait Bar<T> {}
11+
12+
fn baz<T>()
13+
where
14+
T: Foo,
15+
T: Bar<T::Item>,
16+
{
17+
}
18+
19+
fn main() {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// check-pass
2+
3+
// Test that we do not get a cycle due to
4+
// resolving `Self::Bar` in the where clauses
5+
// on a trait definition (in particular, in
6+
// a where clause that is defining a superpredicate).
7+
8+
trait Foo {
9+
type Bar;
10+
}
11+
trait Qux
12+
where
13+
Self: Foo,
14+
Self: AsRef<Self::Bar>,
15+
{
16+
}
17+
trait Foo2 {}
18+
19+
trait Qux2
20+
where
21+
Self: Foo2,
22+
Self: AsRef<Self::Bar>,
23+
{
24+
type Bar;
25+
}
26+
27+
fn main() {}

‎src/test/ui/cycle-projection-based-on-where-clause.rs

Lines changed: 0 additions & 24 deletions
This file was deleted.

‎src/test/ui/cycle-projection-based-on-where-clause.stderr

Lines changed: 0 additions & 16 deletions
This file was deleted.

‎src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
error[E0391]: cycle detected when computing the supertraits of `Chromosome`
1+
error[E0391]: cycle detected when computing the super predicates of `Chromosome`
2+
--> $DIR/cycle-trait-supertrait-direct.rs:3:1
3+
|
4+
LL | trait Chromosome: Chromosome {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: ...which requires computing the super traits of `Chromosome`...
28
--> $DIR/cycle-trait-supertrait-direct.rs:3:19
39
|
410
LL | trait Chromosome: Chromosome {
511
| ^^^^^^^^^^
6-
|
7-
= note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle
12+
= note: ...which again requires computing the super predicates of `Chromosome`, completing the cycle
813
note: cycle used when collecting item types in top-level module
914
--> $DIR/cycle-trait-supertrait-direct.rs:3:1
1015
|

‎src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
1-
error[E0391]: cycle detected when computing the supertraits of `B`
1+
error[E0391]: cycle detected when computing the super predicates of `B`
2+
--> $DIR/cycle-trait-supertrait-indirect.rs:7:1
3+
|
4+
LL | trait B: C {
5+
| ^^^^^^^^^^
6+
|
7+
note: ...which requires computing the super traits of `B`...
28
--> $DIR/cycle-trait-supertrait-indirect.rs:7:10
39
|
410
LL | trait B: C {
511
| ^
12+
note: ...which requires computing the super predicates of `C`...
13+
--> $DIR/cycle-trait-supertrait-indirect.rs:11:1
614
|
7-
note: ...which requires computing the supertraits of `C`...
15+
LL | trait C: B { }
16+
| ^^^^^^^^^^
17+
note: ...which requires computing the super traits of `C`...
818
--> $DIR/cycle-trait-supertrait-indirect.rs:11:10
919
|
1020
LL | trait C: B { }
1121
| ^
12-
= note: ...which again requires computing the supertraits of `B`, completing the cycle
13-
note: cycle used when computing the supertraits of `A`
22+
= note: ...which again requires computing the super predicates of `B`, completing the cycle
23+
note: cycle used when computing the super traits of `A`
1424
--> $DIR/cycle-trait-supertrait-indirect.rs:4:10
1525
|
1626
LL | trait A: B {

‎src/test/ui/issues/issue-12511.stderr

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
1-
error[E0391]: cycle detected when computing the supertraits of `T1`
1+
error[E0391]: cycle detected when computing the super predicates of `T1`
2+
--> $DIR/issue-12511.rs:1:1
3+
|
4+
LL | trait T1 : T2 {
5+
| ^^^^^^^^^^^^^
6+
|
7+
note: ...which requires computing the super traits of `T1`...
28
--> $DIR/issue-12511.rs:1:12
39
|
410
LL | trait T1 : T2 {
511
| ^^
12+
note: ...which requires computing the super predicates of `T2`...
13+
--> $DIR/issue-12511.rs:5:1
614
|
7-
note: ...which requires computing the supertraits of `T2`...
15+
LL | trait T2 : T1 {
16+
| ^^^^^^^^^^^^^
17+
note: ...which requires computing the super traits of `T2`...
818
--> $DIR/issue-12511.rs:5:12
919
|
1020
LL | trait T2 : T1 {
1121
| ^^
12-
= note: ...which again requires computing the supertraits of `T1`, completing the cycle
22+
= note: ...which again requires computing the super predicates of `T1`, completing the cycle
1323
note: cycle used when collecting item types in top-level module
1424
--> $DIR/issue-12511.rs:1:1
1525
|

‎src/test/ui/issues/issue-20772.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
error[E0391]: cycle detected when computing the supertraits of `T`
1+
error[E0391]: cycle detected when computing the super traits of `T` with associated type name `Item`
22
--> $DIR/issue-20772.rs:1:1
33
|
44
LL | / trait T : Iterator<Item=Self::Item>
55
LL | |
66
LL | | {}
77
| |__^
88
|
9-
= note: ...which again requires computing the supertraits of `T`, completing the cycle
10-
note: cycle used when collecting item types in top-level module
9+
= note: ...which again requires computing the super traits of `T` with associated type name `Item`, completing the cycle
10+
note: cycle used when computing the super traits of `T`
1111
--> $DIR/issue-20772.rs:1:1
1212
|
1313
LL | / trait T : Iterator<Item=Self::Item>

‎src/test/ui/issues/issue-20825.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
error[E0391]: cycle detected when computing the supertraits of `Processor`
1+
error[E0391]: cycle detected when computing the super traits of `Processor` with associated type name `Input`
22
--> $DIR/issue-20825.rs:5:1
33
|
44
LL | pub trait Processor: Subscriber<Input = Self::Input> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: ...which again requires computing the supertraits of `Processor`, completing the cycle
8-
note: cycle used when collecting item types in top-level module
7+
= note: ...which again requires computing the super traits of `Processor` with associated type name `Input`, completing the cycle
8+
note: cycle used when computing the super traits of `Processor`
99
--> $DIR/issue-20825.rs:5:1
1010
|
1111
LL | pub trait Processor: Subscriber<Input = Self::Input> {

‎src/test/ui/issues/issue-22673.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
trait Expr : PartialEq<Self::Item> {
2-
//~^ ERROR: cycle detected
1+
// check-pass
2+
3+
trait Expr: PartialEq<Self::Item> {
34
type Item;
45
}
56

‎src/test/ui/issues/issue-22673.stderr

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.