Skip to content

Commit 69c78a9

Browse files
authored
Rollup merge of #85478 - FabianWolff:issue-85348, r=petrochenkov
Disallow shadowing const parameters This pull request fixes #85348. Trying to shadow a `const` parameter as follows: ```rust fn foo<const N: i32>() { let N @ _ = 0; } ``` currently causes an ICE. With my changes, I get: ``` error[E0530]: let bindings cannot shadow const parameters --> test.rs:2:9 | 1 | fn foo<const N: i32>() { | - the const parameter `N` is defined here 2 | let N @ _ = 0; | ^ cannot be named the same as a const parameter error: aborting due to previous error ``` This is the same error you get when trying to shadow a constant: ```rust const N: i32 = 0; let N @ _ = 0; ``` ``` error[E0530]: let bindings cannot shadow constants --> src/lib.rs:3:5 | 2 | const N: i32 = 0; | ----------------- the constant `N` is defined here 3 | let N @ _ = 0; | ^ cannot be named the same as a constant error: aborting due to previous error ``` The reason for disallowing shadowing in both cases is described [here](#33118 (comment)) (the comment there only talks about constants, but the same reasoning applies to `const` parameters).
2 parents 1969c2e + f749d88 commit 69c78a9

File tree

7 files changed

+124
-15
lines changed

7 files changed

+124
-15
lines changed

compiler/rustc_resolve/src/diagnostics.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -425,24 +425,29 @@ impl<'a> Resolver<'a> {
425425
}
426426
err
427427
}
428-
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
429-
let res = binding.res();
430-
let shadows_what = res.descr();
428+
ResolutionError::BindingShadowsSomethingUnacceptable {
429+
shadowing_binding_descr,
430+
name,
431+
participle,
432+
article,
433+
shadowed_binding_descr,
434+
shadowed_binding_span,
435+
} => {
431436
let mut err = struct_span_err!(
432437
self.session,
433438
span,
434439
E0530,
435440
"{}s cannot shadow {}s",
436-
what_binding,
437-
shadows_what
441+
shadowing_binding_descr,
442+
shadowed_binding_descr,
438443
);
439444
err.span_label(
440445
span,
441-
format!("cannot be named the same as {} {}", res.article(), shadows_what),
446+
format!("cannot be named the same as {} {}", article, shadowed_binding_descr),
442447
);
443-
let participle = if binding.is_import() { "imported" } else { "defined" };
444-
let msg = format!("the {} `{}` is {} here", shadows_what, name, participle);
445-
err.span_label(binding.span, msg);
448+
let msg =
449+
format!("the {} `{}` is {} here", shadowed_binding_descr, name, participle);
450+
err.span_label(shadowed_binding_span, msg);
446451
err
447452
}
448453
ResolutionError::ForwardDeclaredTyParam => {

compiler/rustc_resolve/src/late.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -1763,13 +1763,33 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
17631763
// to something unusable as a pattern (e.g., constructor function),
17641764
// but we still conservatively report an error, see
17651765
// issues/33118#issuecomment-233962221 for one reason why.
1766+
let binding = binding.expect("no binding for a ctor or static");
17661767
self.report_error(
17671768
ident.span,
1768-
ResolutionError::BindingShadowsSomethingUnacceptable(
1769-
pat_src.descr(),
1770-
ident.name,
1771-
binding.expect("no binding for a ctor or static"),
1772-
),
1769+
ResolutionError::BindingShadowsSomethingUnacceptable {
1770+
shadowing_binding_descr: pat_src.descr(),
1771+
name: ident.name,
1772+
participle: if binding.is_import() { "imported" } else { "defined" },
1773+
article: binding.res().article(),
1774+
shadowed_binding_descr: binding.res().descr(),
1775+
shadowed_binding_span: binding.span,
1776+
},
1777+
);
1778+
None
1779+
}
1780+
Res::Def(DefKind::ConstParam, def_id) => {
1781+
// Same as for DefKind::Const above, but here, `binding` is `None`, so we
1782+
// have to construct the error differently
1783+
self.report_error(
1784+
ident.span,
1785+
ResolutionError::BindingShadowsSomethingUnacceptable {
1786+
shadowing_binding_descr: pat_src.descr(),
1787+
name: ident.name,
1788+
participle: "defined",
1789+
article: res.article(),
1790+
shadowed_binding_descr: res.descr(),
1791+
shadowed_binding_span: self.r.opt_span(def_id).expect("const parameter defined outside of local crate"),
1792+
}
17731793
);
17741794
None
17751795
}

