Skip to content

Commit 25c342f

Browse files
Split implied and super predicate queries
1 parent 3dab259 commit 25c342f

File tree

16 files changed

+125
-96
lines changed

16 files changed

+125
-96
lines changed

compiler/rustc_hir_analysis/src/collect.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ pub fn provide(providers: &mut Providers) {
6464
predicates_defined_on,
6565
explicit_predicates_of: predicates_of::explicit_predicates_of,
6666
super_predicates_of: predicates_of::super_predicates_of,
67-
super_predicates_that_define_assoc_type: |tcx, (def_id, assoc_name)| {
68-
predicates_of::super_predicates_that_define_assoc_type(tcx, (def_id, Some(assoc_name)))
69-
},
67+
implied_predicates_of: predicates_of::implied_predicates_of,
68+
super_predicates_that_define_assoc_type:
69+
predicates_of::super_predicates_that_define_assoc_type,
7070
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
7171
type_param_predicates: predicates_of::type_param_predicates,
7272
trait_def,
@@ -597,6 +597,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
597597
}
598598
hir::ItemKind::TraitAlias(..) => {
599599
tcx.ensure().generics_of(def_id);
600+
tcx.at(it.span).implied_predicates_of(def_id);
600601
tcx.at(it.span).super_predicates_of(def_id);
601602
tcx.ensure().predicates_of(def_id);
602603
}

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+81-32
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
125125
// on a trait we need to add in the supertrait bounds and bounds found on
126126
// associated types.
127127
if let Some(_trait_ref) = is_trait {
128-
predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
128+
predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned());
129129
}
130130

131131
// In default impls, we can assume that the self type implements
@@ -534,31 +534,62 @@ pub(super) fn explicit_predicates_of<'tcx>(
534534
}
535535
}
536536

537+
#[derive(Copy, Clone, Debug)]
538+
pub enum PredicateFilter {
539+
/// All predicates may be implied by the trait
540+
All,
541+
542+
/// Only traits that reference `Self: ..` are implied by the trait
543+
SelfOnly,
544+
545+
/// Only traits that reference `Self: ..` and define an associated type
546+
/// with the given ident are implied by the trait
547+
SelfThatDefines(Ident),
548+
}
549+
537550
/// Ensures that the super-predicates of the trait with a `DefId`
538551
/// of `trait_def_id` are converted and stored. This also ensures that
539552
/// the transitive super-predicates are converted.
540553
pub(super) fn super_predicates_of(
541554
tcx: TyCtxt<'_>,
542555
trait_def_id: LocalDefId,
543556
) -> ty::GenericPredicates<'_> {
544-
tcx.super_predicates_that_define_assoc_type((trait_def_id.to_def_id(), None))
557+
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
558+
}
559+
560+
pub(super) fn super_predicates_that_define_assoc_type(
561+
tcx: TyCtxt<'_>,
562+
(trait_def_id, assoc_name): (DefId, Ident),
563+
) -> ty::GenericPredicates<'_> {
564+
implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name))
565+
}
566+
567+
pub(super) fn implied_predicates_of(
568+
tcx: TyCtxt<'_>,
569+
trait_def_id: LocalDefId,
570+
) -> ty::GenericPredicates<'_> {
571+
if tcx.is_trait_alias(trait_def_id.to_def_id()) {
572+
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
573+
} else {
574+
tcx.super_predicates_of(trait_def_id)
575+
}
545576
}
546577

547578
/// Ensures that the super-predicates of the trait with a `DefId`
548579
/// of `trait_def_id` are converted and stored. This also ensures that
549580
/// the transitive super-predicates are converted.
550-
pub(super) fn super_predicates_that_define_assoc_type(
581+
pub(super) fn implied_predicates_with_filter(
551582
tcx: TyCtxt<'_>,
552-
(trait_def_id, assoc_name): (DefId, Option<Ident>),
583+
trait_def_id: DefId,
584+
filter: PredicateFilter,
553585
) -> ty::GenericPredicates<'_> {
554586
let Some(trait_def_id) = trait_def_id.as_local() else {
555587
// if `assoc_name` is None, then the query should've been redirected to an
556588
// external provider
557-
assert!(assoc_name.is_some());
589+
assert!(matches!(filter, PredicateFilter::SelfThatDefines(_)));
558590
return tcx.super_predicates_of(trait_def_id);
559591
};
560592

561-
debug!("local trait");
562593
let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id);
563594

