diff options
| author | bors <bors@rust-lang.org> | 2017-11-10 19:10:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-11-10 19:10:12 +0000 |
| commit | a35a3abcda67a729edbb7d649dbc663c6feabd4c (patch) | |
| tree | 57774687c76fadcb30a945409bcc3738d40901a0 /src/librustc_resolve | |
| parent | 75d25acd977085e6ae01d6a5c56cbbfc97463f89 (diff) | |
| parent | 765076faabcceba7cc75ae78c4923f89bb34975b (diff) | |
| download | rust-a35a3abcda67a729edbb7d649dbc663c6feabd4c.tar.gz rust-a35a3abcda67a729edbb7d649dbc663c6feabd4c.zip | |
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
Diffstat (limited to 'src/librustc_resolve')
| -rw-r--r-- | src/librustc_resolve/lib.rs | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 58bdf542fc9..8207057fd0a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -377,12 +377,6 @@ enum PatternSource { } impl PatternSource { - fn is_refutable(self) -> bool { - match self { - PatternSource::Match | PatternSource::IfLet | PatternSource::WhileLet => true, - PatternSource::Let | PatternSource::For | PatternSource::FnParam => false, - } - } fn descr(self) -> &'static str { match self { PatternSource::Match => "match binding", @@ -2388,20 +2382,24 @@ impl<'a> Resolver<'a> { false, pat.span) .and_then(LexicalScopeBinding::item); let resolution = binding.map(NameBinding::def).and_then(|def| { - let ivmode = BindingMode::ByValue(Mutability::Immutable); - let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || - bmode != ivmode; + let is_syntactic_ambiguity = opt_pat.is_none() && + bmode == BindingMode::ByValue(Mutability::Immutable); match def { Def::StructCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Const) | - Def::Const(..) if !always_binding => { - // A unit struct/variant or constant pattern. + Def::Const(..) if is_syntactic_ambiguity => { + // Disambiguate in favor of a unit struct/variant + // or constant pattern. self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span); Some(PathResolution::new(def)) } Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | Def::Static(..) => { - // A fresh binding that shadows something unacceptable. + // This is unambiguously a fresh binding, either syntactically + // (e.g. `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves + // 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. resolve_error( self, ident.span, @@ -2410,7 +2408,7 @@ impl<'a> Resolver<'a> { ); None } - Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => { + Def::Fn(..) | Def::Err => { // These entities are explicitly allowed // to be shadowed by fresh bindings. None |
