@@ -51,6 +51,7 @@ use rustc_trait_selection::traits::wf::object_region_bounds;
51
51
use rustc_trait_selection:: traits:: { self , ObligationCtxt } ;
52
52
use tracing:: { debug, instrument} ;
53
53
54
+ use self :: errors:: assoc_kind_str;
54
55
use crate :: bounds:: Bounds ;
55
56
use crate :: check:: check_abi_fn_ptr;
56
57
use crate :: errors:: { AmbiguousLifetimeBound , BadReturnTypeNotation , InvalidBaseType , WildPatTy } ;
@@ -261,6 +262,42 @@ pub enum FeedConstTy {
261
262
No ,
262
263
}
263
264
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
+
264
301
/// New-typed boolean indicating whether explicit late-bound lifetimes
265
302
/// are present in a set of generic arguments.
266
303
///
@@ -1112,7 +1149,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1112
1149
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
1113
1150
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
1114
1151
#[ instrument( level = "debug" , skip_all, ret) ]
1115
- pub fn lower_assoc_path (
1152
+ pub fn lower_assoc_path_ty (
1116
1153
& self ,
1117
1154
hir_ref_id : HirId ,
1118
1155
span : Span ,
@@ -1121,6 +1158,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1121
1158
assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1122
1159
permit_variants : bool ,
1123
1160
) -> 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 > {
1124
1211
debug ! ( %qself_ty, ?assoc_segment. ident) ;
1125
1212
let tcx = self . tcx ( ) ;
1126
1213
@@ -1135,28 +1222,47 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1135
1222
. iter ( )
1136
1223
. find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
1137
1224
if let Some ( variant_def) = variant_def {
1138
- if permit_variants {
1225
+ if mode . permit_variants ( ) {
1139
1226
tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
1140
1227
let _ = self . prohibit_generic_args (
1141
1228
slice:: from_ref ( assoc_segment) . iter ( ) ,
1142
1229
GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
1143
1230
) ;
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
+ } ) ;
1145
1235
} else {
1146
1236
variant_resolution = Some ( variant_def. def_id ) ;
1147
1237
}
1148
1238
}
1149
1239
}
1150
1240
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
+ }
1160
1266
}
1161
1267
}
1162
1268
@@ -1185,7 +1291,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1185
1291
)
1186
1292
} ,
1187
1293
AssocItemQSelf :: SelfTyAlias ,
1188
- ty :: AssocKind :: Type ,
1294
+ mode . kind ( ) ,
1189
1295
assoc_ident,
1190
1296
span,
1191
1297
None ,
@@ -1197,14 +1303,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1197
1303
) => self . probe_single_ty_param_bound_for_assoc_item (
1198
1304
param_did. expect_local ( ) ,
1199
1305
qself. span ,
1200
- ty :: AssocKind :: Type ,
1306
+ mode . kind ( ) ,
1201
1307
assoc_ident,
1202
1308
span,
1203
1309
) ?,
1204
1310
_ => {
1311
+ let kind_str = assoc_kind_str ( mode. kind ( ) ) ;
1205
1312
let reported = if variant_resolution. is_some ( ) {
1206
1313
// 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}`" ) ;
1208
1315
self . dcx ( ) . span_err ( span, msg)
1209
1316
} else if qself_ty. is_enum ( ) {
1210
1317
let mut err = struct_span_code_err ! (
@@ -1312,18 +1419,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1312
1419
& [ qself_ty. to_string ( ) ] ,
1313
1420
& traits,
1314
1421
assoc_ident. name ,
1315
- ty :: AssocKind :: Type ,
1422
+ mode . kind ( ) ,
1316
1423
)
1317
1424
} ;
1318
1425
return Err ( reported) ;
1319
1426
}
1320
1427
} ;
1321
1428
1322
1429
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
+ } ;
1327
1453
1328
1454
if let Some ( variant_def_id) = variant_resolution {
1329
1455
tcx. node_span_lint ( AMBIGUOUS_ASSOCIATED_ITEMS , hir_ref_id, span, |lint| {
@@ -1339,7 +1465,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1339
1465
} ;
1340
1466
1341
1467
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" ) ;
1343
1469
1344
1470
lint. span_suggestion (
1345
1471
span,
@@ -1349,7 +1475,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1349
1475
) ;
1350
1476
} ) ;
1351
1477
}
1352
- Ok ( ( ty , DefKind :: AssocTy , assoc_ty . def_id ) )
1478
+ Ok ( result )
1353
1479
}
1354
1480
1355
1481
fn probe_inherent_assoc_ty (
@@ -2247,7 +2373,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2247
2373
hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2248
2374
debug ! ( ?qself, ?segment) ;
2249
2375
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)
2251
2377
. unwrap_or_else ( |guar| Const :: new_error ( tcx, guar) )
2252
2378
}
2253
2379
hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
@@ -2362,114 +2488,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2362
2488
}
2363
2489
}
2364
2490
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
-
2473
2491
/// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
2474
2492
#[ instrument( skip( self ) , level = "debug" ) ]
2475
2493
fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
@@ -2670,7 +2688,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2670
2688
hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2671
2689
debug ! ( ?qself, ?segment) ;
2672
2690
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 )
2674
2692
. map ( |( ty, _, _) | ty)
2675
2693
. unwrap_or_else ( |guar| Ty :: new_error ( tcx, guar) )
2676
2694
}
0 commit comments