Disallow shadowing const parameters
This commit is contained in:
parent
3e827cc21e
commit
f749d88ae7
7 changed files with 124 additions and 15 deletions
|
@ -425,24 +425,29 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
|
ResolutionError::BindingShadowsSomethingUnacceptable {
|
||||||
let res = binding.res();
|
shadowing_binding_descr,
|
||||||
let shadows_what = res.descr();
|
name,
|
||||||
|
participle,
|
||||||
|
article,
|
||||||
|
shadowed_binding_descr,
|
||||||
|
shadowed_binding_span,
|
||||||
|
} => {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.session,
|
self.session,
|
||||||
span,
|
span,
|
||||||
E0530,
|
E0530,
|
||||||
"{}s cannot shadow {}s",
|
"{}s cannot shadow {}s",
|
||||||
what_binding,
|
shadowing_binding_descr,
|
||||||
shadows_what
|
shadowed_binding_descr,
|
||||||
);
|
);
|
||||||
err.span_label(
|
err.span_label(
|
||||||
span,
|
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 =
|
||||||
let msg = format!("the {} `{}` is {} here", shadows_what, name, participle);
|
format!("the {} `{}` is {} here", shadowed_binding_descr, name, participle);
|
||||||
err.span_label(binding.span, msg);
|
err.span_label(shadowed_binding_span, msg);
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
ResolutionError::ForwardDeclaredTyParam => {
|
ResolutionError::ForwardDeclaredTyParam => {
|
||||||
|
|
|
@ -1763,13 +1763,33 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
// to something unusable as a pattern (e.g., constructor function),
|
// to something unusable as a pattern (e.g., constructor function),
|
||||||
// but we still conservatively report an error, see
|
// but we still conservatively report an error, see
|
||||||
// issues/33118#issuecomment-233962221 for one reason why.
|
// issues/33118#issuecomment-233962221 for one reason why.
|
||||||
|
let binding = binding.expect("no binding for a ctor or static");
|
||||||
self.report_error(
|
self.report_error(
|
||||||
ident.span,
|
ident.span,
|
||||||
ResolutionError::BindingShadowsSomethingUnacceptable(
|
ResolutionError::BindingShadowsSomethingUnacceptable {
|
||||||
pat_src.descr(),
|
shadowing_binding_descr: pat_src.descr(),
|
||||||
ident.name,
|
name: ident.name,
|
||||||
binding.expect("no binding for a ctor or static"),
|
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
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,7 +234,14 @@ enum ResolutionError<'a> {
|
||||||
/* current */ &'static str,
|
/* current */ &'static str,
|
||||||
),
|
),
|
||||||
/// Error E0530: `X` bindings cannot shadow `Y`s.
|
/// 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.
|
/// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
|
||||||
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
|
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
|
||||||
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
|
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
|
||||||
|
|
12
src/test/ui/resolve/issue-85348.rs
Normal file
12
src/test/ui/resolve/issue-85348.rs
Normal file
|
@ -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
src/test/ui/resolve/issue-85348.stderr
Normal file
25
src/test/ui/resolve/issue-85348.stderr
Normal file
|
@ -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
src/test/ui/resolve/shadow-const-param.rs
Normal file
20
src/test/ui/resolve/shadow-const-param.rs
Normal file
|
@ -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
src/test/ui/resolve/shadow-const-param.stderr
Normal file
20
src/test/ui/resolve/shadow-const-param.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue