Skip to content

Commit 4307c75

Browse files
Rollup merge of rust-lang#126228 - BoxyUwU:nested_repeat_expr_generics, r=compiler-errors
Provide correct parent for nested anon const Fixes rust-lang#126147 99% of this PR is just comments explaining what the issue is. `tcx.parent(` and `hir().get_parent_item(` give different results as the hir owner for all the hir of anon consts is the enclosing function. I didn't attempt to change that as being a hir owner requires a `DefId` and long term we want to stop creating anon consts' `DefId`s before hir ty lowering. So i just opted to change `generics_of` to use `tcx.parent` to get the parent for `AnonConst`'s. I'm not entirely sure about this being what we want, it does seem weird that we have two ways of getting the parent of an `AnonConst` and they both give different results. Alternatively we could just go ahead and make `const_evaluatable_unchecked` a hard error and stop providing generics to repeat exprs. Then this isn't an issue. (The FCW has been around for almost 4 years now) r? ```@compiler-errors```
2 parents 343a659 + bfb7757 commit 4307c75

File tree

3 files changed

+52
-5
lines changed

3 files changed

+52
-5
lines changed

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+21-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_session::lint;
1111
use rustc_span::symbol::{kw, Symbol};
1212
use rustc_span::Span;
1313

14+
#[instrument(level = "debug", skip(tcx))]
1415
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
1516
use rustc_hir::*;
1617

@@ -66,7 +67,22 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
6667
// FIXME(#43408) always enable this once `lazy_normalization` is
6768
// stable enough and does not need a feature gate anymore.
6869
Node::AnonConst(_) => {
69-
let parent_def_id = tcx.hir().get_parent_item(hir_id);
70+
let parent_did = tcx.parent(def_id.to_def_id());
71+
72+
// We don't do this unconditionally because the `DefId` parent of an anon const
73+
// might be an implicitly created closure during `async fn` desugaring. This would
74+
// have the wrong generics.
75+
//
76+
// i.e. `async fn foo<'a>() { let a = [(); { 1 + 2 }]; bar().await() }`
77+
// would implicitly have a closure in its body that would be the parent of
78+
// the `{ 1 + 2 }` anon const. This closure's generics is simply a witness
79+
// instead of `['a]`.
80+
let parent_did = if let DefKind::AnonConst = tcx.def_kind(parent_did) {
81+
parent_did
82+
} else {
83+
tcx.hir().get_parent_item(hir_id).to_def_id()
84+
};
85+
debug!(?parent_did);
7086

7187
let mut in_param_ty = false;
7288
for (_parent, node) in tcx.hir().parent_iter(hir_id) {
@@ -121,7 +137,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
121137
//
122138
// This has some implications for how we get the predicates available to the anon const
123139
// see `explicit_predicates_of` for more information on this
124-
let generics = tcx.generics_of(parent_def_id.to_def_id());
140+
let generics = tcx.generics_of(parent_did);
125141
let param_def_idx = generics.param_def_id_to_index[&param_id.to_def_id()];
126142
// In the above example this would be .params[..N#0]
127143
let own_params = generics.params_to(param_def_idx as usize, tcx).to_owned();
@@ -147,7 +163,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
147163
//
148164
// Note that we do not supply the parent generics when using
149165
// `min_const_generics`.
150-
Some(parent_def_id.to_def_id())
166+
Some(parent_did)
151167
}
152168
} else {
153169
let parent_node = tcx.parent_hir_node(hir_id);
@@ -159,7 +175,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
159175
Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
160176
if constant.hir_id() == hir_id =>
161177
{
162-
Some(parent_def_id.to_def_id())
178+
Some(parent_did)
163179
}
164180
// Exclude `GlobalAsm` here which cannot have generics.
165181
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
@@ -171,7 +187,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
171187
_ => false,
172188
}) =>
173189
{
174-
Some(parent_def_id.to_def_id())
190+
Some(parent_did)
175191
}
176192
_ => None,
177193
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Given an anon const `a`: `{ N }` and some anon const `b` which references the
2+
// first anon const: `{ [1; a] }`. `b` should not have any generics as it is not
3+
// a simple `N` argument nor is it a repeat expr count.
4+
//
5+
// On the other hand `b` *is* a repeat expr count and so it should inherit its
6+
// parents generics as part of the `const_evaluatable_unchecked` fcw (#76200).
7+
//
8+
// In this specific case however `b`'s parent should be `a` and so it should wind
9+
// up not having any generics after all. If `a` were to inherit its generics from
10+
// the enclosing item then the reference to `a` from `b` would contain generic
11+
// parameters not usable by `b` which would cause us to ICE.
12+
13+
fn bar<const N: usize>() {}
14+
15+
fn foo<const N: usize>() {
16+
bar::<{ [1; N] }>();
17+
//~^ ERROR: generic parameters may not be used in const operations
18+
}
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: generic parameters may not be used in const operations
2+
--> $DIR/repeat_expr_hack_gives_right_generics.rs:16:17
3+
|
4+
LL | bar::<{ [1; N] }>();
5+
| ^ cannot perform const operation using `N`
6+
|
7+
= help: const parameters may only be used as standalone arguments, i.e. `N`
8+
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
9+
10+
error: aborting due to 1 previous error
11+

0 commit comments

Comments
 (0)