@@ -2167,11 +2167,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21672167 let opt_self_ty = maybe_qself. as_ref ( ) . map ( |qself| self . lower_ty ( qself) ) ;
21682168 self . lower_const_path_resolved ( opt_self_ty, path, hir_id)
21692169 }
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+ }
21752182 hir:: ConstArgKind :: Anon ( anon) => self . lower_anon_const ( anon) ,
21762183 hir:: ConstArgKind :: Infer ( span, ( ) ) => self . ct_infer ( None , span) ,
21772184 }
@@ -2264,8 +2271,134 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22642271 }
22652272 }
22662273
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`.
22692402 #[ instrument( skip( self ) , level = "debug" ) ]
22702403 fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
22712404 let tcx = self . tcx ( ) ;
0 commit comments