]> git.lizzy.rs Git - rust.git/commitdiff
move hair::cx::pattern to const_eval
authorAriel Ben-Yehuda <ariel.byd@gmail.com>
Sat, 24 Sep 2016 14:45:24 +0000 (17:45 +0300)
committerAriel Ben-Yehuda <ariel.byd@gmail.com>
Wed, 26 Oct 2016 19:41:17 +0000 (22:41 +0300)
src/Cargo.lock
src/librustc_const_eval/Cargo.toml
src/librustc_const_eval/lib.rs
src/librustc_const_eval/pattern.rs [new file with mode: 0644]
src/librustc_mir/build/mod.rs
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/cx/pattern.rs [deleted file]
src/librustc_mir/hair/mod.rs

index a32ba02457edf2008aa6a1b46c7d18623521f736..d12b95d8b22e3470d7e34aabe33ac77aae2b7168 100644 (file)
@@ -335,6 +335,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
+ "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
index 8967672548b101b3b35a01f04b8207ab8b5d1198..ec4d2fdf967d6deffdd6521514c0434b2a6817ee 100644 (file)
@@ -14,6 +14,7 @@ serialize = { path = "../libserialize" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
+rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
 graphviz = { path = "../libgraphviz" }
index 7b40269ba56ad271ac459e55c88c1d111fbdd762..9a97df966960046d205bc30084dcbe61267b1407 100644 (file)
@@ -36,6 +36,7 @@
 #[macro_use] extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_const_math;
+extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate graphviz;
 extern crate syntax_pos;
@@ -47,6 +48,7 @@
 
 mod eval;
 pub mod check_match;
+pub mod pattern;
 
 pub use eval::*;
 
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
new file mode 100644 (file)
index 0000000..b32c78b
--- /dev/null
@@ -0,0 +1,377 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use eval;
+
+use rustc::middle::const_val::ConstVal;
+use rustc::mir::repr::{Field, Literal, BorrowKind, Mutability};
+use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
+use rustc::hir::{self, PatKind};
+use rustc::hir::def::Def;
+use rustc::hir::pat_util::EnumerateAndAdjustIterator;
+
+use rustc_data_structures::indexed_vec::Idx;
+
+use syntax::ast;
+use syntax::ptr::P;
+use syntax_pos::Span;
+
+#[derive(Copy, Clone, Debug)]
+pub enum BindingMode<'tcx> {
+    ByValue,
+    ByRef(&'tcx Region, BorrowKind),
+}
+
+#[derive(Clone, Debug)]
+pub struct FieldPattern<'tcx> {
+    pub field: Field,
+    pub pattern: Pattern<'tcx>,
+}
+
+#[derive(Clone, Debug)]
+pub struct Pattern<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub span: Span,
+    pub kind: Box<PatternKind<'tcx>>,
+}
+
+#[derive(Clone, Debug)]
+pub enum PatternKind<'tcx> {
+    Wild,
+
+    /// x, ref x, x @ P, etc
+    Binding {
+        mutability: Mutability,
+        name: ast::Name,
+        mode: BindingMode<'tcx>,
+        var: ast::NodeId,
+        ty: Ty<'tcx>,
+        subpattern: Option<Pattern<'tcx>>,
+    },
+
+    /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
+    Variant {
+        adt_def: AdtDef<'tcx>,
+        variant_index: usize,
+        subpatterns: Vec<FieldPattern<'tcx>>,
+    },
+
+    /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
+    Leaf {
+        subpatterns: Vec<FieldPattern<'tcx>>,
+    },
+
+    /// box P, &P, &mut P, etc
+    Deref {
+        subpattern: Pattern<'tcx>,
+    },
+
+    Constant {
+        value: ConstVal,
+    },
+
+    Range {
+        lo: Literal<'tcx>,
+        hi: Literal<'tcx>,
+    },
+
+    /// matches against a slice, checking the length and extracting elements
+    Slice {
+        prefix: Vec<Pattern<'tcx>>,
+        slice: Option<Pattern<'tcx>>,
+        suffix: Vec<Pattern<'tcx>>,
+    },
+
+    /// fixed match against an array, irrefutable
+    Array {
+        prefix: Vec<Pattern<'tcx>>,
+        slice: Option<Pattern<'tcx>>,
+        suffix: Vec<Pattern<'tcx>>,
+    },
+}
+
+impl<'a, 'gcx, 'tcx> Pattern<'tcx> {
+    pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>, pat: &hir::Pat) -> Self {
+        let mut ty = tcx.node_id_to_type(pat.id);
+
+        let kind = match pat.node {
+            PatKind::Wild => PatternKind::Wild,
+
+            PatKind::Lit(ref value) => {
+                let value = eval::eval_const_expr(tcx.global_tcx(), value);
+                PatternKind::Constant { value: value }
+            }
+
+            PatKind::Range(ref lo, ref hi) => {
+                let lo = eval::eval_const_expr(tcx.global_tcx(), lo);
+                let lo = Literal::Value { value: lo };
+                let hi = eval::eval_const_expr(tcx.global_tcx(), hi);
+                let hi = Literal::Value { value: hi };
+                PatternKind::Range { lo: lo, hi: hi }
+            },
+
+            PatKind::Path(..) => {
+                match tcx.expect_def(pat.id) {
+                    Def::Const(def_id) | Def::AssociatedConst(def_id) => {
+                        let tcx = tcx.global_tcx();
+                        let substs = Some(tcx.node_id_item_substs(pat.id).substs);
+                        match eval::lookup_const_by_id(tcx, def_id, substs) {
+                            Some((const_expr, _const_ty)) => {
+                                match eval::const_expr_to_pat(tcx,
+                                                              const_expr,
+                                                              pat.id,
+                                                              pat.span) {
+                                    Ok(pat) =>
+                                        return Pattern::from_hir(tcx, &pat),
+                                    Err(_) =>
+                                        span_bug!(
+                                            pat.span, "illegal constant"),
+                                }
+                            }
+                            None => {
+                                span_bug!(
+                                    pat.span,
+                                    "cannot eval constant: {:?}",
+                                    def_id)
+                            }
+                        }
+                    }
+                    _ => {
+                        PatternKind::from_variant_or_leaf(tcx, pat, vec![])
+                    }
+                }
+            }
+
+            PatKind::Ref(ref subpattern, _) |
+            PatKind::Box(ref subpattern) => {
+                PatternKind::Deref { subpattern: Self::from_hir(tcx, subpattern) }
+            }
+
+            PatKind::Slice(ref prefix, ref slice, ref suffix) => {
+                let ty = tcx.node_id_to_type(pat.id);
+                match ty.sty {
+                    ty::TyRef(_, mt) =>
+                        PatternKind::Deref {
+                            subpattern: Pattern {
+                                ty: mt.ty,
+                                span: pat.span,
+                                kind: Box::new(PatternKind::from_slice_or_array(
+                                    tcx, pat.span, mt.ty, prefix, slice, suffix))
+                            },
+                        },
+
+                    ty::TySlice(..) |
+                    ty::TyArray(..) =>
+                        PatternKind::from_slice_or_array(
+                            tcx, pat.span, ty, prefix, slice, suffix),
+
+                    ref sty =>
+                        span_bug!(
+                            pat.span,
+                            "unexpanded type for vector pattern: {:?}",
+                            sty),
+                }
+            }
+
+            PatKind::Tuple(ref subpatterns, ddpos) => {
+                match tcx.node_id_to_type(pat.id).sty {
+                    ty::TyTuple(ref tys) => {
+                        let subpatterns =
+                            subpatterns.iter()
+                                       .enumerate_and_adjust(tys.len(), ddpos)
+                                       .map(|(i, subpattern)| FieldPattern {
+                                            field: Field::new(i),
+                                            pattern: Self::from_hir(tcx, subpattern),
+                                       })
+                                       .collect();
+
+                        PatternKind::Leaf { subpatterns: subpatterns }
+                    }
+
+                    ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
+                }
+            }
+
+            PatKind::Binding(bm, ref ident, ref sub) => {
+                let def_id = tcx.expect_def(pat.id).def_id();
+                let id = tcx.map.as_local_node_id(def_id).unwrap();
+                let var_ty = tcx.node_id_to_type(pat.id);
+                let region = match var_ty.sty {
+                    ty::TyRef(r, _) => Some(r),
+                    _ => None,
+                };
+                let (mutability, mode) = match bm {
+                    hir::BindByValue(hir::MutMutable) =>
+                        (Mutability::Mut, BindingMode::ByValue),
+                    hir::BindByValue(hir::MutImmutable) =>
+                        (Mutability::Not, BindingMode::ByValue),
+                    hir::BindByRef(hir::MutMutable) =>
+                        (Mutability::Not, BindingMode::ByRef(region.unwrap(), BorrowKind::Mut)),
+                    hir::BindByRef(hir::MutImmutable) =>
+                        (Mutability::Not, BindingMode::ByRef(region.unwrap(), BorrowKind::Shared)),
+                };
+
+                // A ref x pattern is the same node used for x, and as such it has
+                // x's type, which is &T, where we want T (the type being matched).
+                if let hir::BindByRef(_) = bm {
+                    if let ty::TyRef(_, mt) = ty.sty {
+                        ty = mt.ty;
+                    } else {
+                        bug!("`ref {}` has wrong type {}", ident.node, ty);
+                    }
+                }
+
+                PatternKind::Binding {
+                    mutability: mutability,
+                    mode: mode,
+                    name: ident.node,
+                    var: id,
+                    ty: var_ty,
+                    subpattern: Self::from_opt_pattern(tcx, sub),
+                }
+            }
+
+            PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
+                let pat_ty = tcx.node_id_to_type(pat.id);
+                let adt_def = match pat_ty.sty {
+                    ty::TyAdt(adt_def, _) => adt_def,
+                    _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
+                };
+                let variant_def = adt_def.variant_of_def(tcx.expect_def(pat.id));
+
+                let subpatterns =
+                        subpatterns.iter()
+                                   .enumerate_and_adjust(variant_def.fields.len(), ddpos)
+                                   .map(|(i, field)| FieldPattern {
+                                       field: Field::new(i),
+                                       pattern: Self::from_hir(tcx, field),
+                                   })
+                                   .collect();
+                PatternKind::from_variant_or_leaf(tcx, pat, subpatterns)
+            }
+
+            PatKind::Struct(_, ref fields, _) => {
+                let pat_ty = tcx.node_id_to_type(pat.id);
+                let adt_def = match pat_ty.sty {
+                    ty::TyAdt(adt_def, _) => adt_def,
+                    _ => {
+                        span_bug!(
+                            pat.span,
+                            "struct pattern not applied to an ADT");
+                    }
+                };
+                let variant_def = adt_def.variant_of_def(tcx.expect_def(pat.id));
+
+                let subpatterns =
+                    fields.iter()
+                          .map(|field| {
+                              let index = variant_def.index_of_field_named(field.node.name);
+                              let index = index.unwrap_or_else(|| {
+                                  span_bug!(
+                                      pat.span,
+                                      "no field with name {:?}",
+                                      field.node.name);
+                              });
+                              FieldPattern {
+                                  field: Field::new(index),
+                                  pattern: Self::from_hir(tcx, &field.node.pat),
+                              }
+                          })
+                          .collect();
+
+                PatternKind::from_variant_or_leaf(tcx, pat, subpatterns)
+            }
+        };
+
+        Pattern {
+            span: pat.span,
+            ty: ty,
+            kind: Box::new(kind),
+        }
+    }
+
+    fn from_patterns(tcx: TyCtxt<'a, 'gcx, 'tcx>, pats: &[P<hir::Pat>]) -> Vec<Self> {
+        pats.iter().map(|p| Self::from_hir(tcx, p)).collect()
+    }
+
+    fn from_opt_pattern(tcx: TyCtxt<'a, 'gcx, 'tcx>, pat: &Option<P<hir::Pat>>) -> Option<Self>
+    {
+        pat.as_ref().map(|p| Self::from_hir(tcx, p))
+    }
+}
+
+impl<'a, 'gcx, 'tcx> PatternKind<'tcx> {
+    fn from_slice_or_array(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        span: Span,
+        ty: Ty<'tcx>,
+        prefix: &[P<hir::Pat>],
+        slice: &Option<P<hir::Pat>>,
+        suffix: &[P<hir::Pat>])
+        -> Self
+    {
+        match ty.sty {
+            ty::TySlice(..) => {
+                // matching a slice or fixed-length array
+                PatternKind::Slice {
+                    prefix: Pattern::from_patterns(tcx, prefix),
+                    slice: Pattern::from_opt_pattern(tcx, slice),
+                    suffix: Pattern::from_patterns(tcx, suffix),
+                }
+            }
+
+            ty::TyArray(_, len) => {
+                // fixed-length array
+                assert!(len >= prefix.len() + suffix.len());
+                PatternKind::Array {
+                    prefix: Pattern::from_patterns(tcx, prefix),
+                    slice: Pattern::from_opt_pattern(tcx, slice),
+                    suffix: Pattern::from_patterns(tcx, suffix),
+                }
+            }
+
+            _ => {
+                span_bug!(span, "unexpanded macro or bad constant etc");
+            }
+        }
+    }
+
+    fn from_variant_or_leaf(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        pat: &hir::Pat,
+        subpatterns: Vec<FieldPattern<'tcx>>)
+        -> Self
+    {
+        match tcx.expect_def(pat.id) {
+            Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
+                let enum_id = tcx.parent_def_id(variant_id).unwrap();
+                let adt_def = tcx.lookup_adt_def(enum_id);
+                if adt_def.variants.len() > 1 {
+                    PatternKind::Variant {
+                        adt_def: adt_def,
+                        variant_index: adt_def.variant_index_with_id(variant_id),
+                        subpatterns: subpatterns,
+                    }
+                } else {
+                    PatternKind::Leaf { subpatterns: subpatterns }
+                }
+            }
+
+            Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
+            Def::TyAlias(..) | Def::AssociatedTy(..) => {
+                PatternKind::Leaf { subpatterns: subpatterns }
+            }
+
+            def => {
+                span_bug!(pat.span, "inappropriate def for pattern: {:?}", def);
+            }
+        }
+    }
+}
index 7b3306de7538bf1b1506b941e37ce56a795a25d3..a7249677e01031a7c9895e02cf72720f2e9fad96 100644 (file)
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 use hair::cx::Cx;
+use hair::Pattern;
+
 use rustc::middle::region::{CodeExtent, CodeExtentData, ROOT_CODE_EXTENT};
 use rustc::ty::{self, Ty};
 use rustc::mir::repr::*;
