]> git.lizzy.rs Git - rust.git/commitdiff
resolve: extract `try_resolve_as_non_binding`.
authorMazdak Farrokhzad <twingoow@gmail.com>
Wed, 28 Aug 2019 08:10:10 +0000 (10:10 +0200)
committerMazdak Farrokhzad <twingoow@gmail.com>
Thu, 5 Sep 2019 06:33:09 +0000 (08:33 +0200)
src/librustc_resolve/late.rs
src/librustc_resolve/lib.rs

index 82971094ae7b71e847d7622ed7ce7609b850c222..20a12a4ae938ea4c3525f5add6717a0c4e3aab06 100644 (file)
@@ -9,7 +9,7 @@
 use RibKind::*;
 
 use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
-use crate::{Module, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult};
+use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
 use log::debug;
@@ -1327,78 +1327,37 @@ fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxHashMap<Ident, Res
         &mut self.ribs[ns].last_mut().unwrap().bindings
     }
 
-    fn resolve_pattern(&mut self,
-                       pat: &Pat,
-                       pat_src: PatternSource,
-                       // Maps idents to the node ID for the
-                       // outermost pattern that binds them.
-                       bindings: &mut FxHashMap<Ident, NodeId>) {
+    fn resolve_pattern(
+        &mut self,
+        pat: &Pat,
+        pat_src: PatternSource,
+        // Maps idents to the node ID for the outermost pattern that binds them.
+        bindings: &mut FxHashMap<Ident, NodeId>,
+    ) {
         // Visit all direct subpatterns of this pattern.
         let outer_pat_id = pat.id;
         pat.walk(&mut |pat| {
             debug!("resolve_pattern pat={:?} node={:?}", pat, pat.node);
             match pat.node {
-                PatKind::Ident(bmode, ident, ref opt_pat) => {
-                    // First try to resolve the identifier as some existing
-                    // entity, then fall back to a fresh binding.
-                    let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS,
-                                                                      None, pat.span)
-                                      .and_then(LexicalScopeBinding::item);
-                    let res = binding.map(NameBinding::res).and_then(|res| {
-                        let is_syntactic_ambiguity = opt_pat.is_none() &&
-                            bmode == BindingMode::ByValue(Mutability::Immutable);
-                        match res {
-                            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
-                            Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => {
-                                // Disambiguate in favor of a unit struct/variant
-                                // or constant pattern.
-                                self.r.record_use(ident, ValueNS, binding.unwrap(), false);
-                                Some(res)
-                            }
-                            Res::Def(DefKind::Ctor(..), _)
-                            | Res::Def(DefKind::Const, _)
-                            | Res::Def(DefKind::Static, _) => {
-                                // 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.
-                                self.r.report_error(
-                                    ident.span,
-                                    ResolutionError::BindingShadowsSomethingUnacceptable(
-                                        pat_src.descr(), ident.name, binding.unwrap())
-                                );
-                                None
-                            }
-                            Res::Def(DefKind::Fn, _) | 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);
-                            }
-                        }
-                    }).unwrap_or_else(|| {
-                        self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
-                    });
-
+                PatKind::Ident(bmode, ident, ref sub) => {
+                    // First try to resolve the identifier as some existing entity,
+                    // then fall back to a fresh binding.
+                    let has_sub = sub.is_some();
+                    let res = self.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
+                        .unwrap_or_else(|| {
+                            self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
+                        });
                     self.r.record_partial_res(pat.id, PartialRes::new(res));
                 }
-
                 PatKind::TupleStruct(ref path, ..) => {
                     self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct);
                 }
-
                 PatKind::Path(ref qself, ref path) => {
                     self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
                 }
-
                 PatKind::Struct(ref path, ..) => {
                     self.smart_resolve_path(pat.id, None, path, PathSource::Struct);
                 }
-
                 _ => {}
             }
             true
@@ -1407,6 +1366,58 @@ fn resolve_pattern(&mut self,
         visit::walk_pat(self, pat);
     }
 
+    fn try_resolve_as_non_binding(
+        &mut self,
+        pat_src: PatternSource,
+        pat: &Pat,
+        bm: BindingMode,
+        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();
+
+        // An immutable (no `mut`) by-value (no `ref`) binding pattern without
+        // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
+        // also be interpreted as a path to e.g. a constant, variant, etc.
+        let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Immutable);
+
+        match res {
+            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
+            Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => {
+                // Disambiguate in favor of a unit struct/variant or constant pattern.
+                self.r.record_use(ident, ValueNS, binding, false);
+                Some(res)
+            }
+            Res::Def(DefKind::Ctor(..), _)
+            | Res::Def(DefKind::Const, _)
+            | Res::Def(DefKind::Static, _) => {
+                // 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.
+                self.r.report_error(
+                    ident.span,
+                    ResolutionError::BindingShadowsSomethingUnacceptable(
+                        pat_src.descr(),
+                        ident.name,
+                        binding,
+                    ),
+                );
+                None
+            }
+            Res::Def(DefKind::Fn, _) | 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);
+            }
+        }
+    }
+
     // High-level and context dependent path resolution routine.
     // Resolves the path and records the resolution into definition map.
     // If resolution fails tries several techniques to find likely
index 875ae449d94e0f0e9d5f47d208b88cf71b208e64..9b92bb7698aaa506e5e6a805b4bd4a83c445904d 100644 (file)
@@ -9,6 +9,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(inner_deref)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
 #![feature(mem_take)]