@@ -51,6 +51,7 @@ use rustc_trait_selection::traits::wf::object_region_bounds;
5151use rustc_trait_selection:: traits:: { self , ObligationCtxt } ;
5252use tracing:: { debug, instrument} ;
5353
54+ use self :: errors:: assoc_kind_str;
5455use crate :: bounds:: Bounds ;
5556use crate :: check:: check_abi_fn_ptr;
5657use crate :: errors:: { AmbiguousLifetimeBound , BadReturnTypeNotation , InvalidBaseType , WildPatTy } ;
@@ -261,6 +262,42 @@ pub enum FeedConstTy {
261262 No ,
262263}
263264
265+ #[ derive( Debug , Clone , Copy ) ]
266+ enum LowerAssocMode {
267+ Type { permit_variants : bool } ,
268+ Const ,
269+ }
270+
271+ impl LowerAssocMode {
272+ fn kind ( self ) -> ty:: AssocKind {
273+ match self {
274+ LowerAssocMode :: Type { .. } => ty:: AssocKind :: Type ,
275+ LowerAssocMode :: Const => ty:: AssocKind :: Const ,
276+ }
277+ }
278+
279+ fn def_kind ( self ) -> DefKind {
280+ match self {
281+ LowerAssocMode :: Type { .. } => DefKind :: AssocTy ,
282+ LowerAssocMode :: Const => DefKind :: AssocConst ,
283+ }
284+ }
285+
286+ fn permit_variants ( self ) -> bool {
287+ match self {
288+ LowerAssocMode :: Type { permit_variants } => permit_variants,
289+ LowerAssocMode :: Const => true ,
290+ }
291+ }
292+ }
293+
294+ #[ derive( Debug , Clone , Copy ) ]
295+ enum LoweredAssoc < ' tcx > {
296+ Type ( Ty < ' tcx > , DefId ) ,
297+ Variant { adt : Ty < ' tcx > , variant_did : DefId } ,
298+ Const ( Const < ' tcx > ) ,
299+ }
300+
264301/// New-typed boolean indicating whether explicit late-bound lifetimes
265302/// are present in a set of generic arguments.
266303///
@@ -1112,7 +1149,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11121149 // NOTE: When this function starts resolving `Trait::AssocTy` successfully
11131150 // it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
11141151 #[ instrument( level = "debug" , skip_all, ret) ]
1115- pub fn lower_assoc_path (
1152+ pub fn lower_assoc_path_ty (
11161153 & self ,
11171154 hir_ref_id : HirId ,
11181155 span : Span ,
@@ -1121,6 +1158,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11211158 assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
11221159 permit_variants : bool ,
11231160 ) -> Result < ( Ty < ' tcx > , DefKind , DefId ) , ErrorGuaranteed > {
1161+ match self . lower_assoc_path_shared (
1162+ hir_ref_id,
1163+ span,
1164+ qself_ty,
1165+ qself,
1166+ assoc_segment,
1167+ LowerAssocMode :: Type { permit_variants } ,
1168+ ) ? {
1169+ LoweredAssoc :: Type ( ty, def_id) => Ok ( ( ty, DefKind :: AssocTy , def_id) ) ,
1170+ LoweredAssoc :: Variant { adt, variant_did } => Ok ( ( adt, DefKind :: Variant , variant_did) ) ,
1171+ LoweredAssoc :: Const ( _) => unreachable ! ( "lowered assoc type to const somehow" ) ,
1172+ }
1173+ }
1174+
1175+ #[ instrument( level = "debug" , skip_all, ret) ]
1176+ fn lower_assoc_path_const (
1177+ & self ,
1178+ hir_ref_id : HirId ,
1179+ span : Span ,
1180+ qself_ty : Ty < ' tcx > ,
1181+ qself : & ' tcx hir:: Ty < ' tcx > ,
1182+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1183+ ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
1184+ match self . lower_assoc_path_shared (
1185+ hir_ref_id,
1186+ span,
1187+ qself_ty,
1188+ qself,
1189+ assoc_segment,
1190+ LowerAssocMode :: Const ,
1191+ ) ? {
1192+ LoweredAssoc :: Type ( ..) => unreachable ! ( "lowered assoc const to type somehow" ) ,
1193+ LoweredAssoc :: Variant { adt : _, variant_did } => {
1194+ let uv = ty:: UnevaluatedConst :: new ( variant_did, ty:: List :: empty ( ) ) ;
1195+ Ok ( Const :: new_unevaluated ( self . tcx ( ) , uv) )
1196+ }
1197+ LoweredAssoc :: Const ( ct) => Ok ( ct) ,
1198+ }
1199+ }
1200+
1201+ #[ instrument( level = "debug" , skip_all, ret) ]
1202+ fn lower_assoc_path_shared (
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+ mode : LowerAssocMode ,
1210+ ) -> Result < LoweredAssoc < ' tcx > , ErrorGuaranteed > {
11241211 debug ! ( %qself_ty, ?assoc_segment. ident) ;
11251212 let tcx = self . tcx ( ) ;
11261213
@@ -1135,28 +1222,47 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11351222 . iter ( )
11361223 . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
11371224 if let Some ( variant_def) = variant_def {
1138- if permit_variants {
1225+ if mode . permit_variants ( ) {
11391226 tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
11401227 let _ = self . prohibit_generic_args (
11411228 slice:: from_ref ( assoc_segment) . iter ( ) ,
11421229 GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
11431230 ) ;
1144- return Ok ( ( qself_ty, DefKind :: Variant , variant_def. def_id ) ) ;
1231+ return Ok ( LoweredAssoc :: Variant {
1232+ adt : qself_ty,
1233+ variant_did : variant_def. def_id ,
1234+ } ) ;
11451235 } else {
11461236 variant_resolution = Some ( variant_def. def_id ) ;
11471237 }
11481238 }
11491239 }
11501240
1151- // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1152- if let Some ( ( ty, did) ) = self . probe_inherent_assoc_ty (
1153- assoc_segment,
1154- adt_def. did ( ) ,
1155- qself_ty,
1156- hir_ref_id,
1157- span,
1158- ) ? {
1159- return Ok ( ( ty, DefKind :: AssocTy , did) ) ;
1241+ match mode {
1242+ LowerAssocMode :: Type { .. } => {
1243+ // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1244+ if let Some ( ( ty, did) ) = self . probe_inherent_assoc_ty (
1245+ assoc_segment,
1246+ adt_def. did ( ) ,
1247+ qself_ty,
1248+ hir_ref_id,
1249+ span,
1250+ ) ? {
1251+ return Ok ( LoweredAssoc :: Type ( ty, did) ) ;
1252+ }
1253+ }
1254+ LowerAssocMode :: Const => {
1255+ // FIXME(mgca): Support self types other than ADTs.
1256+ if let Some ( ( ct, _) ) = self . probe_inherent_assoc_const (
1257+ assoc_segment,
1258+ adt_def. did ( ) ,
1259+ qself_ty,
1260+ hir_ref_id,
1261+ span,
1262+ ) ? {
1263+ return Ok ( LoweredAssoc :: Const ( ct) ) ;
1264+ }
1265+ }
11601266 }
11611267 }
11621268
@@ -1185,7 +1291,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11851291 )
11861292 } ,
11871293 AssocItemQSelf :: SelfTyAlias ,
1188- ty :: AssocKind :: Type ,
1294+ mode . kind ( ) ,
11891295 assoc_ident,
11901296 span,
11911297 None ,
@@ -1197,14 +1303,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11971303 ) => self . probe_single_ty_param_bound_for_assoc_item (
11981304 param_did. expect_local ( ) ,
11991305 qself. span ,
1200- ty :: AssocKind :: Type ,
1306+ mode . kind ( ) ,
12011307 assoc_ident,
12021308 span,
12031309 ) ?,
12041310 _ => {
1311+ let kind_str = assoc_kind_str ( mode. kind ( ) ) ;
12051312 let reported = if variant_resolution. is_some ( ) {
12061313 // Variant in type position
1207- let msg = format ! ( "expected type , found variant `{assoc_ident}`" ) ;
1314+ let msg = format ! ( "expected {kind_str} , found variant `{assoc_ident}`" ) ;
12081315 self . dcx ( ) . span_err ( span, msg)
12091316 } else if qself_ty. is_enum ( ) {
12101317 let mut err = struct_span_code_err ! (
@@ -1312,18 +1419,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13121419 & [ qself_ty. to_string ( ) ] ,
13131420 & traits,
13141421 assoc_ident. name ,
1315- ty :: AssocKind :: Type ,
1422+ mode . kind ( ) ,
13161423 )
13171424 } ;
13181425 return Err ( reported) ;
13191426 }
13201427 } ;
13211428
13221429 let trait_did = bound. def_id ( ) ;
1323- let assoc_ty = self
1324- . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Type , hir_ref_id, span, trait_did)
1325- . expect ( "failed to find associated type" ) ;
1326- let ty = self . lower_assoc_ty ( span, assoc_ty. def_id , assoc_segment, bound) ;
1430+ let assoc_item = self
1431+ . probe_assoc_item ( assoc_ident, mode. kind ( ) , hir_ref_id, span, trait_did)
1432+ . expect ( "failed to find associated item" ) ;
1433+ let result = match mode {
1434+ LowerAssocMode :: Type { .. } => {
1435+ let assoc_ty = self . lower_assoc_ty ( span, assoc_item. def_id , assoc_segment, bound) ;
1436+ LoweredAssoc :: Type ( assoc_ty, assoc_item. def_id )
1437+ }
1438+ LowerAssocMode :: Const => {
1439+ if assoc_item. has_type_const_attr ( tcx) {
1440+ let assoc_ct =
1441+ self . lower_assoc_const ( span, assoc_item. def_id , assoc_segment, bound) ;
1442+ LoweredAssoc :: Const ( assoc_ct)
1443+ } else {
1444+ let mut err = tcx. dcx ( ) . struct_span_err (
1445+ span,
1446+ "use of trait associated const without `#[type_const]`" ,
1447+ ) ;
1448+ err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
1449+ return Err ( err. emit ( ) ) ;
1450+ }
1451+ }
1452+ } ;
13271453
13281454 if let Some ( variant_def_id) = variant_resolution {
13291455 tcx. node_span_lint ( AMBIGUOUS_ASSOCIATED_ITEMS , hir_ref_id, span, |lint| {
@@ -1339,7 +1465,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13391465 } ;
13401466
13411467 could_refer_to ( DefKind :: Variant , variant_def_id, "" ) ;
1342- could_refer_to ( DefKind :: AssocTy , assoc_ty . def_id , " also" ) ;
1468+ could_refer_to ( mode . def_kind ( ) , assoc_item . def_id , " also" ) ;
13431469
13441470 lint. span_suggestion (
13451471 span,
@@ -1349,7 +1475,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13491475 ) ;
13501476 } ) ;
13511477 }
1352- Ok ( ( ty , DefKind :: AssocTy , assoc_ty . def_id ) )
1478+ Ok ( result )
13531479 }
13541480
13551481 fn probe_inherent_assoc_ty (
@@ -2247,7 +2373,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22472373 hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
22482374 debug ! ( ?qself, ?segment) ;
22492375 let ty = self . lower_ty ( qself) ;
2250- self . lower_const_assoc_path ( hir_id, const_arg. span ( ) , ty, qself, segment)
2376+ self . lower_assoc_path_const ( hir_id, const_arg. span ( ) , ty, qself, segment)
22512377 . unwrap_or_else ( |guar| Const :: new_error ( tcx, guar) )
22522378 }
22532379 hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
@@ -2362,114 +2488,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23622488 }
23632489 }
23642490
2365- #[ instrument( level = "debug" , skip( self ) , ret) ]
2366- pub fn lower_const_assoc_path (
2367- & self ,
2368- hir_ref_id : HirId ,
2369- span : Span ,
2370- qself_ty : Ty < ' tcx > ,
2371- qself : & ' tcx hir:: Ty < ' tcx > ,
2372- assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
2373- ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
2374- debug ! ( %qself_ty, ?assoc_segment. ident) ;
2375- let tcx = self . tcx ( ) ;
2376-
2377- let assoc_ident = assoc_segment. ident ;
2378-
2379- // Check if we have an enum variant or an inherent associated const.
2380- // FIXME(mgca): handle assoc fns once we support those
2381- if let Some ( adt_def) = self . probe_adt ( span, qself_ty) {
2382- if adt_def. is_enum ( ) {
2383- let variant_def = adt_def
2384- . variants ( )
2385- . iter ( )
2386- . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
2387- if let Some ( variant_def) = variant_def {
2388- tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
2389- let _ = self . prohibit_generic_args (
2390- slice:: from_ref ( assoc_segment) . iter ( ) ,
2391- GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
2392- ) ;
2393- let uv = ty:: UnevaluatedConst :: new ( variant_def. def_id , ty:: List :: empty ( ) ) ;
2394- return Ok ( Const :: new_unevaluated ( tcx, uv) ) ;
2395- }
2396- }
2397-
2398- // FIXME(mgca): Support self types other than ADTs.
2399- if let Some ( ( ct, _) ) = self . probe_inherent_assoc_const (
2400- assoc_segment,
2401- adt_def. did ( ) ,
2402- qself_ty,
2403- hir_ref_id,
2404- span,
2405- ) ? {
2406- return Ok ( ct) ;
2407- }
2408- }
2409-
2410- let qself_res = if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & qself. kind {
2411- path. res
2412- } else {
2413- Res :: Err
2414- } ;
2415-
2416- // Find the type of the associated item, and the trait where the associated
2417- // item is declared.
2418- let bound_result = match ( qself_ty. kind ( ) , qself_res) {
2419- ( _, Res :: SelfTyAlias { alias_to : impl_def_id, is_trait_impl : true , .. } ) => {
2420- // `Self` in an impl of a trait -- we have a concrete self type and a
2421- // trait reference.
2422- let Some ( trait_ref) = tcx. impl_trait_ref ( impl_def_id) else {
2423- // A cycle error occurred, most likely.
2424- self . dcx ( ) . span_bug ( span, "expected cycle error" ) ;
2425- } ;
2426-
2427- self . probe_single_bound_for_assoc_item (
2428- || {
2429- traits:: supertraits (
2430- tcx,
2431- ty:: Binder :: dummy ( trait_ref. instantiate_identity ( ) ) ,
2432- )
2433- } ,
2434- AssocItemQSelf :: SelfTyAlias ,
2435- ty:: AssocKind :: Const ,
2436- assoc_ident,
2437- span,
2438- None ,
2439- )
2440- }
2441- (
2442- & ty:: Param ( _) ,
2443- Res :: SelfTyParam { trait_ : param_did } | Res :: Def ( DefKind :: TyParam , param_did) ,
2444- ) => self . probe_single_ty_param_bound_for_assoc_item (
2445- param_did. expect_local ( ) ,
2446- qself. span ,
2447- ty:: AssocKind :: Const ,
2448- assoc_ident,
2449- span,
2450- ) ,
2451- _ => panic ! ( "handle errors here" ) , // FIXME: do this
2452- } ;
2453- let bound = match bound_result {
2454- Ok ( b) => b,
2455- Err ( reported) => return Err ( reported) ,
2456- } ;
2457-
2458- let trait_did = bound. def_id ( ) ;
2459- let assoc_const = self
2460- . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Const , hir_ref_id, span, trait_did)
2461- . expect ( "failed to find associated const" ) ;
2462- if assoc_const. has_type_const_attr ( tcx) {
2463- Ok ( self . lower_assoc_const ( span, assoc_const. def_id , assoc_segment, bound) )
2464- } else {
2465- let mut err = tcx
2466- . dcx ( )
2467- . struct_span_err ( span, "use of trait associated const without `#[type_const]`" ) ;
2468- err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
2469- Err ( err. emit ( ) )
2470- }
2471- }
2472-
24732491 /// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
24742492 #[ instrument( skip( self ) , level = "debug" ) ]
24752493 fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
@@ -2670,7 +2688,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26702688 hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
26712689 debug ! ( ?qself, ?segment) ;
26722690 let ty = self . lower_ty ( qself) ;
2673- self . lower_assoc_path ( hir_ty. hir_id , hir_ty. span , ty, qself, segment, false )
2691+ self . lower_assoc_path_ty ( hir_ty. hir_id , hir_ty. span , ty, qself, segment, false )
26742692 . map ( |( ty, _, _) | ty)
26752693 . unwrap_or_else ( |guar| Ty :: new_error ( tcx, guar) )
26762694 }
0 commit comments