@@ -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 , 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///
@@ -1111,7 +1148,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11111148 // NOTE: When this function starts resolving `Trait::AssocTy` successfully
11121149 // it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
11131150 #[ instrument( level = "debug" , skip_all, ret) ]
1114- pub fn lower_assoc_path (
1151+ pub fn lower_assoc_path_ty (
11151152 & self ,
11161153 hir_ref_id : HirId ,
11171154 span : Span ,
@@ -1120,6 +1157,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11201157 assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
11211158 permit_variants : bool ,
11221159 ) -> Result < ( Ty < ' tcx > , DefKind , DefId ) , ErrorGuaranteed > {
1160+ match self . lower_assoc_path_shared (
1161+ hir_ref_id,
1162+ span,
1163+ qself_ty,
1164+ qself,
1165+ assoc_segment,
1166+ LowerAssocMode :: Type { permit_variants } ,
1167+ ) ? {
1168+ LoweredAssoc :: Type ( ty, def_id) => Ok ( ( ty, DefKind :: AssocTy , def_id) ) ,
1169+ LoweredAssoc :: Variant { adt, variant_did } => Ok ( ( adt, DefKind :: Variant , variant_did) ) ,
1170+ LoweredAssoc :: Const ( _) => unreachable ! ( "lowered assoc type to const somehow" ) ,
1171+ }
1172+ }
1173+
1174+ #[ instrument( level = "debug" , skip_all, ret) ]
1175+ fn lower_assoc_path_const (
1176+ & self ,
1177+ hir_ref_id : HirId ,
1178+ span : Span ,
1179+ qself_ty : Ty < ' tcx > ,
1180+ qself : & ' tcx hir:: Ty < ' tcx > ,
1181+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1182+ ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
1183+ match self . lower_assoc_path_shared (
1184+ hir_ref_id,
1185+ span,
1186+ qself_ty,
1187+ qself,
1188+ assoc_segment,
1189+ LowerAssocMode :: Const ,
1190+ ) ? {
1191+ LoweredAssoc :: Type ( ..) => unreachable ! ( "lowered assoc const to type somehow" ) ,
1192+ LoweredAssoc :: Variant { adt : _, variant_did } => {
1193+ let uv = ty:: UnevaluatedConst :: new ( variant_did, ty:: List :: empty ( ) ) ;
1194+ Ok ( Const :: new_unevaluated ( self . tcx ( ) , uv) )
1195+ }
1196+ LoweredAssoc :: Const ( ct) => Ok ( ct) ,
1197+ }
1198+ }
1199+
1200+ #[ instrument( level = "debug" , skip_all, ret) ]
1201+ fn lower_assoc_path_shared (
1202+ & self ,
1203+ hir_ref_id : HirId ,
1204+ span : Span ,
1205+ qself_ty : Ty < ' tcx > ,
1206+ qself : & ' tcx hir:: Ty < ' tcx > ,
1207+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1208+ mode : LowerAssocMode ,
1209+ ) -> Result < LoweredAssoc < ' tcx > , ErrorGuaranteed > {
11231210 debug ! ( %qself_ty, ?assoc_segment. ident) ;
11241211 let tcx = self . tcx ( ) ;
11251212
@@ -1134,28 +1221,47 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11341221 . iter ( )
11351222 . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
11361223 if let Some ( variant_def) = variant_def {
1137- if permit_variants {
1224+ if mode . permit_variants ( ) {
11381225 tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
11391226 let _ = self . prohibit_generic_args (
11401227 slice:: from_ref ( assoc_segment) . iter ( ) ,
11411228 GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
11421229 ) ;
1143- return Ok ( ( qself_ty, DefKind :: Variant , variant_def. def_id ) ) ;
1230+ return Ok ( LoweredAssoc :: Variant {
1231+ adt : qself_ty,
1232+ variant_did : variant_def. def_id ,
1233+ } ) ;
11441234 } else {
11451235 variant_resolution = Some ( variant_def. def_id ) ;
11461236 }
11471237 }
11481238 }
11491239
1150- // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1151- if let Some ( ( ty, did) ) = self . probe_inherent_assoc_ty (
1152- assoc_segment,
1153- adt_def. did ( ) ,
1154- qself_ty,
1155- hir_ref_id,
1156- span,
1157- ) ? {
1158- return Ok ( ( ty, DefKind :: AssocTy , did) ) ;
1240+ match mode {
1241+ LowerAssocMode :: Type { .. } => {
1242+ // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1243+ if let Some ( ( ty, did) ) = self . probe_inherent_assoc_ty (
1244+ assoc_segment,
1245+ adt_def. did ( ) ,
1246+ qself_ty,
1247+ hir_ref_id,
1248+ span,
1249+ ) ? {
1250+ return Ok ( LoweredAssoc :: Type ( ty, did) ) ;
1251+ }
1252+ }
1253+ LowerAssocMode :: Const => {
1254+ // FIXME(mgca): Support self types other than ADTs.
1255+ if let Some ( ( ct, _) ) = self . probe_inherent_assoc_const (
1256+ assoc_segment,
1257+ adt_def. did ( ) ,
1258+ qself_ty,
1259+ hir_ref_id,
1260+ span,
1261+ ) ? {
1262+ return Ok ( LoweredAssoc :: Const ( ct) ) ;
1263+ }
1264+ }
11591265 }
11601266 }
11611267
@@ -1184,7 +1290,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11841290 )
11851291 } ,
11861292 AssocItemQSelf :: SelfTyAlias ,
1187- ty :: AssocKind :: Type ,
1293+ mode . kind ( ) ,
11881294 assoc_ident,
11891295 span,
11901296 None ,
@@ -1196,14 +1302,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11961302 ) => self . probe_single_ty_param_bound_for_assoc_item (
11971303 param_did. expect_local ( ) ,
11981304 qself. span ,
1199- ty :: AssocKind :: Type ,
1305+ mode . kind ( ) ,
12001306 assoc_ident,
12011307 span,
12021308 ) ?,
12031309 _ => {
1310+ let kind_str = assoc_kind_str ( mode. kind ( ) ) ;
12041311 let reported = if variant_resolution. is_some ( ) {
12051312 // Variant in type position
1206- let msg = format ! ( "expected type , found variant `{assoc_ident}`" ) ;
1313+ let msg = format ! ( "expected {kind_str} , found variant `{assoc_ident}`" ) ;
12071314 self . dcx ( ) . span_err ( span, msg)
12081315 } else if qself_ty. is_enum ( ) {
12091316 let mut err = struct_span_code_err ! (
@@ -1311,18 +1418,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13111418 & [ qself_ty. to_string ( ) ] ,
13121419 & traits,
13131420 assoc_ident. name ,
1314- ty :: AssocKind :: Type ,
1421+ mode . kind ( ) ,
13151422 )
13161423 } ;
13171424 return Err ( reported) ;
13181425 }
13191426 } ;
13201427
13211428 let trait_did = bound. def_id ( ) ;
1322- let assoc_ty = self
1323- . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Type , hir_ref_id, span, trait_did)
1324- . expect ( "failed to find associated type" ) ;
1325- let ty = self . lower_assoc_ty ( span, assoc_ty. def_id , assoc_segment, bound) ;
1429+ let assoc_item = self
1430+ . probe_assoc_item ( assoc_ident, mode. kind ( ) , hir_ref_id, span, trait_did)
1431+ . expect ( "failed to find associated item" ) ;
1432+ let result = match mode {
1433+ LowerAssocMode :: Type { .. } => {
1434+ let assoc_ty = self . lower_assoc_ty ( span, assoc_item. def_id , assoc_segment, bound) ;
1435+ LoweredAssoc :: Type ( assoc_ty, assoc_item. def_id )
1436+ }
1437+ LowerAssocMode :: Const => {
1438+ if assoc_item. has_type_const_attr ( tcx) {
1439+ let assoc_ct =
1440+ self . lower_assoc_const ( span, assoc_item. def_id , assoc_segment, bound) ;
1441+ LoweredAssoc :: Const ( assoc_ct)
1442+ } else {
1443+ let mut err = tcx. dcx ( ) . struct_span_err (
1444+ span,
1445+ "use of trait associated const without `#[type_const]`" ,
1446+ ) ;
1447+ err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
1448+ return Err ( err. emit ( ) ) ;
1449+ }
1450+ }
1451+ } ;
13261452
13271453 if let Some ( variant_def_id) = variant_resolution {
13281454 tcx. node_span_lint ( AMBIGUOUS_ASSOCIATED_ITEMS , hir_ref_id, span, |lint| {
@@ -1338,7 +1464,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13381464 } ;
13391465
13401466 could_refer_to ( DefKind :: Variant , variant_def_id, "" ) ;
1341- could_refer_to ( DefKind :: AssocTy , assoc_ty . def_id , " also" ) ;
1467+ could_refer_to ( mode . def_kind ( ) , assoc_item . def_id , " also" ) ;
13421468
13431469 lint. span_suggestion (
13441470 span,
@@ -1348,7 +1474,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13481474 ) ;
13491475 } ) ;
13501476 }
1351- Ok ( ( ty , DefKind :: AssocTy , assoc_ty . def_id ) )
1477+ Ok ( result )
13521478 }
13531479
13541480 fn probe_inherent_assoc_ty (
@@ -2246,7 +2372,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22462372 hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
22472373 debug ! ( ?qself, ?segment) ;
22482374 let ty = self . lower_ty ( qself) ;
2249- self . lower_const_assoc_path ( hir_id, const_arg. span ( ) , ty, qself, segment)
2375+ self . lower_assoc_path_const ( hir_id, const_arg. span ( ) , ty, qself, segment)
22502376 . unwrap_or_else ( |guar| Const :: new_error ( tcx, guar) )
22512377 }
22522378 hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
@@ -2361,114 +2487,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23612487 }
23622488 }
23632489
2364- #[ instrument( level = "debug" , skip( self ) , ret) ]
2365- pub fn lower_const_assoc_path (
2366- & self ,
2367- hir_ref_id : HirId ,
2368- span : Span ,
2369- qself_ty : Ty < ' tcx > ,
2370- qself : & ' tcx hir:: Ty < ' tcx > ,
2371- assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
2372- ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
2373- debug ! ( %qself_ty, ?assoc_segment. ident) ;
2374- let tcx = self . tcx ( ) ;
2375-
2376- let assoc_ident = assoc_segment. ident ;
2377-
2378- // Check if we have an enum variant or an inherent associated const.
2379- // FIXME(mgca): handle assoc fns once we support those
2380- if let Some ( adt_def) = self . probe_adt ( span, qself_ty) {
2381- if adt_def. is_enum ( ) {
2382- let variant_def = adt_def
2383- . variants ( )
2384- . iter ( )
2385- . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
2386- if let Some ( variant_def) = variant_def {
2387- tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
2388- let _ = self . prohibit_generic_args (
2389- slice:: from_ref ( assoc_segment) . iter ( ) ,
2390- GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
2391- ) ;
2392- let uv = ty:: UnevaluatedConst :: new ( variant_def. def_id , ty:: List :: empty ( ) ) ;
2393- return Ok ( Const :: new_unevaluated ( tcx, uv) ) ;
2394- }
2395- }
2396-
2397- // FIXME(mgca): Support self types other than ADTs.
2398- if let Some ( ( ct, _) ) = self . probe_inherent_assoc_const (
2399- assoc_segment,
2400- adt_def. did ( ) ,
2401- qself_ty,
2402- hir_ref_id,
2403- span,
2404- ) ? {
2405- return Ok ( ct) ;
2406- }
2407- }
2408-
2409- let qself_res = if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & qself. kind {
2410- path. res
2411- } else {
2412- Res :: Err
2413- } ;
2414-
2415- // Find the type of the associated item, and the trait where the associated
2416- // item is declared.
2417- let bound_result = match ( qself_ty. kind ( ) , qself_res) {
2418- ( _, Res :: SelfTyAlias { alias_to : impl_def_id, is_trait_impl : true , .. } ) => {
2419- // `Self` in an impl of a trait -- we have a concrete self type and a
2420- // trait reference.
2421- let Some ( trait_ref) = tcx. impl_trait_ref ( impl_def_id) else {
2422- // A cycle error occurred, most likely.
2423- self . dcx ( ) . span_bug ( span, "expected cycle error" ) ;
2424- } ;
2425-
2426- self . probe_single_bound_for_assoc_item (
2427- || {
2428- traits:: supertraits (
2429- tcx,
2430- ty:: Binder :: dummy ( trait_ref. instantiate_identity ( ) ) ,
2431- )
2432- } ,
2433- AssocItemQSelf :: SelfTyAlias ,
2434- ty:: AssocKind :: Const ,
2435- assoc_ident,
2436- span,
2437- None ,
2438- )
2439- }
2440- (
2441- & ty:: Param ( _) ,
2442- Res :: SelfTyParam { trait_ : param_did } | Res :: Def ( DefKind :: TyParam , param_did) ,
2443- ) => self . probe_single_ty_param_bound_for_assoc_item (
2444- param_did. expect_local ( ) ,
2445- qself. span ,
2446- ty:: AssocKind :: Const ,
2447- assoc_ident,
2448- span,
2449- ) ,
2450- _ => panic ! ( "handle errors here" ) , // FIXME: do this
2451- } ;
2452- let bound = match bound_result {
2453- Ok ( b) => b,
2454- Err ( reported) => return Err ( reported) ,
2455- } ;
2456-
2457- let trait_did = bound. def_id ( ) ;
2458- let assoc_const = self
2459- . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Const , hir_ref_id, span, trait_did)
2460- . expect ( "failed to find associated const" ) ;
2461- if assoc_const. has_type_const_attr ( tcx) {
2462- Ok ( self . lower_assoc_const ( span, assoc_const. def_id , assoc_segment, bound) )
2463- } else {
2464- let mut err = tcx
2465- . dcx ( )
2466- . struct_span_err ( span, "use of trait associated const without `#[type_const]`" ) ;
2467- err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
2468- Err ( err. emit ( ) )
2469- }
2470- }
2471-
24722490 /// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
24732491 #[ instrument( skip( self ) , level = "debug" ) ]
24742492 fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
@@ -2666,7 +2684,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26662684 hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
26672685 debug ! ( ?qself, ?segment) ;
26682686 let ty = self . lower_ty ( qself) ;
2669- self . lower_assoc_path ( hir_ty. hir_id , hir_ty. span , ty, qself, segment, false )
2687+ self . lower_assoc_path_ty ( hir_ty. hir_id , hir_ty. span , ty, qself, segment, false )
26702688 . map ( |( ty, _, _) | ty)
26712689 . unwrap_or_else ( |guar| Ty :: new_error ( tcx, guar) )
26722690 }
0 commit comments