]> git.lizzy.rs Git - rust.git/commitdiff
resolve: Prevent fresh bindings from shadowing ambiguity items
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 14 Mar 2020 16:44:11 +0000 (19:44 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sun, 15 Mar 2020 09:35:48 +0000 (12:35 +0300)
Correctly treat const generic parameters in fresh binding disambiguation

src/librustc_mir_build/hair/pattern/check_match.rs
src/librustc_mir_build/hair/pattern/mod.rs
src/librustc_resolve/late.rs
src/librustc_resolve/lib.rs
src/librustc_typeck/check/pat.rs
src/test/ui/binding/ambiguity-item.rs [new file with mode: 0644]
src/test/ui/binding/ambiguity-item.stderr [new file with mode: 0644]
src/test/ui/binding/const-param.rs [new file with mode: 0644]
src/test/ui/binding/const-param.stderr [new file with mode: 0644]

index d0eefb2e4d14f0e4ecbab35bd3760cf93475dd64..b817470b4c30f9e0cdfa8a4c55b7170ee6fb460b 100644 (file)
@@ -87,6 +87,9 @@ fn report_inlining_errors(&self, pat_span: Span) {
                 PatternError::AssocConstInPattern(span) => {
                     self.span_e0158(span, "associated consts cannot be referenced in patterns")
                 }
+                PatternError::ConstParamInPattern(span) => {
+                    self.span_e0158(span, "const parameters cannot be referenced in patterns")
+                }
                 PatternError::FloatBug => {
                     // FIXME(#31407) this is only necessary because float parsing is buggy
                     ::rustc::mir::interpret::struct_error(
index f58216fbb4e76bfdf4c722500d3e0197ded7ab6b..6786c3562930840d5411ce940d0e90393ec96439 100644 (file)
@@ -31,6 +31,7 @@
 #[derive(Clone, Debug)]
 crate enum PatternError {
     AssocConstInPattern(Span),
+    ConstParamInPattern(Span),
     StaticInPattern(Span),
     FloatBug,
     NonConstPath(Span),
@@ -727,7 +728,11 @@ fn lower_variant_or_leaf(
             | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
 
             _ => {
-                self.errors.push(PatternError::NonConstPath(span));
+                let pattern_error = match res {
+                    Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
+                    _ => PatternError::NonConstPath(span),
+                };
+                self.errors.push(pattern_error);
                 PatKind::Wild
             }
         };
index 97f3ad72ee37ff822feffae5a97c69921c3e7e58..30ba48f797007efcc981fa7a7bd3e47674b43ee8 100644 (file)
@@ -1517,9 +1517,17 @@ fn try_resolve_as_non_binding(
         ident: Ident,
         has_sub: bool,
     ) -> Option<Res> {
-        let binding =
-            self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?;
-        let res = binding.res();
+        let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?;
+        let (res, binding) = match ls_binding {
+            LexicalScopeBinding::Item(binding) if binding.is_ambiguity() => {
+                // For ambiguous bindings we don't know all their definitions and cannot check
+                // whether they can be shadowed by fresh bindings or not, so force an error.
+                self.r.record_use(ident, ValueNS, binding, false);
+                return None;
+            }
+            LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
+            LexicalScopeBinding::Res(res) => (res, None),
+        };
 
         // An immutable (no `mut`) by-value (no `ref`) binding pattern without
         // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
@@ -1527,11 +1535,15 @@ fn try_resolve_as_non_binding(
         let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);
 
         match res {
-            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::Def(DefKind::Const, _)
+            Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
+            | Res::Def(DefKind::Const, _)
+            | Res::Def(DefKind::ConstParam, _)
                 if is_syntactic_ambiguity =>
             {
                 // Disambiguate in favor of a unit struct/variant or constant pattern.
-                self.r.record_use(ident, ValueNS, binding, false);
+                if let Some(binding) = binding {
+                    self.r.record_use(ident, ValueNS, binding, false);
+                }
                 Some(res)
             }
             Res::Def(DefKind::Ctor(..), _)
@@ -1547,23 +1559,20 @@ fn try_resolve_as_non_binding(
                     ResolutionError::BindingShadowsSomethingUnacceptable(
                         pat_src.descr(),
                         ident.name,
-                        binding,
+                        binding.expect("no binding for a ctor or static"),
                     ),
                 );
                 None
             }
-            Res::Def(DefKind::Fn, _) | Res::Err => {
+            Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => {
                 // These entities are explicitly allowed to be shadowed by fresh bindings.
                 None
             }
-            res => {
-                span_bug!(
-                    ident.span,
-                    "unexpected resolution for an \
-                                        identifier in pattern: {:?}",
-                    res
-                );
-            }
+            _ => span_bug!(
+                ident.span,
+                "unexpected resolution for an identifier in pattern: {:?}",
+                res
+            ),
         }
     }
 
index 948b86225f38b7a6f735c54ec32c7069327a3a60..37a800a0b7bdb20a8c7a0c9db557777b4c26f5e9 100644 (file)
@@ -323,13 +323,6 @@ enum LexicalScopeBinding<'a> {
 }
 
 impl<'a> LexicalScopeBinding<'a> {
-    fn item(self) -> Option<&'a NameBinding<'a>> {
-        match self {
-            LexicalScopeBinding::Item(binding) => Some(binding),
-            _ => None,
-        }
-    }
-
     fn res(self) -> Res {
         match self {
             LexicalScopeBinding::Item(binding) => binding.res(),
index 60132dde9caec09c02aa24d44d022c2dafaf4ae3..fabf3dd1153b7db9c84390cf09a6c2008f43a18b 100644 (file)
@@ -716,7 +716,8 @@ fn check_pat_path(
             Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
             | Res::SelfCtor(..)
             | Res::Def(DefKind::Const, _)
-            | Res::Def(DefKind::AssocConst, _) => {} // OK
+            | Res::Def(DefKind::AssocConst, _)
+            | Res::Def(DefKind::ConstParam, _) => {} // OK
             _ => bug!("unexpected pattern resolution: {:?}", res),
         }
 
diff --git a/src/test/ui/binding/ambiguity-item.rs b/src/test/ui/binding/ambiguity-item.rs
new file mode 100644 (file)
index 0000000..10613cc
--- /dev/null
@@ -0,0 +1,18 @@
+// Identifier pattern referring to an ambiguity item is an error (issue #46079).
+
+mod m {
+    pub fn f() {}
+}
+use m::*;
+
+mod n {
+    pub fn f() {}
+}
+use n::*; // OK, no conflict with `use m::*;`
+
+fn main() {
+    let v = f; //~ ERROR `f` is ambiguous
+    match v {
+        f => {} //~ ERROR `f` is ambiguous
+    }
+}
diff --git a/src/test/ui/binding/ambiguity-item.stderr b/src/test/ui/binding/ambiguity-item.stderr
new file mode 100644 (file)
index 0000000..615193c
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/ambiguity-item.rs:14:13
+   |
+LL |     let v = f;
+   |             ^ ambiguous name
+   |
+note: `f` could refer to the function imported here
+  --> $DIR/ambiguity-item.rs:6:5
+   |
+LL | use m::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+note: `f` could also refer to the function imported here
+  --> $DIR/ambiguity-item.rs:11:5
+   |
+LL | use n::*; // OK, no conflict with `use m::*;`
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+
+error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/ambiguity-item.rs:16:9
+   |
+LL |         f => {}
+   |         ^ ambiguous name
+   |
+note: `f` could refer to the function imported here
+  --> $DIR/ambiguity-item.rs:6:5
+   |
+LL | use m::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+note: `f` could also refer to the function imported here
+  --> $DIR/ambiguity-item.rs:11:5
+   |
+LL | use n::*; // OK, no conflict with `use m::*;`
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/binding/const-param.rs b/src/test/ui/binding/const-param.rs
new file mode 100644 (file)
index 0000000..3c7f4d0
--- /dev/null
@@ -0,0 +1,12 @@
+// Identifier pattern referring to a const generic parameter is an error (issue #68853).
+
+#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+
+fn check<const N: usize>() {
+    match 1 {
+        N => {} //~ ERROR const parameters cannot be referenced in patterns
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/binding/const-param.stderr b/src/test/ui/binding/const-param.stderr
new file mode 100644 (file)
index 0000000..25b1c75
--- /dev/null
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0158]: const parameters cannot be referenced in patterns
+  --> $DIR/const-param.rs:7:9
+   |
+LL |         N => {}
+   |         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0158`.