@@ -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 , 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
///
@@ -1111,7 +1148,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1111
1148
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
1112
1149
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
1113
1150
#[ instrument( level = "debug" , skip_all, ret) ]
1114
- pub fn lower_assoc_path (
1151
+ pub fn lower_assoc_path_ty (
1115
1152
& self ,
1116
1153
hir_ref_id : HirId ,
1117
1154
span : Span ,
@@ -1120,6 +1157,56 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1120
1157
assoc_segment : & ' tcx hir:: PathSegment < ' tcx > ,
1121
1158
permit_variants : bool ,
1122
1159
) -> 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 > {
1123
1210
debug ! ( %qself_ty, ?assoc_segment. ident) ;
1124
1211
let tcx = self . tcx ( ) ;
1125
1212
@@ -1134,28 +1221,47 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1134
1221
. iter ( )
1135
1222
. find ( |vd| tcx. hygienic_eq ( assoc_ident, vd. ident ( tcx) , adt_def. did ( ) ) ) ;
1136
1223
if let Some ( variant_def) = variant_def {
1137
- if permit_variants {
1224
+ if mode . permit_variants ( ) {
1138
1225
tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
1139
1226
let _ = self . prohibit_generic_args (
1140
1227
slice:: from_ref ( assoc_segment) . iter ( ) ,
1141
1228
GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } ,
1142
1229
) ;
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
+ } ) ;
1144
1234
} else {
1145
1235
variant_resolution = Some ( variant_def. def_id ) ;
1146
1236
}
1147
1237
}
1148
1238
}
1149
1239
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
+ }
1159
1265
}
1160
1266
}
1161
1267
@@ -1184,7 +1290,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1184
1290
)
1185
1291
} ,
1186
1292
AssocItemQSelf :: SelfTyAlias ,
1187
- ty :: AssocKind :: Type ,
1293
+ mode . kind ( ) ,
1188
1294
assoc_ident,
1189
1295
span,
1190
1296
None ,
@@ -1196,14 +1302,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1196
1302
) => self . probe_single_ty_param_bound_for_assoc_item (
1197
1303
param_did. expect_local ( ) ,
1198
1304
qself. span ,
1199
- ty :: AssocKind :: Type ,
1305
+ mode . kind ( ) ,
1200
1306
assoc_ident,
1201
1307
span,
1202
1308
) ?,
1203
1309
_ => {
1310
+ let kind_str = assoc_kind_str ( mode. kind ( ) ) ;
1204
1311
let reported = if variant_resolution. is_some ( ) {
1205
1312
// 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}`" ) ;
1207
1314
self . dcx ( ) . span_err ( span, msg)
1208
1315
} else if qself_ty. is_enum ( ) {
1209
1316
let mut err = struct_span_code_err ! (
@@ -1311,18 +1418,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1311
1418
& [ qself_ty. to_string ( ) ] ,
1312
1419
& traits,
1313
1420
assoc_ident. name ,
1314
- ty :: AssocKind :: Type ,
1421
+ mode . kind ( ) ,
1315
1422
)
1316
1423
} ;
1317
1424
return Err ( reported) ;
1318
1425
}
1319
1426
} ;
1320
1427
1321
1428
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
+ } ;
1326
1452
1327
1453
if let Some ( variant_def_id) = variant_resolution {
1328
1454
tcx. node_span_lint ( AMBIGUOUS_ASSOCIATED_ITEMS , hir_ref_id, span, |lint| {
@@ -1338,7 +1464,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1338
1464
} ;
1339
1465
1340
1466
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" ) ;
1342
1468
1343
1469
lint. span_suggestion (
1344
1470
span,
@@ -1348,7 +1474,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1348
1474
) ;
1349
1475
} ) ;
1350
1476
}
1351
- Ok ( ( ty , DefKind :: AssocTy , assoc_ty . def_id ) )
1477
+ Ok ( result )
1352
1478
}
1353
1479
1354
1480
fn probe_inherent_assoc_ty (
@@ -2246,7 +2372,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2246
2372
hir:: ConstArgKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2247
2373
debug ! ( ?qself, ?segment) ;
2248
2374
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)
2250
2376
. unwrap_or_else ( |guar| Const :: new_error ( tcx, guar) )
2251
2377
}
2252
2378
hir:: ConstArgKind :: Path ( qpath @ hir:: QPath :: LangItem ( ..) ) => {
@@ -2361,114 +2487,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2361
2487
}
2362
2488
}
2363
2489
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
-
2472
2490
/// Literals are eagerly converted to a constant, everything else becomes `Unevaluated`.
2473
2491
#[ instrument( skip( self ) , level = "debug" ) ]
2474
2492
fn lower_anon_const ( & self , anon : & AnonConst ) -> Const < ' tcx > {
@@ -2666,7 +2684,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2666
2684
hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( qself, segment) ) => {
2667
2685
debug ! ( ?qself, ?segment) ;
2668
2686
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 )
2670
2688
. map ( |( ty, _, _) | ty)
2671
2689
. unwrap_or_else ( |guar| Ty :: new_error ( tcx, guar) )
2672
2690
}
0 commit comments