@@ -52,6 +52,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt};
5252use rustc_type_ir:: Upcast ;
5353use tracing:: { debug, instrument} ;
5454
55+ use self :: errors:: assoc_kind_str;
5556use crate :: check:: check_abi_fn_ptr;
5657use crate :: errors:: {
5758 AmbiguousLifetimeBound , BadReturnTypeNotation , InvalidBaseType , NoVariantNamed ,
@@ -266,6 +267,42 @@ pub enum FeedConstTy<'a, 'tcx> {
266267 No ,
267268}
268269
270+ #[ derive( Debug , Clone , Copy ) ]
271+ enum LowerAssocMode {
272+ Type { permit_variants : bool } ,
273+ Const ,
274+ }
275+
276+ impl LowerAssocMode {
277+ fn kind ( self ) -> ty:: AssocKind {
278+ match self {
279+ LowerAssocMode :: Type { .. } => ty:: AssocKind :: Type ,
280+ LowerAssocMode :: Const => ty:: AssocKind :: Const ,
281+ }
282+ }
283+
284+ fn def_kind ( self ) -> DefKind {
285+ match self {
286+ LowerAssocMode :: Type { .. } => DefKind :: AssocTy ,
287+ LowerAssocMode :: Const => DefKind :: AssocConst ,
288+ }
289+ }
290+
291+ fn permit_variants ( self ) -> bool {
292+ match self {
293+ LowerAssocMode :: Type { permit_variants } => permit_variants,
294+ LowerAssocMode :: Const => true ,
295+ }
296+ }
297+ }
298+
299+ #[ derive( Debug , Clone , Copy ) ]
300+ enum LoweredAssoc < ' tcx > {
301+ Type ( Ty < ' tcx > , DefId ) ,
302+ Variant { adt : Ty < ' tcx > , variant_did : DefId } ,
303+ Const ( Const < ' tcx > ) ,
304+ }
305+
269306/// New-typed boolean indicating whether explicit late-bound lifetimes
270307/// are present in a set of generic arguments.
271308///
@@ -1138,7 +1175,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11381175 // NOTE: When this function starts resolving `Trait::AssocTy` successfully
11391176 // it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
11401177 #[ instrument( level = "debug" , skip_all, ret) ]
1141- pub fn lower_assoc_path (
1178+ pub fn lower_assoc_path_ty (
11421179 & self ,
11431180 hir_ref_id : HirId ,
11441181 span : Span ,
@@ -1147,6 +1184,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11471184 assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
11481185 permit_variants : bool ,
11491186 ) -> Result < ( Ty < ' tcx > , DefKind , DefId ) , ErrorGuaranteed > {
1187+ match self . lower_assoc_path_shared (
1188+ hir_ref_id,
1189+ span,
1190+ qself_ty,
1191+ qself,
1192+ assoc_segment,
1193+ LowerAssocMode :: Type { permit_variants } ,
1194+ ) ? {
1195+ LoweredAssoc :: Type ( ty, def_id) => Ok ( ( ty, DefKind :: AssocTy , def_id) ) ,
1196+ LoweredAssoc :: Variant { adt, variant_did } => Ok ( ( adt, DefKind :: Variant , variant_did) ) ,
1197+ LoweredAssoc :: Const ( _) => unreachable ! ( "lowered assoc type to const somehow" ) ,
1198+ }
1199+ }
1200+
1201+ #[ instrument( level = "debug" , skip_all, ret) ]
1202+ fn lower_assoc_path_const (
1203+ & self ,
1204+ hir_ref_id : HirId ,
1205+ span : Span ,
1206+ qself_ty : Ty < ' tcx > ,
1207+ qself : & ' tcx hir:: Ty < ' tcx > ,
1208+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1209+ ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
1210+ match self . lower_assoc_path_shared (
1211+ hir_ref_id,
1212+ span,
1213+ qself_ty,
1214+ qself,
1215+ assoc_segment,
1216+ LowerAssocMode :: Const ,
1217+ ) ? {
1218+ LoweredAssoc :: Type ( ..) => unreachable ! ( "lowered assoc const to type somehow" ) ,
1219+ LoweredAssoc :: Variant { adt : _, variant_did } => {
1220+ let uv = ty:: UnevaluatedConst :: new ( variant_did, ty:: List :: empty ( ) ) ;
1221+ Ok ( Const :: new_unevaluated ( self . tcx ( ) , uv) )
1222+ }
1223+ LoweredAssoc :: Const ( ct) => Ok ( ct) ,
1224+ }
1225+ }
1226+
1227+ #[ instrument( level = "debug" , skip_all, ret) ]
1228+ fn lower_assoc_path_shared (
1229+ & self ,
1230+ hir_ref_id : HirId ,
1231+ span : Span ,
1232+ qself_ty : Ty < ' tcx > ,
1233+ qself : & ' tcx hir:: Ty < ' tcx > ,
1234+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1235+ mode : LowerAssocMode ,
1236+ ) -> Result < LoweredAssoc < ' tcx > , ErrorGuaranteed > {
11501237 debug ! ( %qself_ty, ?assoc_segment. ident) ;
11511238 let tcx = self . tcx ( ) ;
11521239
@@ -1161,28 +1248,47 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11611248 . iter ( )
11621249 . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
11631250 if let Some ( variant_def) = variant_def {
1164- if permit_variants {
1251+ if mode . permit_variants ( ) {
11651252 tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
11661253 let _ = self . prohibit_generic_args (
11671254 slice:: from_ref ( assoc_segment) . iter ( ) ,
11681255 GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
11691256 ) ;
1170- return Ok ( ( qself_ty, DefKind :: Variant , variant_def. def_id ) ) ;
1257+ return Ok ( LoweredAssoc :: Variant {
1258+ adt : qself_ty,
1259+ variant_did : variant_def. def_id ,
1260+ } ) ;
11711261 } else {
11721262 variant_resolution = Some ( variant_def. def_id ) ;
11731263 }
11741264 }
11751265 }
11761266
1177- // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1178- if let Some ( ( ty, did) ) = self . probe_inherent_assoc_ty (
1179- assoc_segment,
1180- adt_def. did ( ) ,
1181- qself_ty,
1182- hir_ref_id,
1183- span,
1184- ) ? {
1185- return Ok ( ( ty, DefKind :: AssocTy , did) ) ;
1267+ match mode {
1268+ LowerAssocMode :: Type { .. } => {
1269+ // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1270+ if let Some ( ( ty, did) ) = self . probe_inherent_assoc_ty (
1271+ assoc_segment,
1272+ adt_def. did ( ) ,
1273+ qself_ty,
1274+ hir_ref_id,
1275+ span,
1276+ ) ? {
1277+ return Ok ( LoweredAssoc :: Type ( ty, did) ) ;
1278+ }
1279+ }
1280+ LowerAssocMode :: Const => {
1281+ // FIXME(mgca): Support self types other than ADTs.
1282+ if let Some ( ( ct, _) ) = self . probe_inherent_assoc_const (
1283+ assoc_segment,
1284+ adt_def. did ( ) ,
1285+ qself_ty,
1286+ hir_ref_id,
1287+ span,
1288+ ) ? {
1289+ return Ok ( LoweredAssoc :: Const ( ct) ) ;
1290+ }
1291+ }
11861292 }
11871293 }
11881294
@@ -1211,7 +1317,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12111317 )
12121318 } ,
12131319 AssocItemQSelf :: SelfTyAlias ,
1214- ty :: AssocKind :: Type ,
1320+ mode . kind ( ) ,
12151321 assoc_ident,
12161322 span,
12171323 None ,
@@ -1223,14 +1329,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12231329 ) => self . probe_single_ty_param_bound_for_assoc_item (
12241330 param_did. expect_local ( ) ,
12251331 qself. span ,
1226- ty :: AssocKind :: Type ,
1332+ mode . kind ( ) ,
12271333 assoc_ident,
12281334 span,
12291335 ) ?,
12301336 _ => {
1337+ let kind_str = assoc_kind_str ( mode. kind ( ) ) ;
12311338 let reported = if variant_resolution. is_some ( ) {
12321339 // Variant in type position
1233- let msg = format ! ( "expected type , found variant `{assoc_ident}`" ) ;
1340+ let msg = format ! ( "expected {kind_str} , found variant `{assoc_ident}`" ) ;
12341341 self . dcx ( ) . span_err ( span, msg)
12351342 } else if qself_ty. is_enum ( ) {
12361343 let mut err = self . dcx ( ) . create_err ( NoVariantNamed {
@@ -1334,18 +1441,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13341441 & [ qself_ty. to_string ( ) ] ,
13351442 & traits,
13361443 assoc_ident. name ,
1337- ty :: AssocKind :: Type ,
1444+ mode . kind ( ) ,
13381445 )
13391446 } ;
13401447 return Err ( reported) ;
13411448 }
13421449 } ;
13431450
13441451 let trait_did = bound. def_id ( ) ;
1345- let assoc_ty = self
1346- . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Type , hir_ref_id, span, trait_did)
1347- . expect ( "failed to find associated type" ) ;
1348- let ty = self . lower_assoc_ty ( span, assoc_ty. def_id , assoc_segment, bound) ;
1452+ let assoc_item = self
1453+ . probe_assoc_item ( assoc_ident, mode. kind ( ) , hir_ref_id, span, trait_did)
1454+ . expect ( "failed to find associated item" ) ;
1455+ let result = match mode {
1456+ LowerAssocMode :: Type { .. } => {
1457+ let assoc_ty = self . lower_assoc_ty ( span, assoc_item. def_id , assoc_segment, bound) ;
1458+ LoweredAssoc :: Type ( assoc_ty, assoc_item. def_id )
1459+ }
1460+ LowerAssocMode :: Const => {
1461+ if assoc_item. has_type_const_attr ( tcx) {
1462+ let assoc_ct =
1463+ self . lower_assoc_const ( span, assoc_item. def_id , assoc_segment, bound) ;
1464+ LoweredAssoc :: Const ( assoc_ct)
1465+ } else {
1466+ let mut err = tcx. dcx ( ) . struct_span_err (
1467+ span,
1468+ "use of trait associated const without `#[type_const]`" ,
1469+ ) ;
1470+ err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
1471+ return Err ( err. emit ( ) ) ;
1472+ }
1473+ }
1474+ } ;
13491475
13501476 if let Some ( variant_def_id) = variant_resolution {
13511477 tcx. node_span_lint ( AMBIGUOUS_ASSOCIATED_ITEMS , hir_ref_id, span, |lint| {
@@ -1361,7 +1487,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13611487 } ;
13621488
13631489 could_refer_to ( DefKind :: Variant , variant_def_id, "" ) ;
1364- could_refer_to ( DefKind :: AssocTy , assoc_ty . def_id , " also" ) ;
1490+ could_refer_to ( mode . def_kind ( ) , assoc_item . def_id , " also" ) ;
13651491
13661492 lint. span_suggestion (
13671493 span,
@@ -1371,7 +1497,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13711497 ) ;
13721498 } ) ;
13731499 }
1374- Ok ( ( ty , DefKind :: AssocTy , assoc_ty . def_id ) )
1500+ Ok ( result )
13751501 }
13761502
13771503 fn probe_inherent_assoc_ty (
@@ -2304,7 +2430,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23042430 hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
23052431 debug ! ( ?qself, ?segment) ;
23062432 let ty = self . lower_ty ( qself) ;
2307- self . lower_const_assoc_path ( hir_id, const_arg. span ( ) , ty, qself, segment)
2433+ self . lower_assoc_path_const ( hir_id, const_arg. span ( ) , ty, qself, segment)
23082434 . unwrap_or_else ( |guar| Const :: new_error ( tcx, guar) )
23092435 }
23102436 hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
@@ -2423,114 +2549,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24232549 }
24242550 }
24252551
2426- #[ instrument( level = "debug" , skip( self ) , ret) ]
2427- pub fn lower_const_assoc_path (
2428- & self ,
2429- hir_ref_id : HirId ,
2430- span : Span ,
2431- qself_ty : Ty < ' tcx > ,
2432- qself : & ' tcx hir:: Ty < ' tcx > ,
2433- assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
2434- ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
2435- debug ! ( %qself_ty, ?assoc_segment. ident) ;
2436- let tcx = self . tcx ( ) ;
2437-
2438- let assoc_ident = assoc_segment. ident ;
2439-
2440- // Check if we have an enum variant or an inherent associated const.
2441- // FIXME(mgca): handle assoc fns once we support those
2442- if let Some ( adt_def) = self . probe_adt ( span, qself_ty) {
2443- if adt_def. is_enum ( ) {
2444- let variant_def = adt_def
2445- . variants ( )
2446- . iter ( )
2447- . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
2448- if let Some ( variant_def) = variant_def {
2449- tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
2450- let _ = self . prohibit_generic_args (
2451- slice:: from_ref ( assoc_segment) . iter ( ) ,
2452- GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
2453- ) ;
2454- let uv = ty:: UnevaluatedConst :: new ( variant_def. def_id , ty:: List :: empty ( ) ) ;
2455- return Ok ( Const :: new_unevaluated ( tcx, uv) ) ;
2456- }
2457- }
2458-
2459- // FIXME(mgca): Support self types other than ADTs.
2460- if let Some ( ( ct, _) ) = self . probe_inherent_assoc_const (
2461- assoc_segment,
2462- adt_def. did ( ) ,
2463- qself_ty,
2464- hir_ref_id,
2465- span,
2466- ) ? {
2467- return Ok ( ct) ;
2468- }
2469- }
2470-
2471- let qself_res = if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & qself. kind {
2472- path. res
2473- } else {
2474- Res :: Err
2475- } ;
2476-
2477- // Find the type of the associated item, and the trait where the associated
2478- // item is declared.
2479- let bound_result = match ( qself_ty. kind ( ) , qself_res) {
2480- ( _, Res :: SelfTyAlias { alias_to : impl_def_id, is_trait_impl : true , .. } ) => {
2481- // `Self` in an impl of a trait -- we have a concrete self type and a
2482- // trait reference.
2483- let Some ( trait_ref) = tcx. impl_trait_ref ( impl_def_id) else {
2484- // A cycle error occurred, most likely.
2485- self . dcx ( ) . span_bug ( span, "expected cycle error" ) ;
2486- } ;
2487-
2488- self . probe_single_bound_for_assoc_item (
2489- || {
2490- traits:: supertraits (
2491- tcx,
2492- ty:: Binder :: dummy ( trait_ref. instantiate_identity ( ) ) ,
2493- )
2494- } ,
2495- AssocItemQSelf :: SelfTyAlias ,
2496- ty:: AssocKind :: Const ,
2497- assoc_ident,
2498- span,
2499- None ,
2500- )
2501- }
2502- (
2503- & ty:: Param ( _) ,
2504- Res :: SelfTyParam { trait_ : param_did } | Res :: Def ( DefKind :: TyParam , param_did) ,
2505- ) => self . probe_single_ty_param_bound_for_assoc_item (
2506- param_did. expect_local ( ) ,
2507- qself. span ,
2508- ty:: AssocKind :: Const ,
2509- assoc_ident,
2510- span,
2511- ) ,
2512- _ => panic ! ( "handle errors here" ) , // FIXME: do this
2513- } ;
2514- let bound = match bound_result {
2515- Ok ( b) => b,
2516- Err ( reported) => return Err ( reported) ,
2517- } ;
2518-
2519- let trait_did = bound. def_id ( ) ;
2520- let assoc_const = self
2521- . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Const , hir_ref_id, span, trait_did)
2522- . expect ( "failed to find associated const" ) ;
2523- if assoc_const. has_type_const_attr ( tcx) {
2524- Ok ( self . lower_assoc_const ( span, assoc_const. def_id , assoc_segment, bound) )
2525- } else {
2526- let mut err = tcx
2527- . dcx ( )
2528- . struct_span_err ( span, "use of trait associated const without `#[type_const]`" ) ;
2529- err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
2530- Err ( err. emit ( ) )
2531- }
2532- }
2533-
25342552 /// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
25352553 #[ instrument( skip( self ) , level = "debug" ) ]
25362554 fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
@@ -2730,7 +2748,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27302748 hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
27312749 debug ! ( ?qself, ?segment) ;
27322750 let ty = self . lower_ty ( qself) ;
2733- self . lower_assoc_path ( hir_ty. hir_id , hir_ty. span , ty, qself, segment, false )
2751+ self . lower_assoc_path_ty ( hir_ty. hir_id , hir_ty. span , ty, qself, segment, false )
27342752 . map ( |( ty, _, _) | ty)
27352753 . unwrap_or_else ( |guar| Ty :: new_error ( tcx, guar) )
27362754 }
0 commit comments