@@ -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 ,
@@ -266,6 +267,42 @@ pub enum FeedConstTy<'a, 'tcx> {
266
267
No ,
267
268
}
268
269
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
+
269
306
/// New-typed boolean indicating whether explicit late-bound lifetimes
270
307
/// are present in a set of generic arguments.
271
308
///
@@ -1138,7 +1175,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1138
1175
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
1139
1176
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
1140
1177
#[ instrument( level = "debug" , skip_all, ret) ]
1141
- pub fn lower_assoc_path (
1178
+ pub fn lower_assoc_path_ty (
1142
1179
& self ,
1143
1180
hir_ref_id : HirId ,
1144
1181
span : Span ,
@@ -1147,6 +1184,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1147
1184
assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1148
1185
permit_variants : bool ,
1149
1186
) -> 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 > {
1150
1237
debug ! ( %qself_ty, ?assoc_segment. ident) ;
1151
1238
let tcx = self . tcx ( ) ;
1152
1239
@@ -1161,28 +1248,47 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1161
1248
. iter ( )
1162
1249
. find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
1163
1250
if let Some ( variant_def) = variant_def {
1164
- if permit_variants {
1251
+ if mode . permit_variants ( ) {
1165
1252
tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
1166
1253
let _ = self . prohibit_generic_args (
1167
1254
slice:: from_ref ( assoc_segment) . iter ( ) ,
1168
1255
GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
1169
1256
) ;
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
+ } ) ;
1171
1261
} else {
1172
1262
variant_resolution = Some ( variant_def. def_id ) ;
1173
1263
}
1174
1264
}
1175
1265
}
1176
1266
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
+ }
1186
1292
}
1187
1293
}
1188
1294
@@ -1211,7 +1317,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1211
1317
)
1212
1318
} ,
1213
1319
AssocItemQSelf :: SelfTyAlias ,
1214
- ty :: AssocKind :: Type ,
1320
+ mode . kind ( ) ,
1215
1321
assoc_ident,
1216
1322
span,
1217
1323
None ,
@@ -1223,14 +1329,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1223
1329
) => self . probe_single_ty_param_bound_for_assoc_item (
1224
1330
param_did. expect_local ( ) ,
1225
1331
qself. span ,
1226
- ty :: AssocKind :: Type ,
1332
+ mode . kind ( ) ,
1227
1333
assoc_ident,
1228
1334
span,
1229
1335
) ?,
1230
1336
_ => {
1337
+ let kind_str = assoc_kind_str ( mode. kind ( ) ) ;
1231
1338
let reported = if variant_resolution. is_some ( ) {
1232
1339
// 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}`" ) ;
1234
1341
self . dcx ( ) . span_err ( span, msg)
1235
1342
} else if qself_ty. is_enum ( ) {
1236
1343
let mut err = self . dcx ( ) . create_err ( NoVariantNamed {
@@ -1334,18 +1441,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1334
1441
& [ qself_ty. to_string ( ) ] ,
1335
1442
& traits,
1336
1443
assoc_ident. name ,
1337
- ty :: AssocKind :: Type ,
1444
+ mode . kind ( ) ,
1338
1445
)
1339
1446
} ;
1340
1447
return Err ( reported) ;
1341
1448
}
1342
1449
} ;
1343
1450
1344
1451
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
+ } ;
1349
1475
1350
1476
if let Some ( variant_def_id) = variant_resolution {
1351
1477
tcx. node_span_lint ( AMBIGUOUS_ASSOCIATED_ITEMS , hir_ref_id, span, |lint| {
@@ -1361,7 +1487,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1361
1487
} ;
1362
1488
1363
1489
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" ) ;
1365
1491
1366
1492
lint. span_suggestion (
1367
1493
span,
@@ -1371,7 +1497,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1371
1497
) ;
1372
1498
} ) ;
1373
1499
}
1374
- Ok ( ( ty , DefKind :: AssocTy , assoc_ty . def_id ) )
1500
+ Ok ( result )
1375
1501
}
1376
1502
1377
1503
fn probe_inherent_assoc_ty (
@@ -2304,7 +2430,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2304
2430
hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2305
2431
debug ! ( ?qself, ?segment) ;
2306
2432
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)
2308
2434
. unwrap_or_else ( |guar| Const :: new_error ( tcx, guar) )
2309
2435
}
2310
2436
hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
@@ -2423,114 +2549,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2423
2549
}
2424
2550
}
2425
2551
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
-
2534
2552
/// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
2535
2553
#[ instrument( skip( self ) , level = "debug" ) ]
2536
2554
fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
@@ -2730,7 +2748,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2730
2748
hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2731
2749
debug ! ( ?qself, ?segment) ;
2732
2750
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 )
2734
2752
. map ( |( ty, _, _) | ty)
2735
2753
. unwrap_or_else ( |guar| Ty :: new_error ( tcx, guar) )
2736
2754
}
0 commit comments