]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/check_match.rs
Add part of new error codes in librustc
[rust.git] / src / librustc / middle / check_match.rs
index f17cb673a5f2d670b6989a343d170cb1a91c68e9..bf2d2fee20e5b5ee7f1c2fc5a776ccdaacabf321 100644 (file)
@@ -17,6 +17,7 @@
 use middle::const_eval::{const_expr_to_pat, lookup_const_by_id};
 use middle::const_eval::EvalHint::ExprTypeChecked;
 use middle::def::*;
+use middle::def_id::{DefId};
 use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init};
 use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
 use middle::expr_use_visitor::WriteAndRead;
 use std::fmt;
 use std::iter::{range_inclusive, FromIterator, IntoIterator, repeat};
 use std::slice;
-use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
+
+use rustc_front::hir;
+use rustc_front::hir::Pat;
+use rustc_front::visit::{self, Visitor, FnKind};
+use rustc_front::util as front_util;
+
+use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
 use syntax::ast_util;
 use syntax::codemap::{Span, Spanned, DUMMY_SP};
-use syntax::fold::{Folder, noop_fold_pat};
-use syntax::print::pprust::pat_to_string;
+use rustc_front::fold::{Folder, noop_fold_pat};
+use rustc_front::print::pprust::pat_to_string;
 use syntax::ptr::P;
-use syntax::visit::{self, Visitor, FnKind};
 use util::nodemap::FnvHashMap;
 
 pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
     id: DUMMY_NODE_ID,
-    node: ast::PatWild(ast::PatWildSingle),
+    node: hir::PatWild(hir::PatWildSingle),
     span: DUMMY_SP
 };
 
