diff --git a/src/libregex_macros/lib.rs b/src/libregex_macros/lib.rs
index 07539a11113..8610621d30a 100644
--- a/src/libregex_macros/lib.rs
+++ b/src/libregex_macros/lib.rs
@@ -594,7 +594,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
             pats: vec!(box(GC) ast::Pat{
                 id: ast::DUMMY_NODE_ID,
                 span: self.sp,
-                node: ast::PatWild,
+                node: ast::PatWild(ast::PatWildSingle),
             }),
             guard: None,
             body: body,
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 9cd46067c10..dba873a72b6 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -112,7 +112,7 @@ impl<'a> CFGBuilder<'a> {
             ast::PatEnum(_, None) |
             ast::PatLit(..) |
             ast::PatRange(..) |
-            ast::PatWild | ast::PatWildMulti => {
+            ast::PatWild(_) => {
                 self.add_node(pat.id, [pred])
             }
 
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 21b9a3f9053..d8a88b66310 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -344,7 +344,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
                 let fields = ty::lookup_struct_fields(cx.tcx, vid);
                 let field_pats: Vec<FieldPat> = fields.move_iter()
                     .zip(pats.iter())
-                    .filter(|&(_, pat)| pat.node != PatWild)
+                    .filter(|&(_, pat)| pat.node != PatWild(PatWildSingle))
                     .map(|(field, pat)| FieldPat {
                         ident: Ident::new(field.name),
                         pat: pat.clone()
@@ -372,7 +372,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
                     },
                     _ => unreachable!()
                 },
-                ty::ty_str => PatWild,
+                ty::ty_str => PatWild(PatWildSingle),
 
                 _ => {
                     assert_eq!(pats.len(), 1);
@@ -394,7 +394,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
         _ => {
             match *ctor {
                 ConstantValue(ref v) => PatLit(const_val_to_expr(v)),
-                _ => PatWild
+                _ => PatWild(PatWildSingle),
             }
         }
     };
@@ -599,7 +599,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
             },
         PatBox(_) | PatTup(_) | PatRegion(..) =>
             vec!(Single),
-        PatWild | PatWildMulti =>
+        PatWild(_) =>
             vec!(),
         PatMac(_) =>
             cx.tcx.sess.bug("unexpanded macro")
@@ -666,10 +666,7 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
         id: pat_id, node: ref node, span: pat_span
     } = &(*raw_pat(r[col]));
     let head: Option<Vec<Gc<Pat>>> = match node {
-        &PatWild =>
-            Some(Vec::from_elem(arity, wild())),
-
-        &PatWildMulti =>
+        &PatWild(_) =>
             Some(Vec::from_elem(arity, wild())),
 
         &PatIdent(_, _, _) => {
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index e2e3081eb2d..83f4fbaed67 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -706,7 +706,7 @@ fn check_sized(tcx: &ty::ctxt, ty: ty::t, name: String, sp: Span) {
 // Check that any variables in a pattern have types with statically known size.
 fn check_pat(cx: &mut Context, pat: &Pat) {
     let var_name = match pat.node {
-        PatWild => Some("_".to_string()),
+        PatWild(PatWildSingle) => Some("_".to_string()),
         PatIdent(_, ref path1, _) => Some(ident_to_string(&path1.node).to_string()),
         _ => None
     };
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index a690d588214..52a32241faf 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1026,7 +1026,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
         op(self, cmt.clone(), pat);
 
         match pat.node {
-          ast::PatWild | ast::PatWildMulti => {
+          ast::PatWild(_) => {
             // _
           }
 
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index faaffc75257..2d9e4ee45be 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -68,7 +68,7 @@ pub fn pat_is_binding(dm: &resolve::DefMap, pat: &Pat) -> bool {
 pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatIdent(..) => pat_is_binding(dm, pat),
-        PatWild | PatWildMulti => true,
+        PatWild(_) => true,
         _ => false
     }
 }
@@ -116,7 +116,7 @@ pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Ident> {
 }
 
 pub fn wild() -> Gc<Pat> {
-    box (GC) Pat { id: 0, node: PatWild, span: DUMMY_SP }
+    box (GC) Pat { id: 0, node: PatWild(PatWildSingle), span: DUMMY_SP }
 }
 
 pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 0b181d2cf36..5334205aa52 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1392,7 +1392,7 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
     // to the default arm.
     let has_default = arms.last().map_or(false, |arm| {
         arm.pats.len() == 1
-        && arm.pats.last().unwrap().node == ast::PatWild
+        && arm.pats.last().unwrap().node == ast::PatWild(ast::PatWildSingle)
     });
 
     compile_submatch(bcx, matches.as_slice(), [discr_datum.val], &chk, has_default);
@@ -1762,7 +1762,7 @@ fn bind_irrefutable_pat<'a>(
         ast::PatMac(..) => {
             bcx.sess().span_bug(pat.span, "unexpanded macro");
         }
-        ast::PatWild | ast::PatWildMulti | ast::PatLit(_) | ast::PatRange(_, _) => ()
+        ast::PatWild(_) | ast::PatLit(_) | ast::PatRange(_, _) => ()
     }
     return bcx;
 }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index f1e84b8da81..e35f60d0c3c 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1032,7 +1032,7 @@ pub fn store_ty(cx: &Block, v: ValueRef, dst: ValueRef, t: ty::t) {
 
 pub fn ignore_lhs(_bcx: &Block, local: &ast::Local) -> bool {
     match local.pat.node {
-        ast::PatWild => true, _ => false
+        ast::PatWild(ast::PatWildSingle) => true, _ => false
     }
 }
 
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 6fe3ee5d29b..6b396411529 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -3429,7 +3429,7 @@ fn populate_scope_map(cx: &CrateContext,
                 }
             }
 
-            ast::PatWild | ast::PatWildMulti => {
+            ast::PatWild(_) => {
                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
             }
 
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 531dced550a..76823155155 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -412,7 +412,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
     let tcx = pcx.fcx.ccx.tcx;
 
     match pat.node {
-      ast::PatWild | ast::PatWildMulti => {
+      ast::PatWild(_) => {
         fcx.write_ty(pat.id, expected);
       }
       ast::PatLit(ref lt) => {
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 10eeefda18e..9a48045b369 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -1257,7 +1257,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
     for i in decl.inputs.iter() {
         match (*i).pat.node {
             ast::PatIdent(_, _, _) => (),
-            ast::PatWild => (),
+            ast::PatWild(ast::PatWildSingle) => (),
             _ => {
                 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
                           "patterns aren't allowed in foreign function declarations");
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7eecae84d1d..e9d5fb70281 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1959,8 +1959,8 @@ fn name_from_pat(p: &ast::Pat) -> String {
     debug!("Trying to get a name from pattern: {:?}", p);
 
     match p.node {
-        PatWild => "_".to_string(),
-        PatWildMulti => "..".to_string(),
+        PatWild(PatWildSingle) => "_".to_string(),
+        PatWild(PatWildMulti) => "..".to_string(),
         PatIdent(_, ref p, _) => token::get_ident(p.node).get().to_string(),
         PatEnum(ref p, _) => path_to_string(p),
         PatStruct(ref name, ref fields, etc) => {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 19882fecaa9..2d39a47a85e 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -324,9 +324,19 @@ pub enum BindingMode {
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
-pub enum Pat_ {
-    PatWild,
+pub enum PatWildKind {
+    /// Represents the wildcard pattern `_`
+    PatWildSingle,
+
+    /// Represents the wildcard pattern `..`
     PatWildMulti,
+}
+
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum Pat_ {
+    /// Represents a wildcard pattern (either `_` or `..`)
+    PatWild(PatWildKind),
+
     /// A PatIdent may either be a new bound variable,
     /// or a nullary enum (in which case the third field
     /// is None).
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 99726da69c9..e58187fe30d 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -636,7 +636,7 @@ pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool {
             after.iter().all(|p| walk_pat(&**p, |p| it(p)))
         }
         PatMac(_) => fail!("attempted to analyze unexpanded pattern"),
-        PatWild | PatWildMulti | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
+        PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
         PatEnum(_, _) => {
             true
         }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index d00406e07b7..01d3920a254 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -229,7 +229,7 @@ impl DummyResult {
     pub fn raw_pat(sp: Span) -> Gc<ast::Pat> {
         box(GC) ast::Pat {
             id: ast::DUMMY_NODE_ID,
-            node: ast::PatWild,
+            node: ast::PatWild(ast::PatWildSingle),
             span: sp,
         }
     }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 5acb84cf852..d500600e25d 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -763,7 +763,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         box(GC) ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
     }
     fn pat_wild(&self, span: Span) -> Gc<ast::Pat> {
-        self.pat(span, ast::PatWild)
+        self.pat(span, ast::PatWild(ast::PatWildSingle))
     }
     fn pat_lit(&self, span: Span, expr: Gc<ast::Expr>) -> Gc<ast::Pat> {
         self.pat(span, ast::PatLit(expr))
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index f3e6cf77e79..2f82702ece4 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -969,8 +969,7 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> SmallVector<Gc
 pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {
     let id = folder.new_id(p.id);
     let node = match p.node {
-        PatWild => PatWild,
-        PatWildMulti => PatWildMulti,
+        PatWild(k) => PatWild(k),
         PatIdent(binding_mode, ref pth1, ref sub) => {
             PatIdent(binding_mode,
                      Spanned{span: folder.new_span(pth1.span),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 18b1d60d4e9..c9fba355c4d 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -39,7 +39,7 @@ use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal}
 use ast::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability};
 use ast::{NamedField, UnNeg, NoReturn, UnNot, P, Pat, PatEnum};
 use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
-use ast::{PatTup, PatBox, PatWild, PatWildMulti};
+use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
 use ast::{BiRem, Required};
 use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
 use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
@@ -2822,7 +2822,7 @@ impl<'a> Parser<'a> {
                 if self.token == token::COMMA || self.token == token::RBRACKET {
                     slice = Some(box(GC) ast::Pat {
                         id: ast::DUMMY_NODE_ID,
-                        node: PatWildMulti,
+                        node: PatWild(PatWildMulti),
                         span: self.span,
                     })
                 } else {
@@ -2920,7 +2920,7 @@ impl<'a> Parser<'a> {
             // parse _
           token::UNDERSCORE => {
             self.bump();
-            pat = PatWild;
+            pat = PatWild(PatWildSingle);
             hi = self.last_span.hi;
             return box(GC) ast::Pat {
                 id: ast::DUMMY_NODE_ID,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 095dca66164..ab0269f807a 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1732,8 +1732,8 @@ impl<'a> State<'a> {
         /* Pat isn't normalized, but the beauty of it
          is that it doesn't matter */
         match pat.node {
-            ast::PatWild => try!(word(&mut self.s, "_")),
-            ast::PatWildMulti => try!(word(&mut self.s, "..")),
+            ast::PatWild(ast::PatWildSingle) => try!(word(&mut self.s, "_")),
+            ast::PatWild(ast::PatWildMulti) => try!(word(&mut self.s, "..")),
             ast::PatIdent(binding_mode, ref path1, sub) => {
                 match binding_mode {
                     ast::BindByRef(mutbl) => {
@@ -1822,7 +1822,7 @@ impl<'a> State<'a> {
                 for p in slice.iter() {
                     if !before.is_empty() { try!(self.word_space(",")); }
                     match **p {
-                        ast::Pat { node: ast::PatWildMulti, .. } => {
+                        ast::Pat { node: ast::PatWild(ast::PatWildMulti), .. } => {
                             // this case is handled by print_pat
                         }
                         _ => try!(word(&mut self.s, "..")),
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 371fae53b41..733c4bfc2b0 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -481,7 +481,7 @@ pub fn walk_pat<E: Clone, V: Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E)
             visitor.visit_expr(&**lower_bound, env.clone());
             visitor.visit_expr(&**upper_bound, env)
         }
-        PatWild | PatWildMulti => (),
+        PatWild(_) => (),
         PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
             for prepattern in prepattern.iter() {
                 visitor.visit_pat(&**prepattern, env.clone())