From f903c97959593e4612403989148f6116ab57611f Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sat, 11 Jun 2016 18:47:47 +0300
Subject: [PATCH] Merge PatKind::QPath into PatKind::Path in AST

---
 src/librustc/hir/lowering.rs                      |  4 ++--
 src/librustc_resolve/lib.rs                       | 13 ++-----------
 src/librustc_save_analysis/lib.rs                 |  3 +--
 src/libsyntax/ast.rs                              | 15 +++++----------
 src/libsyntax/ext/build.rs                        |  2 +-
 src/libsyntax/fold.rs                             | 11 +++++------
 src/libsyntax/parse/parser.rs                     |  7 +------
 src/libsyntax/print/pprust.rs                     |  4 ++--
 src/libsyntax/visit.rs                            |  9 ++++-----
 .../method-resolvable-path-in-pattern.rs          |  2 +-
 10 files changed, 24 insertions(+), 46 deletions(-)

diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 393045bf93e..4473f2ed06c 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -866,10 +866,10 @@ impl<'a> LoweringContext<'a> {
                                               pats.iter().map(|x| self.lower_pat(x)).collect(),
                                               ddpos)
                 }
-                PatKind::Path(ref pth) => {
+                PatKind::Path(None, ref pth) => {
                     hir::PatKind::Path(self.lower_path(pth))
                 }
-                PatKind::QPath(ref qself, ref pth) => {
+                PatKind::Path(Some(ref qself), ref pth) => {
                     let qself = hir::QSelf {
                         ty: self.lower_ty(&qself.ty),
                         position: qself.position,
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index e82b4e2fcd7..ba886509c5a 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2332,8 +2332,8 @@ impl<'a> Resolver<'a> {
                     }, "variant or struct");
                 }
 
-                PatKind::Path(ref path) => {
-                    self.resolve_pattern_path(pat.id, None, path, ValueNS, |def| {
+                PatKind::Path(ref qself, ref path) => {
+                    self.resolve_pattern_path(pat.id, qself.as_ref(), path, ValueNS, |def| {
                         match def {
                             Def::Struct(..) | Def::Variant(..) |
                             Def::Const(..) | Def::AssociatedConst(..) | Def::Err => true,
@@ -2342,15 +2342,6 @@ impl<'a> Resolver<'a> {
                     }, "variant, struct or constant");
                 }
 
-                PatKind::QPath(ref qself, ref path) => {
-                    self.resolve_pattern_path(pat.id, Some(qself), path, ValueNS, |def| {
-                        match def {
-                            Def::AssociatedConst(..) | Def::Err => true,
-                            _ => false,
-                        }
-                    }, "associated constant");
-                }
-
                 PatKind::Struct(ref path, _, _) => {
                     self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| {
                         match def {
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 33351338160..c45aecd07e1 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -699,8 +699,7 @@ impl<'v> Visitor<'v> for PathCollector {
                                            ast::Mutability::Mutable, recorder::TypeRef));
             }
             PatKind::TupleStruct(ref path, _, _) |
-            PatKind::Path(ref path) |
-            PatKind::QPath(_, ref path) => {
+            PatKind::Path(_, ref path) => {
                 self.collected_paths.push((p.id, path.clone(),
                                            ast::Mutability::Mutable, recorder::VarRef));
             }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 8537fcc221c..28af65a87a3 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -579,7 +579,6 @@ impl Pat {
             PatKind::Range(_, _) |
             PatKind::Ident(_, _, _) |
             PatKind::Path(..) |
-            PatKind::QPath(_, _) |
             PatKind::Mac(_) => {
                 true
             }
@@ -627,15 +626,11 @@ pub enum PatKind {
     /// 0 <= position <= subpats.len()
     TupleStruct(Path, Vec<P<Pat>>, Option<usize>),
 
-    /// A path pattern.
-    /// Such pattern can be resolved to a unit struct/variant or a constant.
-    Path(Path),
-
-    /// An associated const named using the qualified path `<T>::CONST` or
-    /// `<T as Trait>::CONST`. Associated consts from inherent impls can be
-    /// referred to as simply `T::CONST`, in which case they will end up as
-    /// PatKind::Path, and the resolver will have to sort that out.
-    QPath(QSelf, Path),
+    /// A possibly qualified path pattern.
+    /// Unquailfied path patterns `A::B::C` can legally refer to variants, structs, constants
+    /// or associated constants. Quailfied path patterns `<A>::B::C`/`<A as Trait>::B::C` can
+    /// only legally refer to associated constants.
+    Path(Option<QSelf>, Path),
 
     /// A tuple pattern `(a, b)`.
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 3a1cdae9bfb..1d27cf5b0a1 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -830,7 +830,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
     fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
         let pat = if subpats.is_empty() {
-            PatKind::Path(path)
+            PatKind::Path(None, path)
         } else {
             PatKind::TupleStruct(path, subpats, None)
         };
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index edf418e3332..5979db15d88 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1088,12 +1088,11 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
                 PatKind::TupleStruct(folder.fold_path(pth),
                         pats.move_map(|x| folder.fold_pat(x)), ddpos)
             }
-            PatKind::Path(pth) => {
-                PatKind::Path(folder.fold_path(pth))
-            }
-            PatKind::QPath(qself, pth) => {
-                let qself = QSelf {ty: folder.fold_ty(qself.ty), .. qself};
-                PatKind::QPath(qself, folder.fold_path(pth))
+            PatKind::Path(opt_qself, pth) => {
+                let opt_qself = opt_qself.map(|qself| {
+                    QSelf { ty: folder.fold_ty(qself.ty), position: qself.position }
+                });
+                PatKind::Path(opt_qself, folder.fold_path(pth))
             }
             PatKind::Struct(pth, fields, etc) => {
                 let pth = folder.fold_path(pth);
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 341b076e7cf..6704543e880 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3715,12 +3715,7 @@ impl<'a> Parser<'a> {
                         pat = PatKind::TupleStruct(path, fields, ddpos)
                       }
                       _ => {
-                        pat = match qself {
-                            // Parse qualified path
-                            Some(qself) => PatKind::QPath(qself, path),
-                            // Parse nullary enum
-                            None => PatKind::Path(path)
-                        };
+                        pat = PatKind::Path(qself, path);
                       }
                     }
                 }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index a2ee5bf6090..eece942e471 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -2483,10 +2483,10 @@ impl<'a> State<'a> {
                 }
                 try!(self.pclose());
             }
-            PatKind::Path(ref path) => {
+            PatKind::Path(None, ref path) => {
                 try!(self.print_path(path, true, 0));
             }
-            PatKind::QPath(ref qself, ref path) => {
+            PatKind::Path(Some(ref qself), ref path) => {
                 try!(self.print_qpath(path, qself, false));
             }
             PatKind::Struct(ref path, ref fields, etc) => {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 07a6317706b..f58304caaab 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -409,11 +409,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
             visitor.visit_path(path, pattern.id);
             walk_list!(visitor, visit_pat, children);
         }
-        PatKind::Path(ref path) => {
-            visitor.visit_path(path, pattern.id);
-        }
-        PatKind::QPath(ref qself, ref path) => {
-            visitor.visit_ty(&qself.ty);
+        PatKind::Path(ref opt_qself, ref path) => {
+            if let Some(ref qself) = *opt_qself {
+                visitor.visit_ty(&qself.ty);
+            }
             visitor.visit_path(path, pattern.id)
         }
         PatKind::Struct(ref path, ref fields, _) => {
diff --git a/src/test/compile-fail/method-resolvable-path-in-pattern.rs b/src/test/compile-fail/method-resolvable-path-in-pattern.rs
index 1cba64ccf2c..3ae792f9c0f 100644
--- a/src/test/compile-fail/method-resolvable-path-in-pattern.rs
+++ b/src/test/compile-fail/method-resolvable-path-in-pattern.rs
@@ -19,6 +19,6 @@ impl MyTrait for Foo {}
 fn main() {
     match 0u32 {
         <Foo as MyTrait>::trait_bar => {}
-        //~^ ERROR expected associated constant, found method `trait_bar`
+        //~^ ERROR expected variant, struct or constant, found method `trait_bar`
     }
 }