Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow shadowing const parameters #85478

Merged
merged 1 commit into from
May 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,24 +425,29 @@ impl<'a> Resolver<'a> {
}
err
}
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
let res = binding.res();
let shadows_what = res.descr();
ResolutionError::BindingShadowsSomethingUnacceptable {
shadowing_binding_descr,
name,
participle,
article,
shadowed_binding_descr,
shadowed_binding_span,
} => {
let mut err = struct_span_err!(
self.session,
span,
E0530,
"{}s cannot shadow {}s",
what_binding,
shadows_what
shadowing_binding_descr,
shadowed_binding_descr,
);
err.span_label(
span,
format!("cannot be named the same as {} {}", res.article(), shadows_what),
format!("cannot be named the same as {} {}", article, shadowed_binding_descr),
);
let participle = if binding.is_import() { "imported" } else { "defined" };
let msg = format!("the {} `{}` is {} here", shadows_what, name, participle);
err.span_label(binding.span, msg);
let msg =
format!("the {} `{}` is {} here", shadowed_binding_descr, name, participle);
err.span_label(shadowed_binding_span, msg);
err
}
ResolutionError::ForwardDeclaredTyParam => {
Expand Down
30 changes: 25 additions & 5 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1763,13 +1763,33 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// to something unusable as a pattern (e.g., constructor function),
// but we still conservatively report an error, see
// issues/33118#issuecomment-233962221 for one reason why.
let binding = binding.expect("no binding for a ctor or static");
self.report_error(
ident.span,
ResolutionError::BindingShadowsSomethingUnacceptable(
pat_src.descr(),
ident.name,
binding.expect("no binding for a ctor or static"),
),
ResolutionError::BindingShadowsSomethingUnacceptable {
shadowing_binding_descr: pat_src.descr(),
name: ident.name,
participle: if binding.is_import() { "imported" } else { "defined" },
article: binding.res().article(),
shadowed_binding_descr: binding.res().descr(),
shadowed_binding_span: binding.span,
},
);
None
}
Res::Def(DefKind::ConstParam, def_id) => {
// Same as for DefKind::Const above, but here, `binding` is `None`, so we
// have to construct the error differently
self.report_error(
ident.span,
ResolutionError::BindingShadowsSomethingUnacceptable {
shadowing_binding_descr: pat_src.descr(),
name: ident.name,
participle: "defined",
article: res.article(),
shadowed_binding_descr: res.descr(),
shadowed_binding_span: self.r.opt_span(def_id).expect("const parameter defined outside of local crate"),
}
);
None
}
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,14 @@ enum ResolutionError<'a> {
/* current */ &'static str,
),
/// Error E0530: `X` bindings cannot shadow `Y`s.
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
BindingShadowsSomethingUnacceptable {
shadowing_binding_descr: &'static str,
name: Symbol,
participle: &'static str,
article: &'static str,
shadowed_binding_descr: &'static str,
shadowed_binding_span: Span,
},
/// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/resolve/issue-85348.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Checks whether shadowing a const parameter leads to an ICE (#85348).

impl<const N: usize> ArrayWindowsExample {
//~^ ERROR: cannot find type `ArrayWindowsExample` in this scope [E0412]
fn next() {
let mut N;
//~^ ERROR: let bindings cannot shadow const parameters [E0530]
//~| ERROR: type annotations needed [E0282]
}
}

fn main() {}
25 changes: 25 additions & 0 deletions src/test/ui/resolve/issue-85348.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error[E0530]: let bindings cannot shadow const parameters
--> $DIR/issue-85348.rs:6:17
|
LL | impl<const N: usize> ArrayWindowsExample {
| - the const parameter `N` is defined here
...
LL | let mut N;
| ^ cannot be named the same as a const parameter

error[E0412]: cannot find type `ArrayWindowsExample` in this scope
--> $DIR/issue-85348.rs:3:22
|
LL | impl<const N: usize> ArrayWindowsExample {
| ^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0282]: type annotations needed
--> $DIR/issue-85348.rs:6:13
|
LL | let mut N;
| ^^^^^ consider giving `N` a type

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0282, E0412, E0530.
For more information about an error, try `rustc --explain E0282`.
20 changes: 20 additions & 0 deletions src/test/ui/resolve/shadow-const-param.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Checks that const parameters cannot be shadowed with fresh bindings
// even in syntactically unambiguous contexts. See
// https://github.com/rust-lang/rust/issues/33118#issuecomment-233962221

fn foo<const N: i32>(i: i32) -> bool {
match i {
N @ _ => true,
//~^ ERROR: match bindings cannot shadow const parameters [E0530]
}
}

fn bar<const N: i32>(i: i32) -> bool {
let N @ _ = 0;
//~^ ERROR: let bindings cannot shadow const parameters [E0530]
match i {
N @ _ => true,
}
}

fn main() {}
20 changes: 20 additions & 0 deletions src/test/ui/resolve/shadow-const-param.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0530]: match bindings cannot shadow const parameters
--> $DIR/shadow-const-param.rs:7:9
|
LL | fn foo<const N: i32>(i: i32) -> bool {
| - the const parameter `N` is defined here
LL | match i {
LL | N @ _ => true,
| ^ cannot be named the same as a const parameter

error[E0530]: let bindings cannot shadow const parameters
--> $DIR/shadow-const-param.rs:13:9
|
LL | fn bar<const N: i32>(i: i32) -> bool {
| - the const parameter `N` is defined here
LL | let N @ _ = 0;
| ^ cannot be named the same as a const parameter

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0530`.