@@ -2167,11 +2167,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2167
2167
let opt_self_ty = maybe_qself. as_ref ( ) . map ( |qself| self . lower_ty ( qself) ) ;
2168
2168
self . lower_const_path_resolved ( opt_self_ty, path, hir_id)
2169
2169
}
2170
- hir:: ConstArgKind :: Path ( qpath) => ty:: Const :: new_error_with_message (
2171
- tcx,
2172
- qpath. span ( ) ,
2173
- format ! ( "Const::lower_const_arg: invalid qpath {qpath:?}" ) ,
2174
- ) ,
2170
+ hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2171
+ debug ! ( ?qself, ?segment) ;
2172
+ let ty = self . lower_ty ( qself) ;
2173
+ self . lower_const_assoc_path ( hir_id, const_arg. span ( ) , ty, qself, segment)
2174
+ }
2175
+ hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
2176
+ ty:: Const :: new_error_with_message (
2177
+ tcx,
2178
+ qpath. span ( ) ,
2179
+ format ! ( "Const::lower_const_arg: invalid qpath {qpath:?}" ) ,
2180
+ )
2181
+ }
2175
2182
hir:: ConstArgKind :: Anon ( anon) => self . lower_anon_const ( anon) ,
2176
2183
hir:: ConstArgKind :: Infer ( span, ( ) ) => self . ct_infer ( None , span) ,
2177
2184
}
@@ -2264,8 +2271,134 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2264
2271
}
2265
2272
}
2266
2273
2267
- /// Literals and const generic parameters are eagerly converted to a constant, everything else
2268
- /// becomes `Unevaluated`.
2274
+ #[ instrument( level = "debug" , skip( self ) ) ]
2275
+ pub fn lower_const_assoc_path (
2276
+ & self ,
2277
+ hir_ref_id : HirId ,
2278
+ span : Span ,
2279
+ qself_ty : Ty < ' tcx > ,
2280
+ qself : & ' tcx hir:: Ty < ' tcx > ,
2281
+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
2282
+ ) -> Const < ' tcx > {
2283
+ debug ! ( %qself_ty, ?assoc_segment. ident) ;
2284
+ let tcx = self . tcx ( ) ;
2285
+
2286
+ let assoc_ident = assoc_segment. ident ;
2287
+
2288
+ // Check if we have an enum variant or an inherent associated const.
2289
+ // FIXME(min_generic_const_args): handle assoc fns once we support those
2290
+ if let Some ( adt_def) = self . probe_adt ( span, qself_ty) {
2291
+ if adt_def. is_enum ( ) {
2292
+ let variant_def = adt_def
2293
+ . variants ( )
2294
+ . iter ( )
2295
+ . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
2296
+ if let Some ( variant_def) = variant_def {
2297
+ tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
2298
+ let _ = self . prohibit_generic_args (
2299
+ slice:: from_ref ( assoc_segment) . iter ( ) ,
2300
+ GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
2301
+ ) ;
2302
+ let uv = ty:: UnevaluatedConst :: new ( variant_def. def_id , ty:: List :: empty ( ) ) ;
2303
+ return Const :: new_unevaluated ( tcx, uv) ;
2304
+ }
2305
+ }
2306
+
2307
+ // FIXME(min_generic_const_args): Support self types other than ADTs.
2308
+ let candidates = tcx
2309
+ . inherent_impls ( adt_def. did ( ) )
2310
+ . iter ( )
2311
+ . filter_map ( |& impl_| {
2312
+ self . probe_assoc_item (
2313
+ assoc_ident,
2314
+ ty:: AssocKind :: Const ,
2315
+ hir_ref_id,
2316
+ span,
2317
+ impl_,
2318
+ )
2319
+ } )
2320
+ . collect :: < Vec < _ > > ( ) ;
2321
+ match & candidates[ ..] {
2322
+ [ ] => { }
2323
+ [ assoc] => return self . lower_assoc_const ( span, assoc. def_id , assoc_segment) ,
2324
+ [ ..] => {
2325
+ return Const :: new_error_with_message ( tcx, span, "ambiguous assoc const path" ) ;
2326
+ }
2327
+ }
2328
+ }
2329
+
2330
+ let qself_res = if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & qself. kind {
2331
+ path. res
2332
+ } else {
2333
+ Res :: Err
2334
+ } ;
2335
+
2336
+ // Find the type of the associated item, and the trait where the associated
2337
+ // item is declared.
2338
+ let bound_result = match ( qself_ty. kind ( ) , qself_res) {
2339
+ ( _, Res :: SelfTyAlias { alias_to : impl_def_id, is_trait_impl : true , .. } ) => {
2340
+ // `Self` in an impl of a trait -- we have a concrete self type and a
2341
+ // trait reference.
2342
+ let Some ( trait_ref) = tcx. impl_trait_ref ( impl_def_id) else {
2343
+ // A cycle error occurred, most likely.
2344
+ self . dcx ( ) . span_bug ( span, "expected cycle error" ) ;
2345
+ } ;
2346
+
2347
+ self . probe_single_bound_for_assoc_item (
2348
+ || {
2349
+ traits:: supertraits (
2350
+ tcx,
2351
+ ty:: Binder :: dummy ( trait_ref. instantiate_identity ( ) ) ,
2352
+ )
2353
+ } ,
2354
+ AssocItemQSelf :: SelfTyAlias ,
2355
+ ty:: AssocKind :: Const ,
2356
+ assoc_ident,
2357
+ span,
2358
+ None ,
2359
+ )
2360
+ }
2361
+ (
2362
+ & ty:: Param ( _) ,
2363
+ Res :: SelfTyParam { trait_ : param_did } | Res :: Def ( DefKind :: TyParam , param_did) ,
2364
+ ) => self . probe_single_ty_param_bound_for_assoc_item (
2365
+ param_did. expect_local ( ) ,
2366
+ qself. span ,
2367
+ ty:: AssocKind :: Const ,
2368
+ assoc_ident,
2369
+ span,
2370
+ ) ,
2371
+ _ => panic ! ( "handle errors here" ) , // TODO: do this
2372
+ } ;
2373
+ let bound = match bound_result {
2374
+ Ok ( b) => b,
2375
+ Err ( reported) => return Const :: new_error ( tcx, reported) ,
2376
+ } ;
2377
+
2378
+ let trait_did = bound. def_id ( ) ;
2379
+ let assoc_const = self
2380
+ . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Const , hir_ref_id, span, trait_did)
2381
+ . expect ( "failed to find associated const" ) ;
2382
+ self . lower_assoc_const ( span, assoc_const. def_id , assoc_segment)
2383
+ }
2384
+
2385
+ fn lower_assoc_const (
2386
+ & self ,
2387
+ span : Span ,
2388
+ item_def_id : DefId ,
2389
+ item_segment : & hir:: PathSegment < ' tcx > ,
2390
+ ) -> Const < ' tcx > {
2391
+ let tcx = self . tcx ( ) ;
2392
+ // FIXME: this is not necessarily correct.
2393
+ // adapted from other code that also had a fixme about it being temporary.
2394
+ let parent_args = ty:: GenericArgs :: identity_for_item ( tcx, tcx. parent ( item_def_id) ) ;
2395
+ let args =
2396
+ self . lower_generic_args_of_assoc_item ( span, item_def_id, item_segment, parent_args) ;
2397
+ let uv = ty:: UnevaluatedConst :: new ( item_def_id, args) ;
2398
+ Const :: new_unevaluated ( tcx, uv)
2399
+ }
2400
+
2401
+ /// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
2269
2402
#[ instrument( skip( self ) , level = "debug" ) ]
2270
2403
fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
2271
2404
let tcx = self . tcx ( ) ;
0 commit comments