@@ -52,6 +52,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt};
52
52
use rustc_type_ir:: Upcast ;
53
53
use tracing:: { debug, instrument} ;
54
54
55
+ use self :: errors:: assoc_kind_str;
55
56
use crate :: check:: check_abi_fn_ptr;
56
57
use crate :: errors:: {
57
58
AmbiguousLifetimeBound , BadReturnTypeNotation , InvalidBaseType , NoVariantNamed ,
@@ -263,6 +264,42 @@ pub enum FeedConstTy {
263
264
No ,
264
265
}
265
266
267
+ #[ derive( Debug , Clone , Copy ) ]
268
+ enum LowerAssocMode {
269
+ Type { permit_variants : bool } ,
270
+ Const ,
271
+ }
272
+
273
+ impl LowerAssocMode {
274
+ fn kind ( self ) -> ty:: AssocKind {
275
+ match self {
276
+ LowerAssocMode :: Type { .. } => ty:: AssocKind :: Type ,
277
+ LowerAssocMode :: Const => ty:: AssocKind :: Const ,
278
+ }
279
+ }
280
+
281
+ fn def_kind ( self ) -> DefKind {
282
+ match self {
283
+ LowerAssocMode :: Type { .. } => DefKind :: AssocTy ,
284
+ LowerAssocMode :: Const => DefKind :: AssocConst ,
285
+ }
286
+ }
287
+
288
+ fn permit_variants ( self ) -> bool {
289
+ match self {
290
+ LowerAssocMode :: Type { permit_variants } => permit_variants,
291
+ LowerAssocMode :: Const => true ,
292
+ }
293
+ }
294
+ }
295
+
296
+ #[ derive( Debug , Clone , Copy ) ]
297
+ enum LoweredAssoc < ' tcx > {
298
+ Type ( Ty < ' tcx > , DefId ) ,
299
+ Variant { adt : Ty < ' tcx > , variant_did : DefId } ,
300
+ Const ( Const < ' tcx > ) ,
301
+ }
302
+
266
303
/// New-typed boolean indicating whether explicit late-bound lifetimes
267
304
/// are present in a set of generic arguments.
268
305
///
@@ -1131,7 +1168,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1131
1168
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
1132
1169
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
1133
1170
#[ instrument( level = "debug" , skip_all, ret) ]
1134
- pub fn lower_assoc_path (
1171
+ pub fn lower_assoc_path_ty (
1135
1172
& self ,
1136
1173
hir_ref_id : HirId ,
1137
1174
span : Span ,
@@ -1140,6 +1177,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1140
1177
assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1141
1178
permit_variants : bool ,
1142
1179
) -> Result < ( Ty < ' tcx > , DefKind , DefId ) , ErrorGuaranteed > {
1180
+ match self . lower_assoc_path_shared (
1181
+ hir_ref_id,
1182
+ span,
1183
+ qself_ty,
1184
+ qself,
1185
+ assoc_segment,
1186
+ LowerAssocMode :: Type { permit_variants } ,
1187
+ ) ? {
1188
+ LoweredAssoc :: Type ( ty, def_id) => Ok ( ( ty, DefKind :: AssocTy , def_id) ) ,
1189
+ LoweredAssoc :: Variant { adt, variant_did } => Ok ( ( adt, DefKind :: Variant , variant_did) ) ,
1190
+ LoweredAssoc :: Const ( _) => unreachable ! ( "lowered assoc type to const somehow" ) ,
1191
+ }
1192
+ }
1193
+
1194
+ #[ instrument( level = "debug" , skip_all, ret) ]
1195
+ fn lower_assoc_path_const (
1196
+ & self ,
1197
+ hir_ref_id : HirId ,
1198
+ span : Span ,
1199
+ qself_ty : Ty < ' tcx > ,
1200
+ qself : & ' tcx hir:: Ty < ' tcx > ,
1201
+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1202
+ ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
1203
+ match self . lower_assoc_path_shared (
1204
+ hir_ref_id,
1205
+ span,
1206
+ qself_ty,
1207
+ qself,
1208
+ assoc_segment,
1209
+ LowerAssocMode :: Const ,
1210
+ ) ? {
1211
+ LoweredAssoc :: Type ( ..) => unreachable ! ( "lowered assoc const to type somehow" ) ,
1212
+ LoweredAssoc :: Variant { adt : _, variant_did } => {
1213
+ let uv = ty:: UnevaluatedConst :: new ( variant_did, ty:: List :: empty ( ) ) ;
1214
+ Ok ( Const :: new_unevaluated ( self . tcx ( ) , uv) )
1215
+ }
1216
+ LoweredAssoc :: Const ( ct) => Ok ( ct) ,
1217
+ }
1218
+ }
1219
+
1220
+ #[ instrument( level = "debug" , skip_all, ret) ]
1221
+ fn lower_assoc_path_shared (
1222
+ & self ,
1223
+ hir_ref_id : HirId ,
1224
+ span : Span ,
1225
+ qself_ty : Ty < ' tcx > ,
1226
+ qself : & ' tcx hir:: Ty < ' tcx > ,
1227
+ assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1228
+ mode : LowerAssocMode ,
1229
+ ) -> Result < LoweredAssoc < ' tcx > , ErrorGuaranteed > {
1143
1230
debug ! ( %qself_ty, ?assoc_segment. ident) ;
1144
1231
let tcx = self . tcx ( ) ;
1145
1232
@@ -1154,28 +1241,47 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1154
1241
. iter ( )
1155
1242
. find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
1156
1243
if let Some ( variant_def) = variant_def {
1157
- if permit_variants {
1244
+ if mode . permit_variants ( ) {
1158
1245
tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
1159
1246
let _ = self . prohibit_generic_args (
1160
1247
slice:: from_ref ( assoc_segment) . iter ( ) ,
1161
1248
GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
1162
1249
) ;
1163
- return Ok ( ( qself_ty, DefKind :: Variant , variant_def. def_id ) ) ;
1250
+ return Ok ( LoweredAssoc :: Variant {
1251
+ adt : qself_ty,
1252
+ variant_did : variant_def. def_id ,
1253
+ } ) ;
1164
1254
} else {
1165
1255
variant_resolution = Some ( variant_def. def_id ) ;
1166
1256
}
1167
1257
}
1168
1258
}
1169
1259
1170
- // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1171
- if let Some ( ( ty, did) ) = self . probe_inherent_assoc_ty (
1172
- assoc_segment,
1173
- adt_def. did ( ) ,
1174
- qself_ty,
1175
- hir_ref_id,
1176
- span,
1177
- ) ? {
1178
- return Ok ( ( ty, DefKind :: AssocTy , did) ) ;
1260
+ match mode {
1261
+ LowerAssocMode :: Type { .. } => {
1262
+ // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1263
+ if let Some ( ( ty, did) ) = self . probe_inherent_assoc_ty (
1264
+ assoc_segment,
1265
+ adt_def. did ( ) ,
1266
+ qself_ty,
1267
+ hir_ref_id,
1268
+ span,
1269
+ ) ? {
1270
+ return Ok ( LoweredAssoc :: Type ( ty, did) ) ;
1271
+ }
1272
+ }
1273
+ LowerAssocMode :: Const => {
1274
+ // FIXME(mgca): Support self types other than ADTs.
1275
+ if let Some ( ( ct, _) ) = self . probe_inherent_assoc_const (
1276
+ assoc_segment,
1277
+ adt_def. did ( ) ,
1278
+ qself_ty,
1279
+ hir_ref_id,
1280
+ span,
1281
+ ) ? {
1282
+ return Ok ( LoweredAssoc :: Const ( ct) ) ;
1283
+ }
1284
+ }
1179
1285
}
1180
1286
}
1181
1287
@@ -1204,7 +1310,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1204
1310
)
1205
1311
} ,
1206
1312
AssocItemQSelf :: SelfTyAlias ,
1207
- ty :: AssocKind :: Type ,
1313
+ mode . kind ( ) ,
1208
1314
assoc_ident,
1209
1315
span,
1210
1316
None ,
@@ -1216,14 +1322,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1216
1322
) => self . probe_single_ty_param_bound_for_assoc_item (
1217
1323
param_did. expect_local ( ) ,
1218
1324
qself. span ,
1219
- ty :: AssocKind :: Type ,
1325
+ mode . kind ( ) ,
1220
1326
assoc_ident,
1221
1327
span,
1222
1328
) ?,
1223
1329
_ => {
1330
+ let kind_str = assoc_kind_str ( mode. kind ( ) ) ;
1224
1331
let reported = if variant_resolution. is_some ( ) {
1225
1332
// Variant in type position
1226
- let msg = format ! ( "expected type , found variant `{assoc_ident}`" ) ;
1333
+ let msg = format ! ( "expected {kind_str} , found variant `{assoc_ident}`" ) ;
1227
1334
self . dcx ( ) . span_err ( span, msg)
1228
1335
} else if qself_ty. is_enum ( ) {
1229
1336
let mut err = self . dcx ( ) . create_err ( NoVariantNamed {
@@ -1328,18 +1435,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1328
1435
& [ qself_ty. to_string ( ) ] ,
1329
1436
& traits,
1330
1437
assoc_ident. name ,
1331
- ty :: AssocKind :: Type ,
1438
+ mode . kind ( ) ,
1332
1439
)
1333
1440
} ;
1334
1441
return Err ( reported) ;
1335
1442
}
1336
1443
} ;
1337
1444
1338
1445
let trait_did = bound. def_id ( ) ;
1339
- let assoc_ty = self
1340
- . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Type , hir_ref_id, span, trait_did)
1341
- . expect ( "failed to find associated type" ) ;
1342
- let ty = self . lower_assoc_ty ( span, assoc_ty. def_id , assoc_segment, bound) ;
1446
+ let assoc_item = self
1447
+ . probe_assoc_item ( assoc_ident, mode. kind ( ) , hir_ref_id, span, trait_did)
1448
+ . expect ( "failed to find associated item" ) ;
1449
+ let result = match mode {
1450
+ LowerAssocMode :: Type { .. } => {
1451
+ let assoc_ty = self . lower_assoc_ty ( span, assoc_item. def_id , assoc_segment, bound) ;
1452
+ LoweredAssoc :: Type ( assoc_ty, assoc_item. def_id )
1453
+ }
1454
+ LowerAssocMode :: Const => {
1455
+ if assoc_item. has_type_const_attr ( tcx) {
1456
+ let assoc_ct =
1457
+ self . lower_assoc_const ( span, assoc_item. def_id , assoc_segment, bound) ;
1458
+ LoweredAssoc :: Const ( assoc_ct)
1459
+ } else {
1460
+ let mut err = tcx. dcx ( ) . struct_span_err (
1461
+ span,
1462
+ "use of trait associated const without `#[type_const]`" ,
1463
+ ) ;
1464
+ err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
1465
+ return Err ( err. emit ( ) ) ;
1466
+ }
1467
+ }
1468
+ } ;
1343
1469
1344
1470
if let Some ( variant_def_id) = variant_resolution {
1345
1471
tcx. node_span_lint ( AMBIGUOUS_ASSOCIATED_ITEMS , hir_ref_id, span, |lint| {
@@ -1355,7 +1481,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1355
1481
} ;
1356
1482
1357
1483
could_refer_to ( DefKind :: Variant , variant_def_id, "" ) ;
1358
- could_refer_to ( DefKind :: AssocTy , assoc_ty . def_id , " also" ) ;
1484
+ could_refer_to ( mode . def_kind ( ) , assoc_item . def_id , " also" ) ;
1359
1485
1360
1486
lint. span_suggestion (
1361
1487
span,
@@ -1365,7 +1491,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1365
1491
) ;
1366
1492
} ) ;
1367
1493
}
1368
- Ok ( ( ty , DefKind :: AssocTy , assoc_ty . def_id ) )
1494
+ Ok ( result )
1369
1495
}
1370
1496
1371
1497
fn probe_inherent_assoc_ty (
@@ -2263,7 +2389,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2263
2389
hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2264
2390
debug ! ( ?qself, ?segment) ;
2265
2391
let ty = self . lower_ty ( qself) ;
2266
- self . lower_const_assoc_path ( hir_id, const_arg. span ( ) , ty, qself, segment)
2392
+ self . lower_assoc_path_const ( hir_id, const_arg. span ( ) , ty, qself, segment)
2267
2393
. unwrap_or_else ( |guar| Const :: new_error ( tcx, guar) )
2268
2394
}
2269
2395
hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
@@ -2382,114 +2508,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2382
2508
}
2383
2509
}
2384
2510
2385
- #[ instrument( level = "debug" , skip( self ) , ret) ]
2386
- pub fn lower_const_assoc_path (
2387
- & self ,
2388
- hir_ref_id : HirId ,
2389
- span : Span ,
2390
- qself_ty : Ty < ' tcx > ,
2391
- qself : & ' tcx hir:: Ty < ' tcx > ,
2392
- assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
2393
- ) -> Result < Const < ' tcx > , ErrorGuaranteed > {
2394
- debug ! ( %qself_ty, ?assoc_segment. ident) ;
2395
- let tcx = self . tcx ( ) ;
2396
-
2397
- let assoc_ident = assoc_segment. ident ;
2398
-
2399
- // Check if we have an enum variant or an inherent associated const.
2400
- // FIXME(mgca): handle assoc fns once we support those
2401
- if let Some ( adt_def) = self . probe_adt ( span, qself_ty) {
2402
- if adt_def. is_enum ( ) {
2403
- let variant_def = adt_def
2404
- . variants ( )
2405
- . iter ( )
2406
- . find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
2407
- if let Some ( variant_def) = variant_def {
2408
- tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
2409
- let _ = self . prohibit_generic_args (
2410
- slice:: from_ref ( assoc_segment) . iter ( ) ,
2411
- GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
2412
- ) ;
2413
- let uv = ty:: UnevaluatedConst :: new ( variant_def. def_id , ty:: List :: empty ( ) ) ;
2414
- return Ok ( Const :: new_unevaluated ( tcx, uv) ) ;
2415
- }
2416
- }
2417
-
2418
- // FIXME(mgca): Support self types other than ADTs.
2419
- if let Some ( ( ct, _) ) = self . probe_inherent_assoc_const (
2420
- assoc_segment,
2421
- adt_def. did ( ) ,
2422
- qself_ty,
2423
- hir_ref_id,
2424
- span,
2425
- ) ? {
2426
- return Ok ( ct) ;
2427
- }
2428
- }
2429
-
2430
- let qself_res = if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & qself. kind {
2431
- path. res
2432
- } else {
2433
- Res :: Err
2434
- } ;
2435
-
2436
- // Find the type of the associated item, and the trait where the associated
2437
- // item is declared.
2438
- let bound_result = match ( qself_ty. kind ( ) , qself_res) {
2439
- ( _, Res :: SelfTyAlias { alias_to : impl_def_id, is_trait_impl : true , .. } ) => {
2440
- // `Self` in an impl of a trait -- we have a concrete self type and a
2441
- // trait reference.
2442
- let Some ( trait_ref) = tcx. impl_trait_ref ( impl_def_id) else {
2443
- // A cycle error occurred, most likely.
2444
- self . dcx ( ) . span_bug ( span, "expected cycle error" ) ;
2445
- } ;
2446
-
2447
- self . probe_single_bound_for_assoc_item (
2448
- || {
2449
- traits:: supertraits (
2450
- tcx,
2451
- ty:: Binder :: dummy ( trait_ref. instantiate_identity ( ) ) ,
2452
- )
2453
- } ,
2454
- AssocItemQSelf :: SelfTyAlias ,
2455
- ty:: AssocKind :: Const ,
2456
- assoc_ident,
2457
- span,
2458
- None ,
2459
- )
2460
- }
2461
- (
2462
- & ty:: Param ( _) ,
2463
- Res :: SelfTyParam { trait_ : param_did } | Res :: Def ( DefKind :: TyParam , param_did) ,
2464
- ) => self . probe_single_ty_param_bound_for_assoc_item (
2465
- param_did. expect_local ( ) ,
2466
- qself. span ,
2467
- ty:: AssocKind :: Const ,
2468
- assoc_ident,
2469
- span,
2470
- ) ,
2471
- _ => panic ! ( "handle errors here" ) , // FIXME: do this
2472
- } ;
2473
- let bound = match bound_result {
2474
- Ok ( b) => b,
2475
- Err ( reported) => return Err ( reported) ,
2476
- } ;
2477
-
2478
- let trait_did = bound. def_id ( ) ;
2479
- let assoc_const = self
2480
- . probe_assoc_item ( assoc_ident, ty:: AssocKind :: Const , hir_ref_id, span, trait_did)
2481
- . expect ( "failed to find associated const" ) ;
2482
- if assoc_const. has_type_const_attr ( tcx) {
2483
- Ok ( self . lower_assoc_const ( span, assoc_const. def_id , assoc_segment, bound) )
2484
- } else {
2485
- let mut err = tcx
2486
- . dcx ( )
2487
- . struct_span_err ( span, "use of trait associated const without `#[type_const]`" ) ;
2488
- err. note ( "the declaration in the trait must be marked with `#[type_const]`" ) ;
2489
- Err ( err. emit ( ) )
2490
- }
2491
- }
2492
-
2493
2511
/// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
2494
2512
#[ instrument( skip( self ) , level = "debug" ) ]
2495
2513
fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
@@ -2689,7 +2707,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2689
2707
hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2690
2708
debug ! ( ?qself, ?segment) ;
2691
2709
let ty = self . lower_ty ( qself) ;
2692
- self . lower_assoc_path ( hir_ty. hir_id , hir_ty. span , ty, qself, segment, false )
2710
+ self . lower_assoc_path_ty ( hir_ty. hir_id , hir_ty. span , ty, qself, segment, false )
2693
2711
. map ( |( ty, _, _) | ty)
2694
2712
. unwrap_or_else ( |guar| Ty :: new_error ( tcx, guar) )
2695
2713
}
0 commit comments