564595
let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
@@ -573,48 +604,66 @@ pub(super) fn super_predicates_that_define_assoc_type(
573604

574605
let icx = ItemCtxt::new(tcx, trait_def_id);
575606

576-
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
577607
let self_param_ty = tcx.types.self_param;
578-
let superbounds1 = if let Some(assoc_name) = assoc_name {
579-
icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
580-
} else {
581-
icx.astconv().compute_bounds(self_param_ty, bounds)
608+
let (superbounds, where_bounds_that_match) = match filter {
609+
PredicateFilter::All => (
610+
// Convert the bounds that follow the colon (or equal in trait aliases)
611+
icx.astconv().compute_bounds(self_param_ty, bounds),
612+
// Also include all where clause bounds
613+
icx.type_parameter_bounds_in_generics(
614+
generics,
615+
item.owner_id.def_id,
616+
self_param_ty,
617+
OnlySelfBounds(false),
618+
None,
619+
),
620+
),
621+
PredicateFilter::SelfOnly => (
622+
// Convert the bounds that follow the colon (or equal in trait aliases)
623+
icx.astconv().compute_bounds(self_param_ty, bounds),
624+
// Include where clause bounds for `Self`
625+
icx.type_parameter_bounds_in_generics(
626+
generics,
627+
item.owner_id.def_id,
628+
self_param_ty,
629+
OnlySelfBounds(true),
630+
None,
631+
),
632+
),
633+
PredicateFilter::SelfThatDefines(assoc_name) => (
634+
// Convert the bounds that follow the colon (or equal) that reference the associated name
635+
icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name),
636+
// Include where clause bounds for `Self` that reference the associated name
637+
icx.type_parameter_bounds_in_generics(
638+
generics,
639+
item.owner_id.def_id,
640+
self_param_ty,
641+
OnlySelfBounds(true),
642+
Some(assoc_name),
643+
),
644+
),
582645
};
583646

584-
let superbounds1 = superbounds1.predicates();
585-
586-
// Convert any explicit superbounds in the where-clause,
587-
// e.g., `trait Foo where Self: Bar`.
588-
// In the case of trait aliases, however, we include all bounds in the where-clause,
589-
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
590-
// as one of its "superpredicates".
591-
let is_trait_alias = tcx.is_trait_alias(trait_def_id.to_def_id());
592-
let superbounds2 = icx.type_parameter_bounds_in_generics(
593-
generics,
594-
item.owner_id.def_id,
595-
self_param_ty,
596-
OnlySelfBounds(!is_trait_alias),
597-
assoc_name,
598-
);
599-
600647
// Combine the two lists to form the complete set of superbounds:
601-
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
602-
debug!(?superbounds);
648+
let implied_bounds = &*tcx
649+
.arena
650+
.alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match));
651+
debug!(?implied_bounds);
603652

