@@ -22,25 +22,65 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
2222 & mut self ,
2323 goal : Goal < ' tcx , ProjectionPredicate < ' tcx > > ,
2424 ) -> QueryResult < ' tcx > {
25- match goal. predicate . projection_ty . kind ( self . tcx ( ) ) {
26- ty:: AliasKind :: Projection => {
25+ let def_id = goal. predicate . def_id ( ) ;
26+ match self . tcx ( ) . def_kind ( def_id) {
27+ DefKind :: AssocTy | DefKind :: AssocConst => {
2728 // To only compute normalization once for each projection we only
28- // normalize if the expected term is an unconstrained inference variable.
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.
2937 //
3038 // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
3139 // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
3240 // `U` and equate it with `u32`. This means that we don't need a separate
33- // projection cache in the solver.
41+ // projection cache in the solver, since we're piggybacking off of regular
42+ // goal caching.
3443 if self . term_is_fully_unconstrained ( goal) {
35- let candidates = self . assemble_and_evaluate_candidates ( goal) ;
36- self . merge_candidates ( candidates)
44+ match self . tcx ( ) . associated_item ( def_id) . container {
45+ ty:: AssocItemContainer :: TraitContainer => {
46+ let candidates = self . assemble_and_evaluate_candidates ( goal) ;
47+ self . merge_candidates ( candidates)
48+ }
49+ ty:: AssocItemContainer :: ImplContainer => {
50+ bug ! ( "IATs not supported here yet" )
51+ }
52+ }
3753 } else {
3854 self . set_normalizes_to_hack_goal ( goal) ;
3955 self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
4056 }
4157 }
42- ty:: AliasKind :: Opaque => self . normalize_opaque_type ( goal) ,
43- ty:: AliasKind :: Inherent => bug ! ( "IATs not supported here yet" ) ,
58+ DefKind :: AnonConst => self . normalize_anon_const ( goal) ,
59+ DefKind :: OpaqueTy => self . normalize_opaque_type ( goal) ,
60+ kind => bug ! ( "unknown DefKind {} in projection goal: {goal:#?}" , kind. descr( def_id) ) ,
61+ }
62+ }
63+
64+ #[ instrument( level = "debug" , skip( self ) , ret) ]
65+ fn normalize_anon_const (
66+ & mut self ,
67+ goal : Goal < ' tcx , ty:: ProjectionPredicate < ' tcx > > ,
68+ ) -> QueryResult < ' tcx > {
69+ if let Some ( normalized_const) = self . try_const_eval_resolve (
70+ goal. param_env ,
71+ ty:: UnevaluatedConst :: new (
72+ goal. predicate . projection_ty . def_id ,
73+ goal. predicate . projection_ty . substs ,
74+ ) ,
75+ self . tcx ( )
76+ . type_of ( goal. predicate . projection_ty . def_id )
77+ . no_bound_vars ( )
78+ . expect ( "const ty should not rely on other generics" ) ,
79+ ) {
80+ self . eq ( goal. param_env , normalized_const, goal. predicate . term . ct ( ) . unwrap ( ) ) ?;
81+ self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
82+ } else {
83+ self . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
4484 }
4585 }
4686}
@@ -173,17 +213,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
173213 ) ;
174214
175215 // Finally we construct the actual value of the associated type.
176- let is_const = matches ! ( tcx. def_kind( assoc_def. item. def_id) , DefKind :: AssocConst ) ;
177- let ty = tcx. type_of ( assoc_def. item . def_id ) ;
178- let term: ty:: EarlyBinder < ty:: Term < ' tcx > > = if is_const {
179- let identity_substs =
180- ty:: InternalSubsts :: identity_for_item ( tcx, assoc_def. item . def_id ) ;
181- let did = assoc_def. item . def_id ;
182- let kind =
183- ty:: ConstKind :: Unevaluated ( ty:: UnevaluatedConst :: new ( did, identity_substs) ) ;
184- ty. map_bound ( |ty| tcx. mk_const ( kind, ty) . into ( ) )
185- } else {
186- 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" ) ,
187220 } ;
188221
189222 ecx. eq ( goal. param_env , goal. predicate . term , term. subst ( tcx, substs) )
0 commit comments