Auto merge of #45050 - petrochenkov:ambind, r=nikomatsakis

resolve: Use same rules for disambiguating fresh bindings in `match` and `let`

Resolve `Unit` as a unit struct pattern in
```rust
struct Unit;

let Unit = x;
```
consistently with
```rust
match x {
    Unit => {}
}
```
It was previously an error.
(The change also applies to unit variants and constants.)

Fixes https://users.rust-lang.org/t/e0530-cannot-shadow-unit-structs-what-in-the-earthly-what/13054
(This particular change doesn't depend on a fix for the issue mentioned in https://users.rust-lang.org/t/e0530-cannot-shadow-unit-structs-what-in-the-earthly-what/13054/4)

cc @rust-lang/lang
r? @nikomatsakis
This commit is contained in:
bors 2017-11-10 19:10:12 +00:00
commit a35a3abcda
9 changed files with 126 additions and 31 deletions

View file

@ -12,6 +12,6 @@ mod foo { pub struct bar; }
fn main() {
let bar = 5;
//~^ ERROR let bindings cannot shadow unit structs
//~^ ERROR mismatched types
use foo::bar;
}

View file

@ -14,6 +14,6 @@ struct Test;
fn main() {
|| {
let Test = 1; //~ ERROR let bindings cannot shadow unit structs
let Test = 1; //~ ERROR mismatched types
};
}

View file

@ -0,0 +1,67 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct UnitStruct;
struct TupleStruct();
struct BracedStruct{}
enum E {
UnitVariant,
TupleVariant(),
BracedVariant{},
}
use E::*;
const CONST: () = ();
static STATIC: () = ();
fn function() {}
fn main() {
let doesnt_matter = 0;
match UnitStruct {
UnitStruct => {} // OK, `UnitStruct` is a unit struct pattern
}
match doesnt_matter {
TupleStruct => {} //~ ERROR match bindings cannot shadow tuple structs
}
match doesnt_matter {
BracedStruct => {} // OK, `BracedStruct` is a fresh binding
}
match UnitVariant {
UnitVariant => {} // OK, `UnitVariant` is a unit variant pattern
}
match doesnt_matter {
TupleVariant => {} //~ ERROR match bindings cannot shadow tuple variants
}
match doesnt_matter {
BracedVariant => {} //~ ERROR match bindings cannot shadow struct variants
}
match CONST {
CONST => {} // OK, `CONST` is a const pattern
}
match doesnt_matter {
STATIC => {} //~ ERROR match bindings cannot shadow statics
}
match doesnt_matter {
function => {} // OK, `function` is a fresh binding
}
let UnitStruct = UnitStruct; // OK, `UnitStruct` is a unit struct pattern
let TupleStruct = doesnt_matter; //~ ERROR let bindings cannot shadow tuple structs
let BracedStruct = doesnt_matter; // OK, `BracedStruct` is a fresh binding
let UnitVariant = UnitVariant; // OK, `UnitVariant` is a unit variant pattern
let TupleVariant = doesnt_matter; //~ ERROR let bindings cannot shadow tuple variants
let BracedVariant = doesnt_matter; //~ ERROR let bindings cannot shadow struct variants
let CONST = CONST; // OK, `CONST` is a const pattern
let STATIC = doesnt_matter; //~ ERROR let bindings cannot shadow statics
let function = doesnt_matter; // OK, `function` is a fresh binding
}

View file

@ -13,17 +13,14 @@ mod foo {
pub const d: u8 = 2;
}
use foo::b as c; //~ NOTE is imported here
use foo::d; //~ NOTE is imported here
use foo::b as c;
use foo::d;
const a: u8 = 2; //~ NOTE is defined here
const a: u8 = 2;
fn main() {
let a = 4; //~ ERROR let bindings cannot shadow constants
//~^ NOTE cannot be named the same as a constant
let c = 4; //~ ERROR let bindings cannot shadow constants
//~^ NOTE cannot be named the same as a constant
let d = 4; //~ ERROR let bindings cannot shadow constants
//~^ NOTE cannot be named the same as a constant
let a = 4; //~ ERROR refutable pattern in local binding: `_` not covered
let c = 4; //~ ERROR refutable pattern in local binding: `_` not covered
let d = 4; //~ ERROR refutable pattern in local binding: `_` not covered
fn f() {} // Check that the `NOTE`s still work with an item here (c.f. issue #35115).
}

View file

@ -0,0 +1,20 @@
error[E0005]: refutable pattern in local binding: `_` not covered
--> $DIR/const-pattern-irrefutable.rs:22:9
|
22 | let a = 4; //~ ERROR refutable pattern in local binding: `_` not covered
| ^ interpreted as a constant pattern, not new variable
error[E0005]: refutable pattern in local binding: `_` not covered
--> $DIR/const-pattern-irrefutable.rs:23:9
|
23 | let c = 4; //~ ERROR refutable pattern in local binding: `_` not covered
| ^ interpreted as a constant pattern, not new variable
error[E0005]: refutable pattern in local binding: `_` not covered
--> $DIR/const-pattern-irrefutable.rs:24:9
|
24 | let d = 4; //~ ERROR refutable pattern in local binding: `_` not covered
| ^ interpreted as a constant pattern, not new variable
error: aborting due to 3 previous errors

View file

@ -8,11 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::option::*;
fn main() {
let None: isize = 42; //~ ERROR let bindings cannot shadow unit variants
log(debug, None);
//~^ ERROR cannot find function `log` in this scope
//~| ERROR cannot find value `debug` in this scope
let None: isize = 42; //~ ERROR mismatched types
}

View file

@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/name-clash-nullary.rs:12:7
|
12 | let None: isize = 42; //~ ERROR mismatched types
| ^^^^ expected isize, found enum `std::option::Option`
|
= note: expected type `isize`
found type `std::option::Option<_>`
error: aborting due to previous error