move hair::cx::pattern to const_eval
This commit is contained in:
parent
bb5afb4121
commit
732f22745d
|
@ -335,6 +335,7 @@ dependencies = [
|
||||||
"rustc 0.0.0",
|
"rustc 0.0.0",
|
||||||
"rustc_back 0.0.0",
|
"rustc_back 0.0.0",
|
||||||
"rustc_const_math 0.0.0",
|
"rustc_const_math 0.0.0",
|
||||||
|
"rustc_data_structures 0.0.0",
|
||||||
"rustc_errors 0.0.0",
|
"rustc_errors 0.0.0",
|
||||||
"serialize 0.0.0",
|
"serialize 0.0.0",
|
||||||
"syntax 0.0.0",
|
"syntax 0.0.0",
|
||||||
|
|
|
@ -14,6 +14,7 @@ serialize = { path = "../libserialize" }
|
||||||
rustc = { path = "../librustc" }
|
rustc = { path = "../librustc" }
|
||||||
rustc_back = { path = "../librustc_back" }
|
rustc_back = { path = "../librustc_back" }
|
||||||
rustc_const_math = { path = "../librustc_const_math" }
|
rustc_const_math = { path = "../librustc_const_math" }
|
||||||
|
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||||
rustc_errors = { path = "../librustc_errors" }
|
rustc_errors = { path = "../librustc_errors" }
|
||||||
syntax = { path = "../libsyntax" }
|
syntax = { path = "../libsyntax" }
|
||||||
graphviz = { path = "../libgraphviz" }
|
graphviz = { path = "../libgraphviz" }
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#[macro_use] extern crate rustc;
|
#[macro_use] extern crate rustc;
|
||||||
extern crate rustc_back;
|
extern crate rustc_back;
|
||||||
extern crate rustc_const_math;
|
extern crate rustc_const_math;
|
||||||
|
extern crate rustc_data_structures;
|
||||||
extern crate rustc_errors;
|
extern crate rustc_errors;
|
||||||
extern crate graphviz;
|
extern crate graphviz;
|
||||||
extern crate syntax_pos;
|
extern crate syntax_pos;
|
||||||
|
@ -47,6 +48,7 @@ pub mod diagnostics;
|
||||||
|
|
||||||
mod eval;
|
mod eval;
|
||||||
pub mod check_match;
|
pub mod check_match;
|
||||||
|
pub mod pattern;
|
||||||
|
|
||||||
pub use eval::*;
|
pub use eval::*;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -8,87 +8,128 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use hair::*;
|
use eval;
|
||||||
use hair::cx::Cx;
|
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc_const_eval as const_eval;
|
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::def::Def;
|
||||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||||
use rustc::ty::{self, Ty};
|
|
||||||
use rustc::mir::repr::*;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use rustc::hir::{self, PatKind};
|
|
||||||
|
use syntax::ast;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
/// When there are multiple patterns in a single arm, each one has its
|
#[derive(Copy, Clone, Debug)]
|
||||||
/// own node-ids for the bindings. References to the variables always
|
pub enum BindingMode<'tcx> {
|
||||||
/// use the node-ids from the first pattern in the arm, so we just
|
ByValue,
|
||||||
/// remap the ids for all subsequent bindings to the first one.
|
ByRef(&'tcx Region, BorrowKind),
|
||||||
///
|
|
||||||
/// 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> {
|
#[derive(Clone, Debug)]
|
||||||
pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
|
pub struct FieldPattern<'tcx> {
|
||||||
PatCx::new(self).to_pattern(pat)
|
pub field: Field,
|
||||||
}
|
pub pattern: Pattern<'tcx>,
|
||||||
|
|
||||||
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> {
|
#[derive(Clone, Debug)]
|
||||||
fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>)
|
pub struct Pattern<'tcx> {
|
||||||
-> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
pub ty: Ty<'tcx>,
|
||||||
PatCx {
|
pub span: Span,
|
||||||
cx: cx,
|
pub kind: Box<PatternKind<'tcx>>,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
|
#[derive(Clone, Debug)]
|
||||||
let mut ty = self.cx.tcx.node_id_to_type(pat.id);
|
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 {
|
let kind = match pat.node {
|
||||||
PatKind::Wild => PatternKind::Wild,
|
PatKind::Wild => PatternKind::Wild,
|
||||||
|
|
||||||
PatKind::Lit(ref value) => {
|
PatKind::Lit(ref value) => {
|
||||||
let value = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), value);
|
let value = eval::eval_const_expr(tcx.global_tcx(), value);
|
||||||
PatternKind::Constant { value: value }
|
PatternKind::Constant { value: value }
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Range(ref lo, ref hi) => {
|
PatKind::Range(ref lo, ref hi) => {
|
||||||
let lo = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), lo);
|
let lo = eval::eval_const_expr(tcx.global_tcx(), lo);
|
||||||
let lo = Literal::Value { value: lo };
|
let lo = Literal::Value { value: lo };
|
||||||
let hi = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), hi);
|
let hi = eval::eval_const_expr(tcx.global_tcx(), hi);
|
||||||
let hi = Literal::Value { value: hi };
|
let hi = Literal::Value { value: hi };
|
||||||
PatternKind::Range { lo: lo, hi: hi }
|
PatternKind::Range { lo: lo, hi: hi }
|
||||||
},
|
},
|
||||||
|
|
||||||
PatKind::Path(..) => {
|
PatKind::Path(..) => {
|
||||||
match self.cx.tcx.expect_def(pat.id) {
|
match tcx.expect_def(pat.id) {
|
||||||
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
|
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
|
||||||
let tcx = self.cx.tcx.global_tcx();
|
let tcx = tcx.global_tcx();
|
||||||
let substs = Some(self.cx.tcx.node_id_item_substs(pat.id).substs);
|
let substs = Some(tcx.node_id_item_substs(pat.id).substs);
|
||||||
match const_eval::lookup_const_by_id(tcx, def_id, substs) {
|
match eval::lookup_const_by_id(tcx, def_id, substs) {
|
||||||
Some((const_expr, _const_ty)) => {
|
Some((const_expr, _const_ty)) => {
|
||||||
match const_eval::const_expr_to_pat(tcx,
|
match eval::const_expr_to_pat(tcx,
|
||||||
const_expr,
|
const_expr,
|
||||||
pat.id,
|
pat.id,
|
||||||
pat.span) {
|
pat.span) {
|
||||||
Ok(pat) =>
|
Ok(pat) =>
|
||||||
return self.to_pattern(&pat),
|
return Pattern::from_hir(tcx, &pat),
|
||||||
Err(_) =>
|
Err(_) =>
|
||||||
span_bug!(
|
span_bug!(
|
||||||
pat.span, "illegal constant"),
|
pat.span, "illegal constant"),
|
||||||
|
@ -103,32 +144,33 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.variant_or_leaf(pat, vec![])
|
PatternKind::from_variant_or_leaf(tcx, pat, vec![])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Ref(ref subpattern, _) |
|
PatKind::Ref(ref subpattern, _) |
|
||||||
PatKind::Box(ref subpattern) => {
|
PatKind::Box(ref subpattern) => {
|
||||||
PatternKind::Deref { subpattern: self.to_pattern(subpattern) }
|
PatternKind::Deref { subpattern: Self::from_hir(tcx, subpattern) }
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Slice(ref prefix, ref slice, ref suffix) => {
|
PatKind::Slice(ref prefix, ref slice, ref suffix) => {
|
||||||
let ty = self.cx.tcx.node_id_to_type(pat.id);
|
let ty = tcx.node_id_to_type(pat.id);
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyRef(_, mt) =>
|
ty::TyRef(_, mt) =>
|
||||||
PatternKind::Deref {
|
PatternKind::Deref {
|
||||||
subpattern: Pattern {
|
subpattern: Pattern {
|
||||||
ty: mt.ty,
|
ty: mt.ty,
|
||||||
span: pat.span,
|
span: pat.span,
|
||||||
kind: Box::new(self.slice_or_array_pattern(pat.span, mt.ty, prefix,
|
kind: Box::new(PatternKind::from_slice_or_array(
|
||||||
slice, suffix)),
|
tcx, pat.span, mt.ty, prefix, slice, suffix))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ty::TySlice(..) |
|
ty::TySlice(..) |
|
||||||
ty::TyArray(..) =>
|
ty::TyArray(..) =>
|
||||||
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
|
PatternKind::from_slice_or_array(
|
||||||
|
tcx, pat.span, ty, prefix, slice, suffix),
|
||||||
|
|
||||||
ref sty =>
|
ref sty =>
|
||||||
span_bug!(
|
span_bug!(
|
||||||
|
@ -139,14 +181,14 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Tuple(ref subpatterns, ddpos) => {
|
PatKind::Tuple(ref subpatterns, ddpos) => {
|
||||||
match self.cx.tcx.node_id_to_type(pat.id).sty {
|
match tcx.node_id_to_type(pat.id).sty {
|
||||||
ty::TyTuple(ref tys) => {
|
ty::TyTuple(ref tys) => {
|
||||||
let subpatterns =
|
let subpatterns =
|
||||||
subpatterns.iter()
|
subpatterns.iter()
|
||||||
.enumerate_and_adjust(tys.len(), ddpos)
|
.enumerate_and_adjust(tys.len(), ddpos)
|
||||||
.map(|(i, subpattern)| FieldPattern {
|
.map(|(i, subpattern)| FieldPattern {
|
||||||
field: Field::new(i),
|
field: Field::new(i),
|
||||||
pattern: self.to_pattern(subpattern),
|
pattern: Self::from_hir(tcx, subpattern),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -158,9 +200,9 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Binding(bm, ref ident, ref sub) => {
|
PatKind::Binding(bm, ref ident, ref sub) => {
|
||||||
let def_id = self.cx.tcx.expect_def(pat.id).def_id();
|
let def_id = tcx.expect_def(pat.id).def_id();
|
||||||
let id = self.cx.tcx.map.as_local_node_id(def_id).unwrap();
|
let id = tcx.map.as_local_node_id(def_id).unwrap();
|
||||||
let var_ty = self.cx.tcx.node_id_to_type(pat.id);
|
let var_ty = tcx.node_id_to_type(pat.id);
|
||||||
let region = match var_ty.sty {
|
let region = match var_ty.sty {
|
||||||
ty::TyRef(r, _) => Some(r),
|
ty::TyRef(r, _) => Some(r),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -192,31 +234,31 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
name: ident.node,
|
name: ident.node,
|
||||||
var: id,
|
var: id,
|
||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
subpattern: self.to_opt_pattern(sub),
|
subpattern: Self::from_opt_pattern(tcx, sub),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
|
PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
|
||||||
let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
|
let pat_ty = tcx.node_id_to_type(pat.id);
|
||||||
let adt_def = match pat_ty.sty {
|
let adt_def = match pat_ty.sty {
|
||||||
ty::TyAdt(adt_def, _) => adt_def,
|
ty::TyAdt(adt_def, _) => adt_def,
|
||||||
_ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
|
_ => 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 variant_def = adt_def.variant_of_def(tcx.expect_def(pat.id));
|
||||||
|
|
||||||
let subpatterns =
|
let subpatterns =
|
||||||
subpatterns.iter()
|
subpatterns.iter()
|
||||||
.enumerate_and_adjust(variant_def.fields.len(), ddpos)
|
.enumerate_and_adjust(variant_def.fields.len(), ddpos)
|
||||||
.map(|(i, field)| FieldPattern {
|
.map(|(i, field)| FieldPattern {
|
||||||
field: Field::new(i),
|
field: Field::new(i),
|
||||||
pattern: self.to_pattern(field),
|
pattern: Self::from_hir(tcx, field),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.variant_or_leaf(pat, subpatterns)
|
PatternKind::from_variant_or_leaf(tcx, pat, subpatterns)
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Struct(_, ref fields, _) => {
|
PatKind::Struct(_, ref fields, _) => {
|
||||||
let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
|
let pat_ty = tcx.node_id_to_type(pat.id);
|
||||||
let adt_def = match pat_ty.sty {
|
let adt_def = match pat_ty.sty {
|
||||||
ty::TyAdt(adt_def, _) => adt_def,
|
ty::TyAdt(adt_def, _) => adt_def,
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -225,7 +267,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
"struct pattern not applied to an ADT");
|
"struct pattern not applied to an ADT");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let variant_def = adt_def.variant_of_def(self.cx.tcx.expect_def(pat.id));
|
let variant_def = adt_def.variant_of_def(tcx.expect_def(pat.id));
|
||||||
|
|
||||||
let subpatterns =
|
let subpatterns =
|
||||||
fields.iter()
|
fields.iter()
|
||||||
|
@ -239,12 +281,12 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
});
|
});
|
||||||
FieldPattern {
|
FieldPattern {
|
||||||
field: Field::new(index),
|
field: Field::new(index),
|
||||||
pattern: self.to_pattern(&field.node.pat),
|
pattern: Self::from_hir(tcx, &field.node.pat),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.variant_or_leaf(pat, subpatterns)
|
PatternKind::from_variant_or_leaf(tcx, pat, subpatterns)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,28 +297,33 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_patterns(&mut self, pats: &[P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
|
fn from_patterns(tcx: TyCtxt<'a, 'gcx, 'tcx>, pats: &[P<hir::Pat>]) -> Vec<Self> {
|
||||||
pats.iter().map(|p| self.to_pattern(p)).collect()
|
pats.iter().map(|p| Self::from_hir(tcx, p)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_opt_pattern(&mut self, pat: &Option<P<hir::Pat>>) -> Option<Pattern<'tcx>> {
|
fn from_opt_pattern(tcx: TyCtxt<'a, 'gcx, 'tcx>, pat: &Option<P<hir::Pat>>) -> Option<Self>
|
||||||
pat.as_ref().map(|p| self.to_pattern(p))
|
{
|
||||||
|
pat.as_ref().map(|p| Self::from_hir(tcx, p))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn slice_or_array_pattern(&mut self,
|
impl<'a, 'gcx, 'tcx> PatternKind<'tcx> {
|
||||||
span: Span,
|
fn from_slice_or_array(
|
||||||
ty: Ty<'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
prefix: &[P<hir::Pat>],
|
span: Span,
|
||||||
slice: &Option<P<hir::Pat>>,
|
ty: Ty<'tcx>,
|
||||||
suffix: &[P<hir::Pat>])
|
prefix: &[P<hir::Pat>],
|
||||||
-> PatternKind<'tcx> {
|
slice: &Option<P<hir::Pat>>,
|
||||||
|
suffix: &[P<hir::Pat>])
|
||||||
|
-> Self
|
||||||
|
{
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TySlice(..) => {
|
ty::TySlice(..) => {
|
||||||
// matching a slice or fixed-length array
|
// matching a slice or fixed-length array
|
||||||
PatternKind::Slice {
|
PatternKind::Slice {
|
||||||
prefix: self.to_patterns(prefix),
|
prefix: Pattern::from_patterns(tcx, prefix),
|
||||||
slice: self.to_opt_pattern(slice),
|
slice: Pattern::from_opt_pattern(tcx, slice),
|
||||||
suffix: self.to_patterns(suffix),
|
suffix: Pattern::from_patterns(tcx, suffix),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,9 +331,9 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
// fixed-length array
|
// fixed-length array
|
||||||
assert!(len >= prefix.len() + suffix.len());
|
assert!(len >= prefix.len() + suffix.len());
|
||||||
PatternKind::Array {
|
PatternKind::Array {
|
||||||
prefix: self.to_patterns(prefix),
|
prefix: Pattern::from_patterns(tcx, prefix),
|
||||||
slice: self.to_opt_pattern(slice),
|
slice: Pattern::from_opt_pattern(tcx, slice),
|
||||||
suffix: self.to_patterns(suffix),
|
suffix: Pattern::from_patterns(tcx, suffix),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,14 +343,16 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn variant_or_leaf(&mut self,
|
fn from_variant_or_leaf(
|
||||||
pat: &hir::Pat,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
subpatterns: Vec<FieldPattern<'tcx>>)
|
pat: &hir::Pat,
|
||||||
-> PatternKind<'tcx> {
|
subpatterns: Vec<FieldPattern<'tcx>>)
|
||||||
match self.cx.tcx.expect_def(pat.id) {
|
-> Self
|
||||||
|
{
|
||||||
|
match tcx.expect_def(pat.id) {
|
||||||
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
|
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
|
||||||
let enum_id = self.cx.tcx.parent_def_id(variant_id).unwrap();
|
let enum_id = tcx.parent_def_id(variant_id).unwrap();
|
||||||
let adt_def = self.cx.tcx.lookup_adt_def(enum_id);
|
let adt_def = tcx.lookup_adt_def(enum_id);
|
||||||
if adt_def.variants.len() > 1 {
|
if adt_def.variants.len() > 1 {
|
||||||
PatternKind::Variant {
|
PatternKind::Variant {
|
||||||
adt_def: adt_def,
|
adt_def: adt_def,
|
|
@ -9,6 +9,8 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use hair::cx::Cx;
|
use hair::cx::Cx;
|
||||||
|
use hair::Pattern;
|
||||||
|
|
||||||
use rustc::middle::region::{CodeExtent, CodeExtentData, ROOT_CODE_EXTENT};
|
use rustc::middle::region::{CodeExtent, CodeExtentData, ROOT_CODE_EXTENT};
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::mir::repr::*;
|
use rustc::mir::repr::*;
|
||||||
|
@ -339,7 +341,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let lvalue = Lvalue::Local(Local::new(index + 1));
|
let lvalue = Lvalue::Local(Local::new(index + 1));
|
||||||
|
|
||||||
if let Some(pattern) = pattern {
|
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);
|
scope = self.declare_bindings(scope, ast_block.span, &pattern);
|
||||||
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
let remainder_extent =
|
let remainder_extent =
|
||||||
cx.tcx.region_maps.lookup_code_extent(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 {
|
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||||
span: stmt.span,
|
span: stmt.span,
|
||||||
kind: StmtKind::Let {
|
kind: StmtKind::Let {
|
||||||
|
|
|
@ -657,7 +657,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
|
||||||
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||||
Arm {
|
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(),
|
guard: arm.guard.to_ref(),
|
||||||
body: arm.body.to_ref(),
|
body: arm.body.to_ref(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,5 +196,4 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
mod block;
|
mod block;
|
||||||
mod expr;
|
mod expr;
|
||||||
mod pattern;
|
|
||||||
mod to_ref;
|
mod to_ref;
|
||||||
|
|
|
@ -14,9 +14,7 @@
|
||||||
//! unit-tested and separated from the Rust source and compiler data
|
//! unit-tested and separated from the Rust source and compiler data
|
||||||
//! structures.
|
//! structures.
|
||||||
|
|
||||||
use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp,
|
use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, UnOp, TypedConstVal};
|
||||||
TypedConstVal};
|
|
||||||
use rustc::middle::const_val::ConstVal;
|
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::middle::region::CodeExtent;
|
use rustc::middle::region::CodeExtent;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
|
@ -28,6 +26,8 @@ use self::cx::Cx;
|
||||||
|
|
||||||
pub mod cx;
|
pub mod cx;
|
||||||
|
|
||||||
|
pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Block<'tcx> {
|
pub struct Block<'tcx> {
|
||||||
pub extent: CodeExtent,
|
pub extent: CodeExtent,
|
||||||
|
@ -266,86 +266,12 @@ pub struct Arm<'tcx> {
|
||||||
pub body: ExprRef<'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)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum LogicalOp {
|
pub enum LogicalOp {
|
||||||
And,
|
And,
|
||||||
Or,
|
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
|
// The Mirror trait
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue