@@ -1441,16 +1441,43 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
1441
1441
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
1442
1442
None
1443
1443
} else if tcx. lazy_normalization ( ) {
1444
- // Only provide backwards declared generics to cg defaults (#86580)
1445
1444
if let Some ( param_id) = tcx. hir ( ) . opt_const_param_default_param_hir_id ( hir_id) {
1445
+ // If the def_id we are calling generics_of on is an anon ct default i.e:
1446
+ //
1447
+ // struct Foo<const N: usize = { .. }>;
1448
+ // ^^^ ^ ^^^^^^ def id of this anon const
1449
+ // ^ ^ param_id
1450
+ // ^ parent_def_id
1451
+ //
1452
+ // then we only want to return generics for params to the left of `N`. If we don't do that we
1453
+ // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, substs: [N#0])`.
1454
+ //
1455
+ // This causes ICEs (#86580) when building the substs for Foo in `fn foo() -> Foo { .. }` as
1456
+ // we substitute the defaults with the partially built substs when we build the substs. Subst'ing
1457
+ // the `N#0` on the unevaluated const indexes into the empty substs we're in the process of building.
1458
+ //
1459
+ // We fix this by having this function return the parent's generics ourselves and truncating the
1460
+ // generics to only include non-forward declared params (with the exception of the `Self` ty)
1461
+ //
1462
+ // For the above code example that means we want `substs: []`
1463
+ // For the following struct def we want `substs: [N#0]` when generics_of is called on
1464
+ // the def id of the `{ N + 1 }` anon const
1465
+ // struct Foo<const N: usize, const M: usize = { N + 1 }>;
1466
+ //
1467
+ // This has some implications for how we get the predicates available to the anon const
1468
+ // see `explicit_predicates_of` for more information on this
1446
1469
let generics = tcx. generics_of ( parent_def_id. to_def_id ( ) ) ;
1447
1470
let param_def = tcx. hir ( ) . local_def_id ( param_id) . to_def_id ( ) ;
1448
1471
let param_def_idx = generics. param_def_id_to_index [ & param_def] ;
1472
+ // In the above example this would be .params[..N#0]
1449
1473
let params = generics. params [ ..param_def_idx as usize ] . to_owned ( ) ;
1450
1474
let param_def_id_to_index =
1451
1475
params. iter ( ) . map ( |param| ( param. def_id , param. index ) ) . collect ( ) ;
1452
1476
1453
1477
return ty:: Generics {
1478
+ // we set the parent of these generics to be our parent's parent so that we
1479
+ // dont end up with substs: [N, M, N] for the const default on a struct like this:
1480
+ // struct Foo<const N: usize, const M: usize = { ... }>;
1454
1481
parent : generics. parent ,
1455
1482
parent_count : generics. parent_count ,
1456
1483
params,
@@ -2425,12 +2452,22 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
2425
2452
}
2426
2453
} else {
2427
2454
if matches ! ( def_kind, DefKind :: AnonConst ) && tcx. lazy_normalization ( ) {
2428
- // Provide predicates of parent item of cg defaults manually as `generics_of`
2429
- // doesn't set the parent item as the parent for the generics (#86580)
2430
2455
let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id. expect_local ( ) ) ;
2431
2456
if let Some ( _) = tcx. hir ( ) . opt_const_param_default_param_hir_id ( hir_id) {
2457
+ // In `generics_of` we set the generics' parent to be our parent's parent which means that
2458
+ // we lose out on the predicates of our actual parent if we dont return those predicates here.
2459
+ // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
2460
+ //
2461
+ // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
2462
+ // ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
2463
+ // ^^^ explicit_predicates_of on
2464
+ // parent item we dont have set as the
2465
+ // parent of generics returned by `generics_of`
2466
+ //
2467
+ // In the above code we want the anon const to have predicates in its param env for `T: Trait`
2432
2468
let item_id = tcx. hir ( ) . get_parent_item ( hir_id) ;
2433
2469
let item_def_id = tcx. hir ( ) . local_def_id ( item_id) . to_def_id ( ) ;
2470
+ // In the above code example we would be calling `explicit_predicates_of(Foo)` here
2434
2471
return tcx. explicit_predicates_of ( item_def_id) ;
2435
2472
}
2436
2473
}
0 commit comments