diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 56d3b927dc592..fda7c7aeb3306 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -623,6 +623,69 @@ let Foo = 12i32; // ok! The goal here is to avoid a conflict of names. "##, +E0414: r##" +A variable binding in an irrefutable pattern is shadowing the name of a +constant. Example of erroneous code: + +```compile_fail +const FOO: u8 = 7; + +let FOO = 5; // error: variable bindings cannot shadow constants + +// or + +fn bar(FOO: u8) { // error: variable bindings cannot shadow constants + +} + +// or + +for FOO in bar { + +} +``` + +Introducing a new variable in Rust is done through a pattern. Thus you can have +`let` bindings like `let (a, b) = ...`. However, patterns also allow constants +in them, e.g. if you want to match over a constant: + +```ignore +const FOO: u8 = 1; + +match (x,y) { + (3, 4) => { .. }, // it is (3,4) + (FOO, 1) => { .. }, // it is (1,1) + (foo, 1) => { .. }, // it is (anything, 1) + // call the value in the first slot "foo" + _ => { .. } // it is anything +} +``` + +Here, the second arm matches the value of `x` against the constant `FOO`, +whereas the third arm will accept any value of `x` and call it `foo`. + +This works for `match`, however in cases where an irrefutable pattern is +required, constants can't be used. An irrefutable pattern is one which always +matches, whose purpose is only to bind variable names to values. These are +required by let, for, and function argument patterns. + +Refutable patterns in such a situation do not make sense, for example: + +```ignore +let Some(x) = foo; // what if foo is None, instead? + +let (1, x) = foo; // what if foo.0 is not 1? + +let (SOME_CONST, x) = foo; // what if foo.0 is not SOME_CONST? + +let SOME_CONST = foo; // what if foo is not SOME_CONST? +``` + +Thus, an irrefutable variable binding can't contain a constant. + +To fix this error, just give the marked variable a different name. +"##, + E0415: r##" More than one function parameter have the same name. Example of erroneous code: @@ -1086,7 +1149,6 @@ register_diagnostics! { E0409, // variable is bound with different mode in pattern # than in // pattern #1 E0410, // variable from pattern is not bound in pattern 1 - E0414, // only irrefutable patterns allowed here E0418, // is not an enum variant, struct or const E0420, // is not an associated const E0421, // unresolved associated const diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ff412be323a7f..7c6c76f130efe 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -139,7 +139,7 @@ enum ResolutionError<'a> { /// error E0413: declaration shadows an enum variant or unit-like struct in scope DeclarationShadowsEnumVariantOrUnitLikeStruct(Name), /// error E0414: only irrefutable patterns allowed here - OnlyIrrefutablePatternsAllowedHere(Name), + ConstantForIrrefutableBinding(Name), /// error E0415: identifier is bound more than once in this parameter list IdentifierBoundMoreThanOnceInParameterList(&'a str), /// error E0416: identifier is bound more than once in the same pattern @@ -321,11 +321,11 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, or unit-like struct in scope", name) } - ResolutionError::OnlyIrrefutablePatternsAllowedHere(name) => { + ResolutionError::ConstantForIrrefutableBinding(name) => { let mut err = struct_span_err!(resolver.session, span, E0414, - "only irrefutable patterns allowed here"); + "variable bindings cannot shadow constants"); err.span_note(span, "there already is a constant in scope sharing the same \ name as this pattern"); @@ -2248,7 +2248,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, pattern.span, - ResolutionError::OnlyIrrefutablePatternsAllowedHere(name) + ResolutionError::ConstantForIrrefutableBinding(name) ); self.record_def(pattern.id, err_path_resolution()); } diff --git a/src/test/compile-fail/const-pattern-irrefutable.rs b/src/test/compile-fail/const-pattern-irrefutable.rs index 825c39011fcc1..0be1e974e7d7d 100644 --- a/src/test/compile-fail/const-pattern-irrefutable.rs +++ b/src/test/compile-fail/const-pattern-irrefutable.rs @@ -19,10 +19,10 @@ use foo::d; //~ NOTE constant imported here const a: u8 = 2; //~ NOTE constant defined here fn main() { - let a = 4; //~ ERROR only irrefutable + let a = 4; //~ ERROR variable bindings cannot //~^ NOTE there already is a constant in scope - let c = 4; //~ ERROR only irrefutable + let c = 4; //~ ERROR variable bindings cannot //~^ NOTE there already is a constant in scope - let d = 4; //~ ERROR only irrefutable + let d = 4; //~ ERROR variable bindings cannot //~^ NOTE there already is a constant in scope } diff --git a/src/test/compile-fail/issue-27033.rs b/src/test/compile-fail/issue-27033.rs index 051edfe5f451b..a729cf95a7bf3 100644 --- a/src/test/compile-fail/issue-27033.rs +++ b/src/test/compile-fail/issue-27033.rs @@ -14,7 +14,7 @@ fn main() { }; const C: u8 = 1; match 1 { - C @ 2 => { //~ ERROR only irrefutable patterns allowed here + C @ 2 => { //~ ERROR variable bindings cannot shadow constants println!("{}", C); } _ => {}