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