@@ -8,9 +8,10 @@ use rustc_middle::ty::util::IntTypeExt;
8
8
use rustc_middle:: ty:: { self , ImplTraitInTraitData , IsSuggestable , Ty , TyCtxt , TypeVisitableExt } ;
9
9
use rustc_span:: symbol:: Ident ;
10
10
use rustc_span:: { Span , DUMMY_SP } ;
11
+ use rustc_trait_selection:: traits;
11
12
12
- use super :: ItemCtxt ;
13
13
use super :: { bad_placeholder, is_suggestable_infer_ty} ;
14
+ use super :: { AstConv , ItemCtxt } ;
14
15
pub use opaque:: test_opaque_hidden_types;
15
16
16
17
mod opaque;
@@ -60,35 +61,78 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
60
61
. expect ( "const parameter types cannot be generic" ) ;
61
62
}
62
63
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 ) ) => {
66
67
let Some ( trait_def_id) = trait_ref. trait_def_id ( ) else {
67
68
return Ty :: new_error_with_message (
68
69
tcx,
69
70
tcx. def_span ( def_id) ,
70
- "Could not find trait" ,
71
+ "could not find trait" ,
71
72
) ;
72
73
} ;
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 ,
79
93
) ;
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 (
87
115
tcx,
88
116
tcx. def_span ( def_id) ,
89
- "Could not find associated const on trait" ,
90
- )
117
+ "could not find associated const on trait" ,
118
+ ) ;
91
119
} ;
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) ;
92
136
}
93
137
94
138
// 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> {
120
164
. unwrap ( )
121
165
. 0
122
166
. 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) ;
125
168
126
169
// Iterate through the generics of the projection to find the one that corresponds to
127
170
// the def_id that this query was called with. We filter to only type and const args here
0 commit comments