@@ -6,7 +6,7 @@ use rustc_type_ir::inherent::*;
66use rustc_type_ir:: lang_items:: TraitSolverLangItem ;
77use rustc_type_ir:: solve:: { CanonicalResponse , SizedTraitKind } ;
88use rustc_type_ir:: {
9- self as ty, Interner , Movability , TraitPredicate , TypeVisitableExt as _, TypingMode ,
9+ self as ty, Interner , Movability , TraitPredicate , TraitRef , TypeVisitableExt as _, TypingMode ,
1010 Upcast as _, elaborate,
1111} ;
1212use tracing:: { debug, instrument, trace} ;
@@ -131,16 +131,29 @@ where
131131 assumption : I :: Clause ,
132132 ) -> Result < ( ) , NoSolution > {
133133 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 ( ) {
137139 if DeepRejectCtxt :: relate_rigid_rigid ( ecx. cx ( ) ) . args_may_unify (
138140 goal. predicate . trait_ref . args ,
139141 trait_clause. skip_binder ( ) . trait_ref . args ,
140142 ) {
141143 return Ok ( ( ) ) ;
142144 }
143145 }
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+ }
144157 }
145158
146159 Err ( NoSolution )
@@ -154,6 +167,17 @@ where
154167 ) -> QueryResult < I > {
155168 let trait_clause = assumption. as_trait_clause ( ) . unwrap ( ) ;
156169
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+
157181 let assumption_trait_pred = ecx. instantiate_binder_with_infer ( trait_clause) ;
158182 ecx. eq ( goal. param_env , goal. predicate . trait_ref , assumption_trait_pred. trait_ref ) ?;
159183
@@ -817,6 +841,25 @@ where
817841 }
818842}
819843
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+
820863impl < D , I > EvalCtxt < ' _ , D >
821864where
822865 D : SolverDelegate < Interner = I > ,
0 commit comments