@@ -339,7 +341,7 @@ fn args_and_body(&mut self,
             let lvalue = Lvalue::Local(Local::new(index + 1));
 
             if let Some(pattern) = pattern {
-                let pattern = self.hir.irrefutable_pat(pattern);
+                let pattern = Pattern::from_hir(self.hir.tcx(), pattern);
                 scope = self.declare_bindings(scope, ast_block.span, &pattern);
                 unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
             }
index 52d54f2cc85724db2203964e0dfa6800115c320f..ec1136368c1354317d18670e0b500be4f4dfa452 100644 (file)
@@ -57,7 +57,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     let remainder_extent =
                         cx.tcx.region_maps.lookup_code_extent(remainder_extent);
 
-                    let pattern = cx.irrefutable_pat(&local.pat);
+                    let pattern = Pattern::from_hir(cx.tcx, &local.pat);
                     result.push(StmtRef::Mirror(Box::new(Stmt {
                         span: stmt.span,
                         kind: StmtKind::Let {
index f23c9d3caf096de2f9bb6f0fb6c6dbacf0fce28d..45c49a4627ff6cac481d647c50c812f0e8c89250 100644 (file)
@@ -657,7 +657,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
 fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                arm: &'tcx hir::Arm) -> Arm<'tcx> {
     Arm {
-        patterns: arm.pats.iter().map(|p| cx.refutable_pat(p)).collect(),
+        patterns: arm.pats.iter().map(|p| Pattern::from_hir(cx.tcx, p)).collect(),
         guard: arm.guard.to_ref(),
         body: arm.body.to_ref(),
     }
index 9fe3addea4127ac83593422c24b58015b995f3f2..f87e0acaa4ca1c689b97015ade729d23e1ff0583 100644 (file)
@@ -196,5 +196,4 @@ pub fn check_overflow(&self) -> bool {
 
 mod block;
 mod expr;
-mod pattern;
 mod to_ref;
diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs
deleted file mode 100644 (file)
index 84f4154..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use hair::*;
-use hair::cx::Cx;
-use rustc_data_structures::indexed_vec::Idx;
-use rustc_const_eval as const_eval;
-use rustc::hir::def::Def;
-use rustc::hir::pat_util::EnumerateAndAdjustIterator;
-use rustc::ty::{self, Ty};
-use rustc::mir::repr::*;
-use rustc::hir::{self, PatKind};
-use syntax::ptr::P;
-use syntax_pos::Span;
-
-/// When there are multiple patterns in a single arm, each one has its
-/// own node-ids for the bindings.  References to the variables always
-/// use the node-ids from the first pattern in the arm, so we just
-/// remap the ids for all subsequent bindings to the first one.
-///
-/// Example:
-/// ```
-/// match foo {
-///    Test1(flavor /* def 1 */) |
-///    Test2(flavor /* def 2 */) if flavor /* ref 1 */.is_tasty() => { ... }
-///    _ => { ... }
-/// }
-/// ```
-struct PatCx<'patcx, 'cx: 'patcx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
-    cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>,
-}
-
-impl<'cx, 'gcx, 'tcx> Cx<'cx, 'gcx, 'tcx> {
-    pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
-        PatCx::new(self).to_pattern(pat)
-    }
-
-    pub fn refutable_pat(&mut self,
-                         pat: &hir::Pat)
-                         -> Pattern<'tcx> {
-        PatCx::new(self).to_pattern(pat)
-    }
-}
-
-impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
-    fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>)
-               -> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
-        PatCx {
-            cx: cx,
-        }
-    }
-
-    fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
-        let mut ty = self.cx.tcx.node_id_to_type(pat.id);
-
-        let kind = match pat.node {
-            PatKind::Wild => PatternKind::Wild,
-
-            PatKind::Lit(ref value) => {
-                let value = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), value);
-                PatternKind::Constant { value: value }
-            }
-
-            PatKind::Range(ref lo, ref hi) => {
-                let lo = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), lo);
-                let lo = Literal::Value { value: lo };
-                let hi = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), hi);
-                let hi = Literal::Value { value: hi };
-                PatternKind::Range { lo: lo, hi: hi }
-            },
-
-            PatKind::Path(..) => {
-                match self.cx.tcx.expect_def(pat.id) {
-                    Def::Const(def_id) | Def::AssociatedConst(def_id) => {
-                        let tcx = self.cx.tcx.global_tcx();
-                        let substs = Some(self.cx.tcx.node_id_item_substs(pat.id).substs);
-                        match const_eval::lookup_const_by_id(tcx, def_id, substs) {
-                            Some((const_expr, _const_ty)) => {
-                                match const_eval::const_expr_to_pat(tcx,
-                                                                    const_expr,
-                                                                    pat.id,
-                                                                    pat.span) {
-                                    Ok(pat) =>
-                                        return self.to_pattern(&pat),
-                                    Err(_) =>
-                                        span_bug!(
-                                            pat.span, "illegal constant"),
-                                }
-                            }
-                            None => {
-                                span_bug!(
-                                    pat.span,
-                                    "cannot eval constant: {:?}",
-                                    def_id)
-                            }
-                        }
-                    }
-                    _ => {
-                        self.variant_or_leaf(pat, vec![])
-                    }
-                }
-            }
-
-            PatKind::Ref(ref subpattern, _) |
-            PatKind::Box(ref subpattern) => {
-                PatternKind::Deref { subpattern: self.to_pattern(subpattern) }
-            }
-
-            PatKind::Slice(ref prefix, ref slice, ref suffix) => {
-                let ty = self.cx.tcx.node_id_to_type(pat.id);
-                match ty.sty {
-                    ty::TyRef(_, mt) =>
-                        PatternKind::Deref {
-                            subpattern: Pattern {
-                                ty: mt.ty,
-                                span: pat.span,
-                                kind: Box::new(self.slice_or_array_pattern(pat.span, mt.ty, prefix,
-                                                                           slice, suffix)),
-                            },
-                        },
-
-                    ty::TySlice(..) |
-                    ty::TyArray(..) =>
-                        self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
-
-                    ref sty =>
-                        span_bug!(
-                            pat.span,
-                            "unexpanded type for vector pattern: {:?}",
-                            sty),
-                }
-            }
-
-            PatKind::Tuple(ref subpatterns, ddpos) => {
-                match self.cx.tcx.node_id_to_type(pat.id).sty {
-                    ty::TyTuple(ref tys) => {
-                        let subpatterns =
-                            subpatterns.iter()
-                                       .enumerate_and_adjust(tys.len(), ddpos)
-                                       .map(|(i, subpattern)| FieldPattern {
-                                            field: Field::new(i),
-                                            pattern: self.to_pattern(subpattern),
-                                       })
-                                       .collect();
-
-                        PatternKind::Leaf { subpatterns: subpatterns }
-                    }
-
-                    ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
-                }
-            }
-
-            PatKind::Binding(bm, ref ident, ref sub) => {
-                let def_id = self.cx.tcx.expect_def(pat.id).def_id();
-                let id = self.cx.tcx.map.as_local_node_id(def_id).unwrap();
-                let var_ty = self.cx.tcx.node_id_to_type(pat.id);
-                let region = match var_ty.sty {
-                    ty::TyRef(r, _) => Some(r),
-                    _ => None,
-                };
-                let (mutability, mode) = match bm {
-                    hir::BindByValue(hir::MutMutable) =>
-                        (Mutability::Mut, BindingMode::ByValue),
-                    hir::BindByValue(hir::MutImmutable) =>
-                        (Mutability::Not, BindingMode::ByValue),
-                    hir::BindByRef(hir::MutMutable) =>
-                        (Mutability::Not, BindingMode::ByRef(region.unwrap(), BorrowKind::Mut)),
-                    hir::BindByRef(hir::MutImmutable) =>
-                        (Mutability::Not, BindingMode::ByRef(region.unwrap(), BorrowKind::Shared)),
-                };
-
-                // A ref x pattern is the same node used for x, and as such it has
-                // x's type, which is &T, where we want T (the type being matched).
-                if let hir::BindByRef(_) = bm {
-                    if let ty::TyRef(_, mt) = ty.sty {
-                        ty = mt.ty;
-                    } else {
-                        bug!("`ref {}` has wrong type {}", ident.node, ty);
-                    }
-                }
-
-                PatternKind::Binding {
-                    mutability: mutability,
-                    mode: mode,
-                    name: ident.node,
-                    var: id,
-                    ty: var_ty,
-                    subpattern: self.to_opt_pattern(sub),
-                }
-            }
-
-            PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
-                let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
-                let adt_def = match pat_ty.sty {
-                    ty::TyAdt(adt_def, _) => adt_def,
-                    _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
-                };
-                let variant_def = adt_def.variant_of_def(self.cx.tcx.expect_def(pat.id));
-
-                let subpatterns =
-                        subpatterns.iter()
-                                   .enumerate_and_adjust(variant_def.fields.len(), ddpos)
-                                   .map(|(i, field)| FieldPattern {
-                                       field: Field::new(i),
-                                       pattern: self.to_pattern(field),
-                                   })
-                                   .collect();
-                self.variant_or_leaf(pat, subpatterns)
-            }
-
-            PatKind::Struct(_, ref fields, _) => {
-                let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
-                let adt_def = match pat_ty.sty {
-                    ty::TyAdt(adt_def, _) => adt_def,
-                    _ => {
-                        span_bug!(
-                            pat.span,
-                            "struct pattern not applied to an ADT");
-                    }
-                };
-                let variant_def = adt_def.variant_of_def(self.cx.tcx.expect_def(pat.id));
-
-                let subpatterns =
-                    fields.iter()
-                          .map(|field| {
-                              let index = variant_def.index_of_field_named(field.node.name);
-                              let index = index.unwrap_or_else(|| {
-                                  span_bug!(
-                                      pat.span,
-                                      "no field with name {:?}",
-                                      field.node.name);
-                              });
-                              FieldPattern {
-                                  field: Field::new(index),
-                                  pattern: self.to_pattern(&field.node.pat),
-                              }
-                          })
-                          .collect();
-
-                self.variant_or_leaf(pat, subpatterns)
-            }
-        };
-
-        Pattern {
-            span: pat.span,
-            ty: ty,
-            kind: Box::new(kind),
-        }
-    }
-
-    fn to_patterns(&mut self, pats: &[P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
-        pats.iter().map(|p| self.to_pattern(p)).collect()
-    }
-
-    fn to_opt_pattern(&mut self, pat: &Option<P<hir::Pat>>) -> Option<Pattern<'tcx>> {
-        pat.as_ref().map(|p| self.to_pattern(p))
-    }
-
-    fn slice_or_array_pattern(&mut self,
-                              span: Span,
-                              ty: Ty<'tcx>,
-                              prefix: &[P<hir::Pat>],
-                              slice: &Option<P<hir::Pat>>,
-                              suffix: &[P<hir::Pat>])
-                              -> PatternKind<'tcx> {
-        match ty.sty {
-            ty::TySlice(..) => {
-                // matching a slice or fixed-length array
-                PatternKind::Slice {
-                    prefix: self.to_patterns(prefix),
-                    slice: self.to_opt_pattern(slice),
-                    suffix: self.to_patterns(suffix),
-                }
-            }
-
-            ty::TyArray(_, len) => {
-                // fixed-length array
-                assert!(len >= prefix.len() + suffix.len());
-                PatternKind::Array {
-                    prefix: self.to_patterns(prefix),
-                    slice: self.to_opt_pattern(slice),
-                    suffix: self.to_patterns(suffix),
-                }
-            }
-
-            _ => {
-                span_bug!(span, "unexpanded macro or bad constant etc");
-            }
-        }
-    }
-
-    fn variant_or_leaf(&mut self,
-                       pat: &hir::Pat,
-                       subpatterns: Vec<FieldPattern<'tcx>>)
-                       -> PatternKind<'tcx> {
-        match self.cx.tcx.expect_def(pat.id) {
-            Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
-                let enum_id = self.cx.tcx.parent_def_id(variant_id).unwrap();
-                let adt_def = self.cx.tcx.lookup_adt_def(enum_id);
-                if adt_def.variants.len() > 1 {
-                    PatternKind::Variant {
-                        adt_def: adt_def,
-                        variant_index: adt_def.variant_index_with_id(variant_id),
-                        subpatterns: subpatterns,
-                    }
-                } else {
-                    PatternKind::Leaf { subpatterns: subpatterns }
-                }
-            }
-
-            Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
-            Def::TyAlias(..) | Def::AssociatedTy(..) => {
-                PatternKind::Leaf { subpatterns: subpatterns }
-            }
-
-            def => {
-                span_bug!(pat.span, "inappropriate def for pattern: {:?}", def);
-            }
-        }
-    }
-}
index 59137e2bcd78fd2d9d55b7c408f71859c58c84e2..49a592b07fb4f5134728da29738787bdf02c1b0a 100644 (file)
@@ -14,9 +14,7 @@
 //! unit-tested and separated from the Rust source and compiler data
 //! structures.
 
