@@ -2110,11 +2110,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2110
2110
let opt_self_ty = maybe_qself. as_ref ( ) . map ( |qself| self . lower_ty ( qself) ) ;
2111
2111
self . lower_const_path_resolved ( opt_self_ty, path, hir_id)
2112
2112
}
2113
- hir:: ConstArgKind :: Path ( qpath) => ty:: Const :: new_error_with_message (
2114
- tcx,
2115
- qpath. span ( ) ,
2116
- format ! ( "Const::lower_const_arg: invalid qpath {qpath:?}" ) ,
2117
- ) ,
2113
+ hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2114
+ debug ! ( ?qself, ?segment) ;
2115
+ let ty = self . lower_ty ( qself) ;
2116
+ self . lower_const_assoc_path ( hir_id, const_arg. span ( ) , ty, qself, segment)
2117
+ }
2118
+ hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
2119
+ ty:: Const :: new_error_with_message (
2120
+ tcx,
2121
+ qpath. span ( ) ,
2122
+ format ! ( "Const::lower_const_arg: invalid qpath {qpath:?}" ) ,
2123
+ )
2124
+ }
2118
2125
hir:: ConstArgKind :: Anon ( anon) => self . lower_anon_const ( anon) ,
2119
2126
hir:: ConstArgKind :: Infer ( span, ( ) ) => self . ct_infer ( None , span) ,
2120
2127
}
@@ -2203,8 +2210,134 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2203
2210
}
2204
2211
}
2205
2212
2206
- /// Literals and const generic parameters are eagerly converted to a constant, everything else
2207
- /// becomes `Unevaluated`.
2213
+ #[ instrument( level = "debug" , skip( self ) ) ]
2214
+ pub fn lower_const_assoc_path (
2215
+ & self ,
2216
+ hir_ref_id : HirId ,
2217
+ span : Span ,
2218
+ qself_ty : Ty < ' tcx > ,
2219
+ qself : & ' tcx hir:: Ty < ' tcx > ,
2220
+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
2221
+ ) -> Const < ' tcx > {
2222
+ debug ! ( %qself_ty, ?assoc_segment. ident) ;
2223
+ let tcx = self . tcx ( ) ;
2224
+
2225
+ let assoc_ident = assoc_segment. ident ;
2226
+
2227
+ // Check if we have an enum variant or an inherent associated const.
2228
+ // FIXME(min_generic_const_args): handle assoc fns once we support those
2229
+ if let Some ( adt_def) = self . probe_adt ( span, qself_ty) {
2230
+ if adt_def. is_enum ( ) {
2231
+ let variant_def = adt_def
2232
+ . variants ( )
2233
+ . iter ( )
2234
+ . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
2235
+ if let Some ( variant_def) = variant_def {
2236
+ tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
2237
+ let _ = self . prohibit_generic_args (
2238
+ slice:: from_ref ( assoc_segment) . iter ( ) ,
2239
+ GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
2240
+ ) ;
2241
+ let uv = ty:: UnevaluatedConst :: new ( variant_def. def_id , ty:: List :: empty ( ) ) ;
2242
+ return Const :: new_unevaluated ( tcx, uv) ;
2243
+ }
2244
+ }
2245
+
2246
+ // FIXME(min_generic_const_args): Support self types other than ADTs.
2247
+ let candidates = tcx
2248
+ . inherent_impls ( adt_def. did ( ) )
2249
+ . iter ( )
2250
+ . filter_map ( |& impl_| {
2251
+ self . probe_assoc_item (
2252
+ assoc_ident,
2253
+ ty:: AssocKind :: Const ,
2254
+ hir_ref_id,
2255
+ span,
2256
+ impl_,
2257
+ )
2258
+ } )
2259
+ . collect :: < Vec < _ > > ( ) ;
2260
+ match & candidates[ ..] {
2261
+ [ ] => { }
2262
+ [ assoc] => return self . lower_assoc_const ( span, assoc. def_id , assoc_segment) ,
2263
+ [ ..] => {
2264
+ return Const :: new_error_with_message ( tcx, span, "ambiguous assoc const path" ) ;
2265
+ }
2266
+ }
2267
+ }
2268
+
2269
+ let qself_res = if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & qself. kind {
2270
+ path. res
2271
+ } else {
2272
+ Res :: Err
2273
+ } ;
2274
+
2275
+ // Find the type of the associated item, and the trait where the associated
2276
+ // item is declared.
2277
+ let bound_result = match ( qself_ty. kind ( ) , qself_res) {
2278
+ ( _, Res :: SelfTyAlias { alias_to : impl_def_id, is_trait_impl : true , .. } ) => {
2279
+ // `Self` in an impl of a trait -- we have a concrete self type and a
2280
+ // trait reference.
2281
+ let Some ( trait_ref) = tcx. impl_trait_ref ( impl_def_id) else {
2282
+ // A cycle error occurred, most likely.
2283
+ self . dcx ( ) . span_bug ( span, "expected cycle error" ) ;
2284
+ } ;
2285
+
2286
+ self . probe_single_bound_for_assoc_item (
2287
+ || {
2288
+ traits:: supertraits (
2289
+ tcx,
2290
+ ty:: Binder :: dummy ( trait_ref. instantiate_identity ( ) ) ,
2291
+ )
2292
+ } ,
2293
+ AssocItemQSelf :: SelfTyAlias ,
2294
+ ty:: AssocKind :: Const ,
2295
+ assoc_ident,
2296
+ span,
2297
+ None ,
2298
+ )
2299
+ }
2300
+ (
2301
+ & ty:: Param ( _) ,
2302
+ Res :: SelfTyParam { trait_ : param_did } | Res :: Def ( DefKind :: TyParam , param_did) ,
2303
+ ) => self . probe_single_ty_param_bound_for_assoc_item (
2304
+ param_did. expect_local ( ) ,
2305
+ qself. span ,
2306
+ ty:: AssocKind :: Const ,
2307
+ assoc_ident,
2308
+ span,
2309
+ ) ,
2310
+ _ => panic ! ( "handle errors here" ) , // TODO: do this
2311
+ } ;
2312
+ let bound = match bound_result {
2313
+ Ok ( b) => b,
2314
+ Err ( reported) => return Const :: new_error ( tcx, reported) ,
2315
+ } ;
2316
+
2317
+ let trait_did = bound. def_id ( ) ;
2318
+ let assoc_const = self
2319
+ . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Const , hir_ref_id, span, trait_did)
2320
+ . expect ( "failed to find associated const" ) ;
2321
+ self . lower_assoc_const ( span, assoc_const. def_id , assoc_segment)
2322
+ }
2323
+
2324
+ fn lower_assoc_const (
2325
+ & self ,
2326
+ span : Span ,
2327
+ item_def_id : DefId ,
2328
+ item_segment : & hir:: PathSegment < ' tcx > ,
2329
+ ) -> Const < ' tcx > {
2330
+ let tcx = self . tcx ( ) ;
2331
+ // FIXME: this is not necessarily correct.
2332
+ // adapted from other code that also had a fixme about it being temporary.
2333
+ let parent_args = ty:: GenericArgs :: identity_for_item ( tcx, tcx. parent ( item_def_id) ) ;
2334
+ let args =
2335
+ self . lower_generic_args_of_assoc_item ( span, item_def_id, item_segment, parent_args) ;
2336
+ let uv = ty:: UnevaluatedConst :: new ( item_def_id, args) ;
2337
+ Const :: new_unevaluated ( tcx, uv)
2338
+ }
2339
+
2340
+ /// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
2208
2341
#[ instrument( skip( self ) , level = "debug" ) ]
2209
2342
fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
2210
2343
let tcx = self . tcx ( ) ;
0 commit comments