@@ -25,29 +25,39 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
2525 let def_id = goal. predicate . def_id ( ) ;
2626 match self . tcx ( ) . def_kind ( def_id) {
2727 DefKind :: AssocTy | DefKind :: AssocConst => {
28- match self . tcx ( ) . associated_item ( def_id) . container {
29- ty:: AssocItemContainer :: TraitContainer => {
30- // To only compute normalization once for each projection we only
31- // normalize if the expected term is an unconstrained inference variable.
32- //
33- // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
34- // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
35- // `U` and equate it with `u32`. This means that we don't need a separate
36- // projection cache in the solver.
37- if self . term_is_fully_unconstrained ( goal) {
28+ // To only compute normalization once for each projection we only
29+ // assemble normalization candidates if the expected term is an
30+ // unconstrained inference variable.
31+ //
32+ // Why: For better cache hits, since if we have an unconstrained RHS then
33+ // there are only as many cache keys as there are (canonicalized) alias
34+ // types in each normalizes-to goal. This also weakens inference in a
35+ // forwards-compatible way so we don't use the value of the RHS term to
36+ // affect candidate assembly for projections.
37+ //
38+ // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
39+ // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
40+ // `U` and equate it with `u32`. This means that we don't need a separate
41+ // projection cache in the solver, since we're piggybacking off of regular
42+ // goal caching.
43+ if self . term_is_fully_unconstrained ( goal) {
44+ match self . tcx ( ) . associated_item ( def_id) . container {
45+ ty:: AssocItemContainer :: TraitContainer => {
3846 let candidates = self . assemble_and_evaluate_candidates ( goal) ;
3947 self . merge_candidates ( candidates)
40- } else {
41- self . set_normalizes_to_hack_goal ( goal ) ;
42- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
48+ }
49+ ty :: AssocItemContainer :: ImplContainer => {
50+ bug ! ( "IATs not supported here yet" )
4351 }
4452 }
45- ty:: AssocItemContainer :: ImplContainer => bug ! ( "IATs not supported here yet" ) ,
53+ } else {
54+ self . set_normalizes_to_hack_goal ( goal) ;
55+ self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
4656 }
4757 }
4858 DefKind :: AnonConst => self . normalize_anon_const ( goal) ,
4959 DefKind :: OpaqueTy => self . normalize_opaque_type ( goal) ,
50- kind => bug ! ( "uknown DefKind {} in projection goal: {goal:#?}" , kind. descr( def_id) ) ,
60+ kind => bug ! ( "unknown DefKind {} in projection goal: {goal:#?}" , kind. descr( def_id) ) ,
5161 }
5262 }
5363
@@ -203,17 +213,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
203213 ) ;
204214
205215 // Finally we construct the actual value of the associated type.
206- let is_const = matches ! ( tcx. def_kind( assoc_def. item. def_id) , DefKind :: AssocConst ) ;
207- let ty = tcx. type_of ( assoc_def. item . def_id ) ;
208- let term: ty:: EarlyBinder < ty:: Term < ' tcx > > = if is_const {
209- let identity_substs =
210- ty:: InternalSubsts :: identity_for_item ( tcx, assoc_def. item . def_id ) ;
211- let did = assoc_def. item . def_id ;
212- let kind =
213- ty:: ConstKind :: Unevaluated ( ty:: UnevaluatedConst :: new ( did, identity_substs) ) ;
214- ty. map_bound ( |ty| tcx. mk_const ( kind, ty) . into ( ) )
215- } else {
216- ty. map_bound ( |ty| ty. into ( ) )
216+ let term = match assoc_def. item . kind {
217+ ty:: AssocKind :: Type => tcx. type_of ( assoc_def. item . def_id ) . map_bound ( |ty| ty. into ( ) ) ,
218+ ty:: AssocKind :: Const => bug ! ( "associated const projection is not supported yet" ) ,
219+ ty:: AssocKind :: Fn => unreachable ! ( "we should never project to a fn" ) ,
217220 } ;
218221
219222 ecx. eq ( goal. param_env , goal. predicate . term , term. subst ( tcx, substs) )
0 commit comments