-use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp,
-    TypedConstVal};
-use rustc::middle::const_val::ConstVal;
+use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, UnOp, TypedConstVal};
 use rustc::hir::def_id::DefId;
 use rustc::middle::region::CodeExtent;
 use rustc::ty::subst::Substs;
@@ -28,6 +26,8 @@
 
 pub mod cx;
 
+pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
+
 #[derive(Clone, Debug)]
 pub struct Block<'tcx> {
     pub extent: CodeExtent,
@@ -266,86 +266,12 @@ pub struct Arm<'tcx> {
     pub body: ExprRef<'tcx>,
 }
 
-#[derive(Clone, Debug)]
-pub struct Pattern<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub span: Span,
-    pub kind: Box<PatternKind<'tcx>>,
-}
-
 #[derive(Copy, Clone, Debug)]
 pub enum LogicalOp {
     And,
     Or,
 }
 
-#[derive(Clone, Debug)]
-pub enum PatternKind<'tcx> {
-    Wild,
-
-    /// x, ref x, x @ P, etc
-    Binding {
-        mutability: Mutability,
-        name: ast::Name,
-        mode: BindingMode<'tcx>,
-        var: ast::NodeId,
-        ty: Ty<'tcx>,
-        subpattern: Option<Pattern<'tcx>>,
-    },
-
-    /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
-    Variant {
-        adt_def: AdtDef<'tcx>,
-        variant_index: usize,
-        subpatterns: Vec<FieldPattern<'tcx>>,
-    },
-
-    /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
-    Leaf {
-        subpatterns: Vec<FieldPattern<'tcx>>,
-    },
-
-    /// box P, &P, &mut P, etc
-    Deref {
-        subpattern: Pattern<'tcx>,
-    },
-
-    Constant {
-        value: ConstVal,
-    },
-
-    Range {
-        lo: Literal<'tcx>,
-        hi: Literal<'tcx>,
-    },
-
-    /// matches against a slice, checking the length and extracting elements
-    Slice {
-        prefix: Vec<Pattern<'tcx>>,
-        slice: Option<Pattern<'tcx>>,
-        suffix: Vec<Pattern<'tcx>>,
-    },
-
-    /// fixed match against an array, irrefutable
-    Array {
-        prefix: Vec<Pattern<'tcx>>,
-        slice: Option<Pattern<'tcx>>,
-        suffix: Vec<Pattern<'tcx>>,
-    },
-}
-
-#[derive(Copy, Clone, Debug)]
-pub enum BindingMode<'tcx> {
-    ByValue,
-    ByRef(&'tcx Region, BorrowKind),
-}
-
-#[derive(Clone, Debug)]
-pub struct FieldPattern<'tcx> {
-    pub field: Field,
-    pub pattern: Pattern<'tcx>,
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // The Mirror trait