From 732f22745dbac22fad9e8f9c0f17d37a23db52f8 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 24 Sep 2016 17:45:24 +0300 Subject: [PATCH] move hair::cx::pattern to const_eval --- src/Cargo.lock | 1 + src/librustc_const_eval/Cargo.toml | 1 + src/librustc_const_eval/lib.rs | 2 + .../cx => librustc_const_eval}/pattern.rs | 245 +++++++++++------- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/hair/cx/block.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_mir/hair/cx/mod.rs | 1 - src/librustc_mir/hair/mod.rs | 80 +----- 9 files changed, 159 insertions(+), 179 deletions(-) rename src/{librustc_mir/hair/cx => librustc_const_eval}/pattern.rs (59%) diff --git a/src/Cargo.lock b/src/Cargo.lock index a32ba02457e..d12b95d8b22 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -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", diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml index 8967672548b..ec4d2fdf967 100644 --- a/src/librustc_const_eval/Cargo.toml +++ b/src/librustc_const_eval/Cargo.toml @@ -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" } diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 7b40269ba56..9a97df96696 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -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 @@ pub mod diagnostics; mod eval; pub mod check_match; +pub mod pattern; pub use eval::*; diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_const_eval/pattern.rs similarity index 59% rename from src/librustc_mir/hair/cx/pattern.rs rename to src/librustc_const_eval/pattern.rs index 84f415463be..b32c78b31bb 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -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 // http://rust-lang.org/COPYRIGHT. // @@ -8,87 +8,128 @@ // 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 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::ty::{self, Ty}; -use rustc::mir::repr::*; -use rustc::hir::{self, PatKind}; + +use rustc_data_structures::indexed_vec::Idx; + +use syntax::ast; 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>, +#[derive(Copy, Clone, Debug)] +pub enum BindingMode<'tcx> { + ByValue, + ByRef(&'tcx Region, BorrowKind), } -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) - } +#[derive(Clone, Debug)] +pub struct FieldPattern<'tcx> { + pub field: Field, + pub pattern: Pattern<'tcx>, } -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, - } - } +#[derive(Clone, Debug)] +pub struct Pattern<'tcx> { + pub ty: Ty<'tcx>, + pub span: Span, + pub kind: Box>, +} - fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { - let mut ty = self.cx.tcx.node_id_to_type(pat.id); +#[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>, + }, + + /// 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>, + }, + + /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant + Leaf { + subpatterns: Vec>, + }, + + /// 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>, + slice: Option>, + suffix: Vec>, + }, + + /// fixed match against an array, irrefutable + Array { + prefix: Vec>, + slice: Option>, + suffix: Vec>, + }, +} + +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 = 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 } } 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 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 }; PatternKind::Range { lo: lo, hi: hi } }, PatKind::Path(..) => { - match self.cx.tcx.expect_def(pat.id) { + match 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) { + 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 const_eval::const_expr_to_pat(tcx, - const_expr, - pat.id, - pat.span) { + match eval::const_expr_to_pat(tcx, + const_expr, + pat.id, + pat.span) { Ok(pat) => - return self.to_pattern(&pat), + return Pattern::from_hir(tcx, &pat), Err(_) => span_bug!( 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::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) => { - let ty = self.cx.tcx.node_id_to_type(pat.id); + 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(self.slice_or_array_pattern(pat.span, mt.ty, prefix, - slice, suffix)), + kind: Box::new(PatternKind::from_slice_or_array( + tcx, pat.span, mt.ty, prefix, slice, suffix)) }, }, ty::TySlice(..) | 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 => span_bug!( @@ -139,14 +181,14 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { } 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) => { let subpatterns = subpatterns.iter() .enumerate_and_adjust(tys.len(), ddpos) .map(|(i, subpattern)| FieldPattern { field: Field::new(i), - pattern: self.to_pattern(subpattern), + pattern: Self::from_hir(tcx, subpattern), }) .collect(); @@ -158,9 +200,9 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { } 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 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, @@ -192,31 +234,31 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { name: ident.node, var: id, ty: var_ty, - subpattern: self.to_opt_pattern(sub), + subpattern: Self::from_opt_pattern(tcx, sub), } } 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 { 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 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.to_pattern(field), + pattern: Self::from_hir(tcx, field), }) .collect(); - self.variant_or_leaf(pat, subpatterns) + PatternKind::from_variant_or_leaf(tcx, pat, subpatterns) } 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 { 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"); } }; - 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 = fields.iter() @@ -239,12 +281,12 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { }); FieldPattern { field: Field::new(index), - pattern: self.to_pattern(&field.node.pat), + pattern: Self::from_hir(tcx, &field.node.pat), } }) .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]) -> Vec> { - pats.iter().map(|p| self.to_pattern(p)).collect() + fn from_patterns(tcx: TyCtxt<'a, 'gcx, 'tcx>, pats: &[P]) -> Vec { + pats.iter().map(|p| Self::from_hir(tcx, p)).collect() } - fn to_opt_pattern(&mut self, pat: &Option>) -> Option> { - pat.as_ref().map(|p| self.to_pattern(p)) + fn from_opt_pattern(tcx: TyCtxt<'a, 'gcx, 'tcx>, pat: &Option>) -> Option + { + pat.as_ref().map(|p| Self::from_hir(tcx, p)) } +} - fn slice_or_array_pattern(&mut self, - span: Span, - ty: Ty<'tcx>, - prefix: &[P], - slice: &Option>, - suffix: &[P]) - -> PatternKind<'tcx> { +impl<'a, 'gcx, 'tcx> PatternKind<'tcx> { + fn from_slice_or_array( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + span: Span, + ty: Ty<'tcx>, + prefix: &[P], + slice: &Option>, + suffix: &[P]) + -> Self + { 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), + prefix: Pattern::from_patterns(tcx, prefix), + slice: Pattern::from_opt_pattern(tcx, slice), + suffix: Pattern::from_patterns(tcx, suffix), } } @@ -284,9 +331,9 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { // 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), + prefix: Pattern::from_patterns(tcx, prefix), + slice: Pattern::from_opt_pattern(tcx, slice), + 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, - pat: &hir::Pat, - subpatterns: Vec>) - -> PatternKind<'tcx> { - match self.cx.tcx.expect_def(pat.id) { + fn from_variant_or_leaf( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + pat: &hir::Pat, + subpatterns: Vec>) + -> Self + { + match 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); + 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, diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 7b3306de753..a7249677e01 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { 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)); } diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 52d54f2cc85..ec1136368c1 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -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 { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index f23c9d3caf0..45c49a4627f 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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(), } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 9fe3addea41..f87e0acaa4c 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -196,5 +196,4 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { mod block; mod expr; -mod pattern; mod to_ref; diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 59137e2bcd7..49a592b07fb 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -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 @@ use self::cx::Cx; 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>, -} - #[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>, - }, - - /// 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>, - }, - - /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant - Leaf { - subpatterns: Vec>, - }, - - /// 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>, - slice: Option>, - suffix: Vec>, - }, - - /// fixed match against an array, irrefutable - Array { - prefix: Vec>, - slice: Option>, - suffix: Vec>, - }, -} - -#[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