@@ -2109,11 +2109,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21092109 let opt_self_ty = maybe_qself. as_ref ( ) . map ( |qself| self . lower_ty ( qself) ) ;
21102110 self . lower_const_path_resolved ( opt_self_ty, path, hir_id)
21112111 }
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+ }
21172124 hir:: ConstArgKind :: Anon ( anon) => self . lower_anon_const ( anon) ,
21182125 hir:: ConstArgKind :: Infer ( span) => self . ct_infer ( None , span) ,
21192126 }
@@ -2202,8 +2209,134 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22022209 }
22032210 }
22042211
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`.
22072340 #[ instrument( skip( self ) , level = "debug" ) ]
22082341 fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
22092342 let tcx = self . tcx ( ) ;
0 commit comments