@@ -8,9 +8,10 @@ use rustc_middle::ty::util::IntTypeExt;
88use rustc_middle:: ty:: { self , ImplTraitInTraitData , IsSuggestable , Ty , TyCtxt , TypeVisitableExt } ;
99use rustc_span:: symbol:: Ident ;
1010use rustc_span:: { Span , DUMMY_SP } ;
11+ use rustc_trait_selection:: traits;
1112
12- use super :: ItemCtxt ;
1313use super :: { bad_placeholder, is_suggestable_infer_ty} ;
14+ use super :: { AstConv , ItemCtxt } ;
1415pub use opaque:: test_opaque_hidden_types;
1516
1617mod opaque;
@@ -60,35 +61,78 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
6061 . expect ( "const parameter types cannot be generic" ) ;
6162 }
6263
63- Node :: TypeBinding ( binding @ & TypeBinding { hir_id : binding_id , .. } )
64- if let Node :: TraitRef ( trait_ref ) = tcx . hir ( ) . get ( tcx . hir ( ) . parent_id ( binding_id ) ) =>
65- {
64+ Node :: TypeBinding (
65+ binding @ & TypeBinding { hir_id : binding_id , ident , gen_args , span , .. } ,
66+ ) if let Node :: TraitRef ( trait_ref ) = tcx . hir ( ) . get ( tcx . hir ( ) . parent_id ( binding_id ) ) => {
6667 let Some ( trait_def_id) = trait_ref. trait_def_id ( ) else {
6768 return Ty :: new_error_with_message (
6869 tcx,
6970 tcx. def_span ( def_id) ,
70- "Could not find trait" ,
71+ "could not find trait" ,
7172 ) ;
7273 } ;
73- let assoc_items = tcx. associated_items ( trait_def_id) ;
74- let assoc_item = assoc_items. find_by_name_and_kind (
75- tcx,
76- binding. ident ,
77- ty:: AssocKind :: Const ,
78- def_id. to_def_id ( ) ,
74+
75+ // FIXME(associated_const_equality): We're now performing a full but ad-hoc type-based
76+ // resolution of the associated constant. Doing all this work *here* isn't great.
77+ // Ideally, we would've computed this already somewhere else (in a query?).
78+
79+ let icx = ItemCtxt :: new ( tcx, def_id) ;
80+ let trait_segment = trait_ref. path . segments . last ( ) . unwrap ( ) ;
81+ let ( trait_args, _) = icx. astconv ( ) . create_args_for_ast_path (
82+ trait_ref. path . span ,
83+ trait_def_id,
84+ & [ ] ,
85+ trait_segment,
86+ trait_segment. args ( ) ,
87+ trait_segment. infer_args ,
88+ // FIXME(associated_const_equality): This isn't correct, it should be the concrete /
89+ // instantiated self type. Theoretically, we could search for it in the HIR of the
90+ // parent item but that's super fragile and hairy.
91+ Some ( tcx. types . self_param ) ,
92+ ty:: BoundConstness :: NotConst ,
7993 ) ;
80- return if let Some ( assoc_item) = assoc_item {
81- tcx. type_of ( assoc_item. def_id )
82- . no_bound_vars ( )
83- . expect ( "const parameter types cannot be generic" )
84- } else {
85- // FIXME(associated_const_equality): add a useful error message here.
86- Ty :: new_error_with_message (
94+ let trait_ref = ty:: Binder :: bind_with_vars (
95+ ty:: TraitRef :: new ( tcx, trait_def_id, trait_args) ,
96+ tcx. late_bound_vars ( trait_ref. hir_ref_id ) ,
97+ ) ;
98+
99+ // We shouldn't need to deal with ambiguity since `add_predicates_for_ast_type_binding`
100+ // should've already bailed out early in such case.
101+ let Some ( ( assoc_item, parent_args) ) =
102+ traits:: supertraits ( tcx, trait_ref) . find_map ( |trait_ref| {
103+ tcx. associated_items ( trait_ref. def_id ( ) )
104+ . find_by_name_and_kind (
105+ tcx,
106+ binding. ident ,
107+ ty:: AssocKind :: Const ,
108+ trait_ref. def_id ( ) ,
109+ )
110+ // FIXME(fmease): `skip_binder` is fishy!
111+ . map ( |item| ( item, trait_ref. skip_binder ( ) . args ) )
112+ } )
113+ else {
114+ return Ty :: new_error_with_message (
87115 tcx,
88116 tcx. def_span ( def_id) ,
89- "Could not find associated const on trait" ,
90- )
117+ "could not find associated const on trait" ,
118+ ) ;
91119 } ;
120+
121+ let args = icx. astconv ( ) . create_args_for_associated_item (
122+ span,
123+ assoc_item. def_id ,
124+ // FIXME(fmease): This is gross as hell!
125+ & hir:: PathSegment {
126+ ident,
127+ hir_id,
128+ res : def:: Res :: Def ( def:: DefKind :: AssocConst , assoc_item. def_id ) ,
129+ args : Some ( gen_args) ,
130+ infer_args : false ,
131+ } ,
132+ parent_args,
133+ ) ;
134+
135+ return tcx. type_of ( assoc_item. def_id ) . instantiate ( tcx, args) ;
92136 }
93137
94138 // This match arm is for when the def_id appears in a GAT whose
@@ -120,8 +164,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
120164 . unwrap ( )
121165 . 0
122166 . def_id ;
123- let item_ctxt = & ItemCtxt :: new ( tcx, item_def_id) as & dyn crate :: astconv:: AstConv < ' _ > ;
124- let ty = item_ctxt. ast_ty_to_ty ( hir_ty) ;
167+ let ty = ItemCtxt :: new ( tcx, item_def_id) . to_ty ( hir_ty) ;
125168
126169 // Iterate through the generics of the projection to find the one that corresponds to
127170 // the def_id that this query was called with. We filter to only type and const args here
0 commit comments