about summary refs log tree commit diff
path: root/src/librustc_resolve
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-11-10 19:10:12 +0000
committerbors <bors@rust-lang.org>2017-11-10 19:10:12 +0000
commita35a3abcda67a729edbb7d649dbc663c6feabd4c (patch)
tree57774687c76fadcb30a945409bcc3738d40901a0 /src/librustc_resolve
parent75d25acd977085e6ae01d6a5c56cbbfc97463f89 (diff)
parent765076faabcceba7cc75ae78c4923f89bb34975b (diff)
downloadrust-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.rs24
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