@@ -6,7 +6,7 @@ use rustc_type_ir::inherent::*;
6
6
use rustc_type_ir:: lang_items:: TraitSolverLangItem ;
7
7
use rustc_type_ir:: solve:: { CanonicalResponse , SizedTraitKind } ;
8
8
use rustc_type_ir:: {
9
- self as ty, Interner , Movability , TraitPredicate , TypeVisitableExt as _, TypingMode ,
9
+ self as ty, Interner , Movability , TraitPredicate , TraitRef , TypeVisitableExt as _, TypingMode ,
10
10
Upcast as _, elaborate,
11
11
} ;
12
12
use tracing:: { debug, instrument, trace} ;
@@ -131,16 +131,29 @@ where
131
131
assumption : I :: Clause ,
132
132
) -> Result < ( ) , NoSolution > {
133
133
if let Some ( trait_clause) = assumption. as_trait_clause ( ) {
134
- if trait_clause. def_id ( ) == goal. predicate . def_id ( )
135
- && trait_clause. polarity ( ) == goal. predicate . polarity
136
- {
134
+ if trait_clause. polarity ( ) != goal. predicate . polarity {
135
+ return Err ( NoSolution ) ;
136
+ }
137
+
138
+ if trait_clause. def_id ( ) == goal. predicate . def_id ( ) {
137
139
if DeepRejectCtxt :: relate_rigid_rigid ( ecx. cx ( ) ) . args_may_unify (
138
140
goal. predicate . trait_ref . args ,
139
141
trait_clause. skip_binder ( ) . trait_ref . args ,
140
142
) {
141
143
return Ok ( ( ) ) ;
142
144
}
143
145
}
146
+
147
+ // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
148
+ // check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
149
+ // are syntactic sugar for a lack of bounds so don't need this.
150
+ if ecx. cx ( ) . is_lang_item ( goal. predicate . def_id ( ) , TraitSolverLangItem :: MetaSized )
151
+ && ecx. cx ( ) . is_lang_item ( trait_clause. def_id ( ) , TraitSolverLangItem :: Sized )
152
+ {
153
+ let meta_sized_clause =
154
+ trait_predicate_with_def_id ( ecx. cx ( ) , trait_clause, goal. predicate . def_id ( ) ) ;
155
+ return Self :: fast_reject_assumption ( ecx, goal, meta_sized_clause) ;
156
+ }
144
157
}
145
158
146
159
Err ( NoSolution )
@@ -154,6 +167,17 @@ where
154
167
) -> QueryResult < I > {
155
168
let trait_clause = assumption. as_trait_clause ( ) . unwrap ( ) ;
156
169
170
+ // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
171
+ // check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
172
+ // are syntactic sugar for a lack of bounds so don't need this.
173
+ if ecx. cx ( ) . is_lang_item ( goal. predicate . def_id ( ) , TraitSolverLangItem :: MetaSized )
174
+ && ecx. cx ( ) . is_lang_item ( trait_clause. def_id ( ) , TraitSolverLangItem :: Sized )
175
+ {
176
+ let meta_sized_clause =
177
+ trait_predicate_with_def_id ( ecx. cx ( ) , trait_clause, goal. predicate . def_id ( ) ) ;
178
+ return Self :: match_assumption ( ecx, goal, meta_sized_clause, then) ;
179
+ }
180
+
157
181
let assumption_trait_pred = ecx. instantiate_binder_with_infer ( trait_clause) ;
158
182
ecx. eq ( goal. param_env , goal. predicate . trait_ref , assumption_trait_pred. trait_ref ) ?;
159
183
@@ -817,6 +841,25 @@ where
817
841
}
818
842
}
819
843
844
+ /// Small helper function to change the `def_id` of a trait predicate - this is not normally
845
+ /// something that you want to do, as different traits will require different args and so making
846
+ /// it easy to change the trait is something of a footgun, but it is useful in the narrow
847
+ /// circumstance of changing from `MetaSized` to `Sized`, which happens as part of the lazy
848
+ /// elaboration of sizedness candidates.
849
+ #[ inline( always) ]
850
+ fn trait_predicate_with_def_id < I : Interner > (
851
+ cx : I ,
852
+ clause : ty:: Binder < I , ty:: TraitPredicate < I > > ,
853
+ did : I :: DefId ,
854
+ ) -> I :: Clause {
855
+ clause
856
+ . map_bound ( |c| TraitPredicate {
857
+ trait_ref : TraitRef :: new_from_args ( cx, did, c. trait_ref . args ) ,
858
+ polarity : c. polarity ,
859
+ } )
860
+ . upcast ( cx)
861
+ }
862
+
820
863
impl < D , I > EvalCtxt < ' _ , D >
821
864
where
822
865
D : SolverDelegate < Interner = I > ,
0 commit comments