compiler/rustc_resolve/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,14 @@ enum ResolutionError<'a> {
233233
/* current */ &'static str,
234234
),
235235
/// Error E0530: `X` bindings cannot shadow `Y`s.
236-
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
236+
BindingShadowsSomethingUnacceptable {
237+
shadowing_binding_descr: &'static str,
238+
name: Symbol,
239+
participle: &'static str,
240+
article: &'static str,
241+
shadowed_binding_descr: &'static str,
242+
shadowed_binding_span: Span,
243+
},
237244
/// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
238245
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
239246
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.

src/test/ui/resolve/issue-85348.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Checks whether shadowing a const parameter leads to an ICE (#85348).
2+
3+
impl<const N: usize> ArrayWindowsExample {
4+
//~^ ERROR: cannot find type `ArrayWindowsExample` in this scope [E0412]
5+
fn next() {
6+
let mut N;
7+
//~^ ERROR: let bindings cannot shadow const parameters [E0530]
8+
//~| ERROR: type annotations needed [E0282]
9+
}
10+
}
11+
12+
fn main() {}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0530]: let bindings cannot shadow const parameters
2+
--> $DIR/issue-85348.rs:6:17
3+
|
4+
LL | impl<const N: usize> ArrayWindowsExample {
5+
| - the const parameter `N` is defined here
6+
...
7+
LL | let mut N;
8+
| ^ cannot be named the same as a const parameter
9+
10+
error[E0412]: cannot find type `ArrayWindowsExample` in this scope
11+
--> $DIR/issue-85348.rs:3:22
12+
|
13+
LL | impl<const N: usize> ArrayWindowsExample {
14+
| ^^^^^^^^^^^^^^^^^^^ not found in this scope
15+
16+
error[E0282]: type annotations needed
17+
--> $DIR/issue-85348.rs:6:13
18+
|
19+
LL | let mut N;
20+
| ^^^^^ consider giving `N` a type
21+
22+
error: aborting due to 3 previous errors
23+
24+
Some errors have detailed explanations: E0282, E0412, E0530.
25+
For more information about an error, try `rustc --explain E0282`.
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Checks that const parameters cannot be shadowed with fresh bindings
2+
// even in syntactically unambiguous contexts. See
3+
// https://github.com/rust-lang/rust/issues/33118#issuecomment-233962221
4+
5+
fn foo<const N: i32>(i: i32) -> bool {
6+
match i {
7+
N @ _ => true,
8+
//~^ ERROR: match bindings cannot shadow const parameters [E0530]
9+
}
10+
}
11+
12+
fn bar<const N: i32>(i: i32) -> bool {
13+
let N @ _ = 0;
14+
//~^ ERROR: let bindings cannot shadow const parameters [E0530]
15+
match i {
16+
N @ _ => true,
17+
}
18+
}
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0530]: match bindings cannot shadow const parameters
2+
--> $DIR/shadow-const-param.rs:7:9
3+
|
4+
LL | fn foo<const N: i32>(i: i32) -> bool {
5+
| - the const parameter `N` is defined here
6+
LL | match i {
7+
LL | N @ _ => true,
8+
| ^ cannot be named the same as a const parameter
9+
10+
error[E0530]: let bindings cannot shadow const parameters
11+
--> $DIR/shadow-const-param.rs:13:9
12+
|
13+
LL | fn bar<const N: i32>(i: i32) -> bool {
14+
| - the const parameter `N` is defined here
15+
LL | let N @ _ = 0;
16+
| ^ cannot be named the same as a const parameter
17+
18+
error: aborting due to 2 previous errors
19+
20+
For more information about this error, try `rustc --explain E0530`.

0 commit comments

Comments
 (0)