@@ -4,6 +4,7 @@ use smallvec::smallvec;
4
4
5
5
use crate :: data_structures:: HashSet ;
6
6
use crate :: inherent:: * ;
7
+ use crate :: lang_items:: TraitSolverLangItem ;
7
8
use crate :: outlives:: { Component , push_outlives_components} ;
8
9
use crate :: { self as ty, Interner , Upcast as _} ;
9
10
@@ -79,20 +80,57 @@ pub fn elaborate<I: Interner, O: Elaboratable<I>>(
79
80
) -> Elaborator < I , O > {
80
81
let mut elaborator =
81
82
Elaborator { cx, stack : Vec :: new ( ) , visited : HashSet :: default ( ) , mode : Filter :: All } ;
82
- elaborator. extend_deduped ( obligations) ;
83
+ elaborator. extend_deduped ( None , obligations) ;
83
84
elaborator
84
85
}
85
86
86
87
impl < I : Interner , O : Elaboratable < I > > Elaborator < I , O > {
87
- fn extend_deduped ( & mut self , obligations : impl IntoIterator < Item = O > ) {
88
+ /// Adds `obligations` to the stack. `current_clause` is the clause which was elaborated to
89
+ /// produce these obligations.
90
+ fn extend_deduped (
91
+ & mut self ,
92
+ current_clause : Option < I :: Clause > ,
93
+ obligations : impl IntoIterator < Item = O > ,
94
+ ) {
88
95
// Only keep those bounds that we haven't already seen.
89
96
// This is necessary to prevent infinite recursion in some
90
97
// cases. One common case is when people define
91
98
// `trait Sized: Sized { }` rather than `trait Sized { }`.
92
99
self . stack . extend (
93
- obligations. into_iter ( ) . filter ( |o| {
94
- self . visited . insert ( self . cx . anonymize_bound_vars ( o. predicate ( ) . kind ( ) ) )
95
- } ) ,
100
+ obligations
101
+ . into_iter ( )
102
+ . filter ( |o| self . visited . insert ( self . cx . anonymize_bound_vars ( o. predicate ( ) . kind ( ) ) ) )
103
+ . filter ( |o| {
104
+ let Some ( current_clause) = current_clause else {
105
+ return true ;
106
+ } ;
107
+ let Some ( next_clause) = o. predicate ( ) . as_clause ( ) else {
108
+ return true ;
109
+ } ;
110
+
111
+ let current_did = match current_clause. kind ( ) . skip_binder ( ) {
112
+ ty:: ClauseKind :: Trait ( data) => data. def_id ( ) ,
113
+ ty:: ClauseKind :: HostEffect ( data) => data. def_id ( ) ,
114
+ _ => return true ,
115
+ } ;
116
+ let next_did = match next_clause. kind ( ) . skip_binder ( ) {
117
+ ty:: ClauseKind :: Trait ( data) => data. def_id ( ) ,
118
+ ty:: ClauseKind :: HostEffect ( data) => data. def_id ( ) ,
119
+ _ => return true ,
120
+ } ;
121
+
122
+ // PERF(sized-hierarchy): To avoid iterating over sizedness supertraits in
123
+ // parameter environments, as an optimisation, sizedness supertraits aren't
124
+ // elaborated, so check if a `Sized` obligation is being elaborated to a
125
+ // `MetaSized` obligation and emit it. Candidate assembly and confirmation
126
+ // are modified to check for the `Sized` subtrait when a `MetaSized` obligation
127
+ // is present.
128
+ if self . cx . is_lang_item ( current_did, TraitSolverLangItem :: Sized ) {
129
+ !self . cx . is_lang_item ( next_did, TraitSolverLangItem :: MetaSized )
130
+ } else {
131
+ true
132
+ }
133
+ } ) ,
96
134
) ;
97
135
}
98
136
@@ -132,12 +170,14 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
132
170
// Get predicates implied by the trait, or only super predicates if we only care about self predicates.
133
171
match self . mode {
134
172
Filter :: All => self . extend_deduped (
173
+ Some ( clause) ,
135
174
cx. explicit_implied_predicates_of ( data. def_id ( ) )
136
175
. iter_identity ( )
137
176
. enumerate ( )
138
177
. map ( map_to_child_clause) ,
139
178
) ,
140
179
Filter :: OnlySelf => self . extend_deduped (
180
+ Some ( clause) ,
141
181
cx. explicit_super_predicates_of ( data. def_id ( ) )
142
182
. iter_identity ( )
143
183
. enumerate ( )
@@ -147,6 +187,7 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
147
187
}
148
188
// `T: ~const Trait` implies `T: ~const Supertrait`.
149
189
ty:: ClauseKind :: HostEffect ( data) => self . extend_deduped (
190
+ Some ( clause) ,
150
191
cx. explicit_implied_const_bounds ( data. def_id ( ) ) . iter_identity ( ) . map ( |trait_ref| {
151
192
elaboratable. child (
152
193
trait_ref
@@ -177,6 +218,7 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
177
218
let mut components = smallvec ! [ ] ;
178
219
push_outlives_components ( cx, ty_max, & mut components) ;
179
220
self . extend_deduped (
221
+ Some ( clause) ,
180
222
components
181
223
. into_iter ( )
182
224
. filter_map ( |component| elaborate_component_to_clause ( cx, component, r_min) )
0 commit comments