"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",
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" }
#[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;
mod eval;
pub mod check_match;
+pub mod pattern;
pub use eval::*;
--- /dev/null
+// 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);
+ }
+ }
+ }
+}
// 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::*;
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));
}
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 {
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(),
}
mod block;
mod expr;
-mod pattern;
mod to_ref;
+++ /dev/null
-// 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);
- }
- }
- }
-}
//! 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;
pub mod cx;
+pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
+
#[derive(Clone, Debug)]
pub struct Block<'tcx> {
pub extent: CodeExtent,
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