604653
// Now require that immediate supertraits are converted,
605654
// which will, in turn, reach indirect supertraits.
606-
if assoc_name.is_none() {
655+
if matches!(filter, PredicateFilter::SelfOnly) {
607656
// Now require that immediate supertraits are converted,
608657
// which will, in turn, reach indirect supertraits.
609-
for &(pred, span) in superbounds {
658+
for &(pred, span) in implied_bounds {
610659
debug!("superbound: {:?}", pred);
611660
if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() {
612661
tcx.at(span).super_predicates_of(bound.def_id());
613662
}
614663
}
615664
}
616665

617-
ty::GenericPredicates { parent: None, predicates: superbounds }
666+
ty::GenericPredicates { parent: None, predicates: implied_bounds }
618667
}
619668

620669
/// Returns the predicates defined on `item_def_id` of the form

compiler/rustc_infer/src/traits/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
192192
match bound_predicate.skip_binder() {
193193
ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
194194
// Get predicates declared on the trait.
195-
let predicates = tcx.super_predicates_of(data.def_id());
195+
let predicates = tcx.implied_predicates_of(data.def_id());
196196

197197
let obligations =
198198
predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| {

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,19 @@ provide! { tcx, def_id, other, cdata,
253253
.get(cdata, def_id.index)
254254
.map(|lazy| lazy.decode((cdata, tcx)))
255255
.process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
256-
}
256+
}
257+
implied_predicates_of => {
258+
cdata
259+
.root
260+
.tables
261+
.implied_predicates_of
262+
.get(cdata, def_id.index)
263+
.map(|lazy| lazy.decode((cdata, tcx)))
264+
.unwrap_or_else(|| {
265+
debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
266+
tcx.super_predicates_of(def_id)
267+
})
268+
}
257269

258270
associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array }
259271

compiler/rustc_metadata/src/rmeta/encoder.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1316,9 +1316,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13161316
let default = self.tcx.object_lifetime_default(def_id);
13171317
record!(self.tables.object_lifetime_default[def_id] <- default);
13181318
}
1319-
if let DefKind::Trait | DefKind::TraitAlias = def_kind {
1319+
if let DefKind::Trait = def_kind {
13201320
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
13211321
}
1322+
if let DefKind::TraitAlias = def_kind {
1323+
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
1324+
record!(self.tables.implied_predicates_of[def_id] <- self.tcx.implied_predicates_of(def_id));
1325+
}
13221326
if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
13231327
self.encode_info_for_adt(def_id);
13241328
}

compiler/rustc_metadata/src/rmeta/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,9 @@ define_tables! {
372372
explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
373373
generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
374374
super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
375+
// As an optimization, we only store this for trait aliases,
376+
// since it's identical to super_predicates_of for traits.
377+
implied_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
375378
type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<Ty<'static>>>>,
376379
variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
377380
fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
@@ -383,7 +386,6 @@ define_tables! {
383386
mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
384387
mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>,
385388
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
386-
// FIXME(compiler-errors): Why isn't this a LazyArray?
387389
thir_abstract_const: Table<DefIndex, LazyValue<ty::Const<'static>>>,
388390
impl_parent: Table<DefIndex, RawDefId>,
389391
impl_polarity: Table<DefIndex, ty::ImplPolarity>,

compiler/rustc_middle/src/query/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,12 @@ rustc_queries! {
627627
separate_provide_extern
628628
}
629629

630+
query implied_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
631+
desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) }
632+
cache_on_disk_if { key.is_local() }
633+
separate_provide_extern
634+
}
635+
630636
/// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
631637
/// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
632638
/// subset of super-predicates that reference traits that define the given associated type.

compiler/rustc_trait_selection/src/traits/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
115115
}
116116

117117
// Get components of trait alias.
118-
let predicates = tcx.super_predicates_of(trait_ref.def_id());
118+
let predicates = tcx.implied_predicates_of(trait_ref.def_id());
119119
debug!(?predicates);
120120