@@ -111,7 +117,7 @@ pub enum Constructor {
     /// e.g. struct patterns and fixed-length arrays.
     Single,
     /// Enum variants.
-    Variant(ast::DefId),
+    Variant(DefId),
     /// Literal values.
     ConstantValue(ConstVal),
     /// Ranges of literal values (2..5).
@@ -136,14 +142,14 @@ enum WitnessPreference {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
-    fn visit_expr(&mut self, ex: &ast::Expr) {
+    fn visit_expr(&mut self, ex: &hir::Expr) {
         check_expr(self, ex);
     }
-    fn visit_local(&mut self, l: &ast::Local) {
+    fn visit_local(&mut self, l: &hir::Local) {
         check_local(self, l);
     }
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, n: NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, s: Span, n: NodeId) {
         check_fn(self, fk, fd, b, s, n);
     }
 }
@@ -156,10 +162,10 @@ pub fn check_crate(tcx: &ty::ctxt) {
     tcx.sess.abort_if_errors();
 }
 
-fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
+fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
     visit::walk_expr(cx, ex);
     match ex.node {
-        ast::ExprMatch(ref scrut, ref arms, source) => {
+        hir::ExprMatch(ref scrut, ref arms, source) => {
             for arm in arms {
                 // First, check legality of move bindings.
                 check_legality_of_move_bindings(cx,
@@ -179,7 +185,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
                 (arm.pats.iter().map(|pat| {
                     static_inliner.fold_pat((*pat).clone())
                 }).collect(), arm.guard.as_ref().map(|e| &**e))
-            }).collect::<Vec<(Vec<P<Pat>>, Option<&ast::Expr>)>>();
+            }).collect::<Vec<(Vec<P<Pat>>, Option<&hir::Expr>)>>();
 
             // Bail out early if inlining failed.
             if static_inliner.failed {
@@ -212,6 +218,9 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
                     span_err!(cx.tcx.sess, ex.span, E0002,
                               "non-exhaustive patterns: type {} is non-empty",
                               pat_ty);
+                    span_help!(cx.tcx.sess, ex.span,
+                        "Please ensure that all possible cases are being handled; \
+                         possibly adding wildcards or more match arms.");
                 }
                 // If the type *is* empty, it's vacuously exhaustive
                 return;
@@ -230,16 +239,16 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
 }
 
 fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) {
-    ast_util::walk_pat(pat, |p| {
+    front_util::walk_pat(pat, |p| {
         match p.node {
-            ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
+            hir::PatIdent(hir::BindByValue(hir::MutImmutable), ident, None) => {
                 let pat_ty = cx.tcx.pat_ty(p);
-                if let ty::TyEnum(def_id, _) = pat_ty.sty {
+                if let ty::TyEnum(edef, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
                     if let Some(DefLocal(_)) = def {
-                        if cx.tcx.enum_variants(def_id).iter().any(|variant|
+                        if edef.variants.iter().any(|variant|
                             variant.name == ident.node.name
-                                && variant.args.is_empty()
+                                && variant.kind() == VariantKind::Unit
                         ) {
                             span_warn!(cx.tcx.sess, p.span, E0170,
                                 "pattern binding `{}` is named the same as one \
@@ -261,8 +270,8 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
 
 // Check that we do not match against a static NaN (#6804)
 fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
-    ast_util::walk_pat(pat, |p| {
-        if let ast::PatLit(ref expr) = p.node {
+    front_util::walk_pat(pat, |p| {
+        if let hir::PatLit(ref expr) = p.node {
             match eval_const_expr_partial(cx.tcx, &**expr, ExprTypeChecked) {
                 Ok(ConstVal::Float(f)) if f.is_nan() => {
                     span_warn!(cx.tcx.sess, p.span, E0003,
@@ -273,9 +282,9 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
 
                 Err(err) => {
                     let subspan = p.span.lo <= err.span.lo && err.span.hi <= p.span.hi;
-                    cx.tcx.sess.span_err(err.span,
-                                         &format!("constant evaluation error: {}",
-                                                  err.description()));
+                    span_err!(cx.tcx.sess, err.span, E0471,
+                              "constant evaluation error: {}",
+                              err.description());
                     if !subspan {
                         cx.tcx.sess.span_note(p.span,
                                               "in pattern here")
@@ -289,8 +298,8 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
 
 // Check for unreachable patterns
 fn check_arms(cx: &MatchCheckCtxt,
-              arms: &[(Vec<P<Pat>>, Option<&ast::Expr>)],
-              source: ast::MatchSource) {
+              arms: &[(Vec<P<Pat>>, Option<&hir::Expr>)],
+              source: hir::MatchSource) {
     let mut seen = Matrix(vec![]);
     let mut printed_if_let_err = false;
     for &(ref pats, guard) in arms {
@@ -300,7 +309,7 @@ fn check_arms(cx: &MatchCheckCtxt,
             match is_useful(cx, &seen, &v[..], LeaveOutWitness) {
                 NotUseful => {
                     match source {
-                        ast::MatchSource::IfLetDesugar { .. } => {
+                        hir::MatchSource::IfLetDesugar { .. } => {
                             if printed_if_let_err {
                                 // we already printed an irrefutable if-let pattern error.
                                 // We don't want two, that's just confusing.
@@ -314,7 +323,7 @@ fn check_arms(cx: &MatchCheckCtxt,
                             }
                         },
 
-                        ast::MatchSource::WhileLetDesugar => {
+                        hir::MatchSource::WhileLetDesugar => {
                             // find the first arm pattern so we can use its span
                             let &(ref first_arm_pats, _) = &arms[0];
                             let first_pat = &first_arm_pats[0];
@@ -322,7 +331,7 @@ fn check_arms(cx: &MatchCheckCtxt,
                             span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern");
                         },
 
-                        ast::MatchSource::ForLoopDesugar => {
+                        hir::MatchSource::ForLoopDesugar => {
                             // this is a bug, because on `match iter.next()` we cover
                             // `Some(<head>)` and `None`. It's impossible to have an unreachable
                             // pattern
@@ -330,7 +339,7 @@ fn check_arms(cx: &MatchCheckCtxt,
                             cx.tcx.sess.span_bug(pat.span, "unreachable for-loop pattern")
                         },
 
-                        ast::MatchSource::Normal => {
+                        hir::MatchSource::Normal => {
                             span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern")
                         },
                     }
@@ -349,12 +358,12 @@ fn check_arms(cx: &MatchCheckCtxt,
 
 fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
     match p.node {
-        ast::PatIdent(_, _, Some(ref s)) => raw_pat(&**s),
+        hir::PatIdent(_, _, Some(ref s)) => raw_pat(&**s),
         _ => p
     }
 }
 
-fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast::MatchSource) {
+fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir::MatchSource) {
     match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
         UsefulWithWitness(pats) => {
             let witness = match &pats[..] {
@@ -363,10 +372,10 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast:
                 _ => unreachable!()
             };
             match source {
-                ast::MatchSource::ForLoopDesugar => {
+                hir::MatchSource::ForLoopDesugar => {
                     // `witness` has the form `Some(<head>)`, peel off the `Some`
                     let witness = match witness.node {
-                        ast::PatEnum(_, Some(ref pats)) => match &pats[..] {
+                        hir::PatEnum(_, Some(ref pats)) => match &pats[..] {
                             [ref pat] => &**pat,
                             _ => unreachable!(),
                         },
@@ -393,14 +402,14 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast:
     }
 }
 
-fn const_val_to_expr(value: &ConstVal) -> P<ast::Expr> {
+fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
     let node = match value {
-        &ConstVal::Bool(b) => ast::LitBool(b),
+        &ConstVal::Bool(b) => hir::LitBool(b),
         _ => unreachable!()
     };
-    P(ast::Expr {
+    P(hir::Expr {
         id: 0,
-        node: ast::ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
+        node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
         span: DUMMY_SP
     })
 }
@@ -439,7 +448,7 @@ fn visit_id(&mut self, node_id: NodeId) {
 impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
     fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
         return match pat.node {
-            ast::PatIdent(..) | ast::PatEnum(..) | ast::PatQPath(..) => {
+            hir::PatIdent(..) | hir::PatEnum(..) | hir::PatQPath(..) => {
                 let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
                 match def {
                     Some(DefAssociatedConst(did)) |
@@ -468,8 +477,8 @@ fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
             _ => noop_fold_pat(pat, self)
         };
 
-        fn record_renamings(const_expr: &ast::Expr,
-                            substituted_pat: &ast::Pat,
+        fn record_renamings(const_expr: &hir::Expr,
+                            substituted_pat: &hir::Pat,
                             renaming_map: &mut FnvHashMap<(NodeId, Span), NodeId>) {
             let mut renaming_recorder = RenamingRecorder {
                 substituted_node_id: substituted_pat.id,
@@ -477,7 +486,7 @@ fn record_renamings(const_expr: &ast::Expr,
                 renaming_map: renaming_map,
             };
 
-            let mut id_visitor = ast_util::IdVisitor {
+            let mut id_visitor = front_util::IdVisitor {
                 operation: &mut renaming_recorder,
                 pass_through_items: true,
                 visited_outermost: false,
@@ -501,37 +510,31 @@ fn record_renamings(const_expr: &ast::Expr,
 ///
 /// left_ty: struct X { a: (bool, &'static str), b: usize}
 /// pats: [(false, "foo"), 42]  => X { a: (false, "foo"), b: 42 }
-fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
-                     pats: Vec<&Pat>, left_ty: Ty) -> P<Pat> {
+fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
+                              pats: Vec<&Pat>, left_ty: Ty<'tcx>) -> P<Pat> {
     let pats_len = pats.len();
     let mut pats = pats.into_iter().map(|p| P((*p).clone()));
     let pat = match left_ty.sty {
-        ty::TyTuple(_) => ast::PatTup(pats.collect()),
-
-        ty::TyEnum(cid, _) | ty::TyStruct(cid, _)  => {
-            let (vid, is_structure) = match ctor {
-                &Variant(vid) =>
-                    (vid, cx.tcx.enum_variant_with_id(cid, vid).arg_names.is_some()),
-                _ =>
-                    (cid, !cx.tcx.is_tuple_struct(cid))
-            };
-            if is_structure {
-                let fields = cx.tcx.lookup_struct_fields(vid);
-                let field_pats: Vec<_> = fields.into_iter()
+        ty::TyTuple(_) => hir::PatTup(pats.collect()),
+
+        ty::TyEnum(adt, _) | ty::TyStruct(adt, _)  => {
+            let v = adt.variant_of_ctor(ctor);
+            if let VariantKind::Dict = v.kind() {
+                let field_pats: Vec<_> = v.fields.iter()
                     .zip(pats)
-                    .filter(|&(_, ref pat)| pat.node != ast::PatWild(ast::PatWildSingle))
+                    .filter(|&(_, ref pat)| pat.node != hir::PatWild(hir::PatWildSingle))
                     .map(|(field, pat)| Spanned {
                         span: DUMMY_SP,
-                        node: ast::FieldPat {
+                        node: hir::FieldPat {
                             ident: ast::Ident::new(field.name),
                             pat: pat,
                             is_shorthand: false,
                         }
                     }).collect();
                 let has_more_fields = field_pats.len() < pats_len;
-                ast::PatStruct(def_to_path(cx.tcx, vid), field_pats, has_more_fields)
+                hir::PatStruct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
             } else {
-                ast::PatEnum(def_to_path(cx.tcx, vid), Some(pats.collect()))
+                hir::PatEnum(def_to_path(cx.tcx, v.did), Some(pats.collect()))
             }
         }
 
@@ -540,46 +543,57 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
                ty::TyArray(_, n) => match ctor {
                     &Single => {
                         assert_eq!(pats_len, n);
-                        ast::PatVec(pats.collect(), None, vec!())
+                        hir::PatVec(pats.collect(), None, vec!())
                     },
                     _ => unreachable!()
                 },
                 ty::TySlice(_) => match ctor {
                     &Slice(n) => {
                         assert_eq!(pats_len, n);
-                        ast::PatVec(pats.collect(), None, vec!())
+                        hir::PatVec(pats.collect(), None, vec!())
                     },
                     _ => unreachable!()
                 },
-                ty::TyStr => ast::PatWild(ast::PatWildSingle),
+                ty::TyStr => hir::PatWild(hir::PatWildSingle),
 
                 _ => {
                     assert_eq!(pats_len, 1);
-                    ast::PatRegion(pats.nth(0).unwrap(), mutbl)
+                    hir::PatRegion(pats.nth(0).unwrap(), mutbl)
                 }
             }
         }
 
         ty::TyArray(_, len) => {
             assert_eq!(pats_len, len);
-            ast::PatVec(pats.collect(), None, vec![])
+            hir::PatVec(pats.collect(), None, vec![])
         }
 
         _ => {
             match *ctor {
-                ConstantValue(ref v) => ast::PatLit(const_val_to_expr(v)),
-                _ => ast::PatWild(ast::PatWildSingle),
+                ConstantValue(ref v) => hir::PatLit(const_val_to_expr(v)),
+                _ => hir::PatWild(hir::PatWildSingle),
             }
         }
     };
 
-    P(ast::Pat {
+    P(hir::Pat {
         id: 0,
         node: pat,
         span: DUMMY_SP
     })
 }
 
+impl<'tcx, 'container> ty::AdtDefData<'tcx, 'container> {
+    fn variant_of_ctor(&self,
+                       ctor: &Constructor)
+                       -> &VariantDefData<'tcx, 'container> {
+        match ctor {
+            &Variant(vid) => self.variant_with_id(vid),
+            _ => self.struct_variant()
+        }
+    }
+}
+
 fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
                        left_ty: Ty, max_slice_length: usize) -> Option<Constructor> {
     let used_constructors: Vec<Constructor> = rows.iter()
@@ -594,7 +608,7 @@ fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
 /// values of type `left_ty`. For vectors, this would normally be an infinite set
 /// but is instead bounded by the maximum fixed length of slice patterns in
 /// the column of patterns being analyzed.
-fn all_constructors(cx: &MatchCheckCtxt, left_ty: Ty,
+fn all_constructors(_cx: &MatchCheckCtxt, left_ty: Ty,
                     max_slice_length: usize) -> Vec<Constructor> {
     match left_ty.sty {
         ty::TyBool =>
@@ -603,17 +617,11 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: Ty,
         ty::TyRef(_, ty::TypeAndMut { ty, .. }) => match ty.sty {
             ty::TySlice(_) =>
                 range_inclusive(0, max_slice_length).map(|length| Slice(length)).collect(),
-            _ => vec!(Single)
+            _ => vec![Single]
         },
 
-        ty::TyEnum(eid, _) =>
-            cx.tcx.enum_variants(eid)
-                .iter()
-                .map(|va| Variant(va.id))
-                .collect(),
-
-        _ =>
-            vec!(Single)
+        ty::TyEnum(def, _) => def.variants.iter().map(|v| Variant(v.did)).collect(),
+        _ => vec![Single]
     }
 }
 
@@ -658,15 +666,15 @@ fn is_useful(cx: &MatchCheckCtxt,
         let left_ty = cx.tcx.pat_ty(&*real_pat);
 
         match real_pat.node {
-            ast::PatIdent(ast::BindByRef(..), _, _) => {
-                left_ty.builtin_deref(false).unwrap().ty
+            hir::PatIdent(hir::BindByRef(..), _, _) => {
+                left_ty.builtin_deref(false, NoPreference).unwrap().ty
             }
             _ => left_ty,
         }
     };
 
     let max_slice_length = rows.iter().filter_map(|row| match row[0].node {
-        ast::PatVec(ref before, _, ref after) => Some(before.len() + after.len()),
+        hir::PatVec(ref before, _, ref after) => Some(before.len() + after.len()),
         _ => None
     }).max().map_or(0, |v| v + 1);
 
@@ -747,7 +755,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                     left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
     let pat = raw_pat(p);
     match pat.node {
-        ast::PatIdent(..) =>
+        hir::PatIdent(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
@@ -756,7 +764,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                 Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!()
             },
-        ast::PatEnum(..) =>
+        hir::PatEnum(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
@@ -764,10 +772,10 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                 Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
-        ast::PatQPath(..) =>
+        hir::PatQPath(..) =>
             cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                             been rewritten"),
-        ast::PatStruct(..) =>
+        hir::PatStruct(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
@@ -775,11 +783,11 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                 Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
-        ast::PatLit(ref expr) =>
+        hir::PatLit(ref expr) =>
             vec!(ConstantValue(eval_const_expr(cx.tcx, &**expr))),
-        ast::PatRange(ref lo, ref hi) =>
+        hir::PatRange(ref lo, ref hi) =>
             vec!(ConstantRange(eval_const_expr(cx.tcx, &**lo), eval_const_expr(cx.tcx, &**hi))),
-        ast::PatVec(ref before, ref slice, ref after) =>
+        hir::PatVec(ref before, ref slice, ref after) =>
             match left_ty.sty {
                 ty::TyArray(_, _) => vec!(Single),
                 _                      => if slice.is_some() {
@@ -790,12 +798,10 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                     vec!(Slice(before.len() + after.len()))
                 }
             },
-        ast::PatBox(_) | ast::PatTup(_) | ast::PatRegion(..) =>
+        hir::PatBox(_) | hir::PatTup(_) | hir::PatRegion(..) =>
             vec!(Single),
-        ast::PatWild(_) =>
+        hir::PatWild(_) =>
             vec!(),
-        ast::PatMac(_) =>
-            cx.tcx.sess.bug("unexpanded macro")
     }
 }
 
@@ -804,7 +810,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
 ///
 /// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3.
 /// A struct pattern's arity is the number of fields it contains, etc.
-pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize {
+pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize {
     match ty.sty {
         ty::TyTuple(ref fs) => fs.len(),
         ty::TyBox(_) => 1,
@@ -817,13 +823,9 @@ pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usi
             ty::TyStr => 0,
             _ => 1
         },
-        ty::TyEnum(eid, _) => {
-            match *ctor {
-                Variant(id) => cx.tcx.enum_variant_with_id(eid, id).args.len(),
-                _ => unreachable!()
-            }
+        ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
+            adt.variant_of_ctor(ctor).fields.len()
         }
-        ty::TyStruct(cid, _) => cx.tcx.lookup_struct_fields(cid).len(),
         ty::TyArray(_, n) => n,
         _ => 0
     }
@@ -861,10 +863,10 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         id: pat_id, ref node, span: pat_span
     } = raw_pat(r[col]);
     let head: Option<Vec<&Pat>> = match *node {
-        ast::PatWild(_) =>
+        hir::PatWild(_) =>
             Some(vec![DUMMY_WILD_PAT; arity]),
 
-        ast::PatIdent(_, _, _) => {
+        hir::PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
             match opt_def {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
@@ -879,7 +881,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatEnum(_, ref args) => {
+        hir::PatEnum(_, ref args) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
                 DefConst(..) | DefAssociatedConst(..) =>
@@ -896,54 +898,35 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatQPath(_, _) => {
+        hir::PatQPath(_, _) => {
             cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                             been rewritten")
         }
 
-        ast::PatStruct(_, ref pattern_fields, _) => {
-            // Is this a struct or an enum variant?
+        hir::PatStruct(_, ref pattern_fields, _) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
-            let class_id = match def {
-                DefConst(..) | DefAssociatedConst(..) =>
-                    cx.tcx.sess.span_bug(pat_span, "const pattern should've \
-                                                    been rewritten"),
-                DefVariant(_, variant_id, _) => if *constructor == Variant(variant_id) {
-                    Some(variant_id)
-                } else {
-                    None
-                },
-                _ => {
-                    // Assume this is a struct.
-                    match cx.tcx.node_id_to_type(pat_id).ty_to_def_id() {
-                        None => {
-                            cx.tcx.sess.span_bug(pat_span,
-                                                 "struct pattern wasn't of a \
-                                                  type with a def ID?!")
-                        }
-                        Some(def_id) => Some(def_id),
-                    }
-                }
-            };
-            class_id.map(|variant_id| {
-                let struct_fields = cx.tcx.lookup_struct_fields(variant_id);
-                let args = struct_fields.iter().map(|sf| {
+            let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
+            let variant = adt.variant_of_ctor(constructor);
+            let def_variant = adt.variant_of_def(def);
+            if variant.did == def_variant.did {
+                Some(variant.fields.iter().map(|sf| {
                     match pattern_fields.iter().find(|f| f.node.ident.name == sf.name) {
                         Some(ref f) => &*f.node.pat,
                         _ => DUMMY_WILD_PAT
                     }
-                }).collect();
-                args
-            })
+                }).collect())
+            } else {
+                None
+            }
         }
 
-        ast::PatTup(ref args) =>
+        hir::PatTup(ref args) =>
             Some(args.iter().map(|p| &**p).collect()),
 
-        ast::PatBox(ref inner) | ast::PatRegion(ref inner, _) =>
+        hir::PatBox(ref inner) | hir::PatRegion(ref inner, _) =>
             Some(vec![&**inner]),
 
-        ast::PatLit(ref expr) => {
+        hir::PatLit(ref expr) => {
             let expr_value = eval_const_expr(cx.tcx, &**expr);
             match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
                 Some(true) => Some(vec![]),
@@ -955,7 +938,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatRange(ref from, ref to) => {
+        hir::PatRange(ref from, ref to) => {
             let from_value = eval_const_expr(cx.tcx, &**from);
             let to_value = eval_const_expr(cx.tcx, &**to);
             match range_covered_by_constructor(constructor, &from_value, &to_value) {
@@ -968,7 +951,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatVec(ref before, ref slice, ref after) => {
+        hir::PatVec(ref before, ref slice, ref after) => {
             match *constructor {
                 // Fixed-length vectors.
                 Single => {
@@ -999,11 +982,6 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
                 _ => None
             }
         }
-
-        ast::PatMac(_) => {
-            span_err!(cx.tcx.sess, pat_span, E0300, "unexpanded macro");
-            None
-        }
     };
     head.map(|mut head| {
         head.push_all(&r[..col]);
@@ -1012,7 +990,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
     })
 }
 
-fn check_local(cx: &mut MatchCheckCtxt, loc: &ast::Local) {
+fn check_local(cx: &mut MatchCheckCtxt, loc: &hir::Local) {
     visit::walk_local(cx, loc);
 
     let pat = StaticInliner::new(cx.tcx, None).fold_pat(loc.pat.clone());
@@ -1025,12 +1003,12 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &ast::Local) {
 
 fn check_fn(cx: &mut MatchCheckCtxt,
             kind: FnKind,
-            decl: &ast::FnDecl,
-            body: &ast::Block,
+            decl: &hir::FnDecl,
+            body: &hir::Block,
             sp: Span,
             fn_id: NodeId) {
     match kind {
-        visit::FkFnBlock => {}
+        FnKind::Closure => {}
         _ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id),
     }
 
@@ -1083,10 +1061,10 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
     for pat in pats {
         pat_bindings(def_map, &**pat, |bm, _, span, _path| {
             match bm {
-                ast::BindByRef(_) => {
+                hir::BindByRef(_) => {
                     by_ref_span = Some(span);
                 }
-                ast::BindByValue(_) => {
+                hir::BindByValue(_) => {
                 }
             }
         })
@@ -1108,10 +1086,10 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
     };
 
     for pat in pats {
-        ast_util::walk_pat(&**pat, |p| {
+        front_util::walk_pat(&**pat, |p| {
             if pat_is_binding(def_map, &*p) {
                 match p.node {
-                    ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
+                    hir::PatIdent(hir::BindByValue(_), _, ref sub) => {
                         let pat_ty = tcx.node_id_to_type(p.id);
                         //FIXME: (@jroesch) this code should be floated up as well
                         let infcx = infer::new_infer_ctxt(cx.tcx,
@@ -1122,7 +1100,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                             check_move(p, sub.as_ref().map(|p| &**p));
                         }
                     }
-                    ast::PatIdent(ast::BindByRef(_), _, _) => {
+                    hir::PatIdent(hir::BindByRef(_), _, _) => {
                     }
                     _ => {
                         cx.tcx.sess.span_bug(
@@ -1142,7 +1120,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
 /// Ensures that a pattern guard doesn't borrow by mutable reference or
 /// assign.
 fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>,
-                                         guard: &ast::Expr) {
+                                         guard: &hir::Expr) {
     let mut checker = MutationChecker {
         cx: cx,
     };
@@ -1211,7 +1189,7 @@ fn visit_pat(&mut self, pat: &Pat) {
         }
 
         match pat.node {
-            ast::PatIdent(_, _, Some(_)) => {
+            hir::PatIdent(_, _, Some(_)) => {
                 let bindings_were_allowed = self.bindings_allowed;
                 self.bindings_allowed = false;
                 visit::walk_pat(self, pat);