121121
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {

tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | trait Baz: Foo + Bar<Self::Item> {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: ...which immediately requires computing the super traits of `Baz` with associated type name `Item` again
8-
note: cycle used when computing the super traits of `Baz`
8+
note: cycle used when computing the super predicates of `Baz`
99
--> $DIR/ambiguous-associated-type2.rs:7:1
1010
|
1111
LL | trait Baz: Foo + Bar<Self::Item> {}

tests/ui/associated-types/issue-20825.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | pub trait Processor: Subscriber<Input = Self::Input> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: ...which immediately requires computing the super traits of `Processor` with associated type name `Input` again
8-
note: cycle used when computing the super traits of `Processor`
8+
note: cycle used when computing the super predicates of `Processor`
99
--> $DIR/issue-20825.rs:5:1
1010
|
1111
LL | pub trait Processor: Subscriber<Input = Self::Input> {

tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
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`...
82
--> $DIR/cycle-trait-supertrait-direct.rs:3:19
93
|
104
LL | trait Chromosome: Chromosome {
115
| ^^^^^^^^^^
12-
= note: ...which again requires computing the super predicates of `Chromosome`, completing the cycle
6+
|
7+
= note: ...which immediately requires computing the super predicates of `Chromosome` again
138
note: cycle used when collecting item types in top-level module
149
--> $DIR/cycle-trait-supertrait-direct.rs:3:1
1510
|

tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr

+2-12
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,16 @@
11
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`...
82
--> $DIR/cycle-trait-supertrait-indirect.rs:7:10
93
|
104
LL | trait B: C {
115
| ^
12-
note: ...which requires computing the super predicates of `C`...
13-
--> $DIR/cycle-trait-supertrait-indirect.rs:11:1
146
|
15-
LL | trait C: B { }
16-
| ^^^^^^^^^^
17-
note: ...which requires computing the super traits of `C`...
7+
note: ...which requires computing the super predicates of `C`...
188
--> $DIR/cycle-trait-supertrait-indirect.rs:11:10
199
|
2010
LL | trait C: B { }
2111
| ^
2212
= note: ...which again requires computing the super predicates of `B`, completing the cycle
23-
note: cycle used when computing the super traits of `A`
13+
note: cycle used when computing the super predicates of `A`
2414
--> $DIR/cycle-trait-supertrait-indirect.rs:4:10
2515
|
2616
LL | trait A: B {

tests/ui/infinite/infinite-trait-alias-recursion.stderr

+1-16
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,15 @@
11
error[E0391]: cycle detected when computing the super predicates of `T1`
2-
--> $DIR/infinite-trait-alias-recursion.rs:3:1
3-
|
4-
LL | trait T1 = T2;
5-
| ^^^^^^^^
6-
|
7-
note: ...which requires computing the super traits of `T1`...
82
--> $DIR/infinite-trait-alias-recursion.rs:3:12
93
|
104
LL | trait T1 = T2;
115
| ^^
12-
note: ...which requires computing the super predicates of `T2`...
13-
--> $DIR/infinite-trait-alias-recursion.rs:6:1
146
|
15-
LL | trait T2 = T3;
16-
| ^^^^^^^^
17-
note: ...which requires computing the super traits of `T2`...
7+
note: ...which requires computing the super predicates of `T2`...
188
--> $DIR/infinite-trait-alias-recursion.rs:6:12
199
|
2010
LL | trait T2 = T3;
2111
| ^^
2212
note: ...which requires computing the super predicates of `T3`...
23-
--> $DIR/infinite-trait-alias-recursion.rs:8:1
24-
|
25-
LL | trait T3 = T1 + T3;
26-
| ^^^^^^^^
27-
note: ...which requires computing the super traits of `T3`...
2813
--> $DIR/infinite-trait-alias-recursion.rs:8:12
2914
|
3015
LL | trait T3 = T1 + T3;

tests/ui/issues/issue-12511.stderr

+1-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
11
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`...
82
--> $DIR/issue-12511.rs:1:12
93
|
104
LL | trait T1 : T2 {
115
| ^^
12-
note: ...which requires computing the super predicates of `T2`...
13-
--> $DIR/issue-12511.rs:5:1
146
|
15-
LL | trait T2 : T1 {
16-
| ^^^^^^^^^^^^^
17-
note: ...which requires computing the super traits of `T2`...
7+
note: ...which requires computing the super predicates of `T2`...
188
--> $DIR/issue-12511.rs:5:12
199
|
2010
LL | trait T2 : T1 {

0 commit comments

Comments
 (0)