diff options
| author | bors <bors@rust-lang.org> | 2017-09-12 04:14:07 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-09-12 04:14:07 +0000 |
| commit | 3cb24bd37bcc46ecbb1f5f3f96f9d1de0aa7e92d (patch) | |
| tree | 0b6b7342122257fbe0d5f38ca38142776cef7542 /src/librustc_mir/transform | |
| parent | 11f64d8f881a8bd994210efc1d3ff1982abf9df3 (diff) | |
| parent | 57ebd28fdb69d7cc4df3de343664e6698a4b55f0 (diff) | |
| download | rust-3cb24bd37bcc46ecbb1f5f3f96f9d1de0aa7e92d.tar.gz rust-3cb24bd37bcc46ecbb1f5f3f96f9d1de0aa7e92d.zip | |
Auto merge of #44275 - eddyb:deferred-ctfe, r=nikomatsakis
Evaluate fixed-length array length expressions lazily. This is in preparation for polymorphic array lengths (aka `[T; T::A]`) and const generics. We need deferred const-evaluation to break cycles when array types show up in positions which require knowing the array type to typeck the array length, e.g. the array type is in a `where` clause. The final step - actually passing bounds in scope to array length expressions from the parent - is not done because it still produces cycles when *normalizing* `ParamEnv`s, and @nikomatsakis' in-progress lazy normalization work is needed to deal with that uniformly. However, the changes here are still useful to unlock work on const generics, which @EpicatSupercell manifested interest in, and I might be mentoring them for that, but we need this baseline first. r? @nikomatsakis cc @oli-obk
Diffstat (limited to 'src/librustc_mir/transform')
| -rw-r--r-- | src/librustc_mir/transform/elaborate_drops.rs | 7 | ||||
| -rw-r--r-- | src/librustc_mir/transform/erase_regions.rs | 35 | ||||
| -rw-r--r-- | src/librustc_mir/transform/generator.rs | 15 | ||||
| -rw-r--r-- | src/librustc_mir/transform/qualify_consts.rs | 14 | ||||
| -rw-r--r-- | src/librustc_mir/transform/simplify_branches.rs | 6 | ||||
| -rw-r--r-- | src/librustc_mir/transform/type_check.rs | 5 |
6 files changed, 44 insertions, 38 deletions
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index d6477f2babf..1077f3b0146 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -520,7 +520,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, ty: self.tcx.types.bool, - literal: Literal::Value { value: ConstVal::Bool(val) } + literal: Literal::Value { + value: self.tcx.mk_const(ty::Const { + val: ConstVal::Bool(val), + ty: self.tcx.types.bool + }) + } }))) } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index fa51cd91be1..dc18cdd8f0d 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -15,7 +15,7 @@ //! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion. use rustc::ty::subst::Substs; -use rustc::ty::{Ty, TyCtxt, ClosureSubsts}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::*; use rustc::mir::visit::{MutVisitor, Lookup}; use rustc::mir::transform::{MirPass, MirSource}; @@ -37,38 +37,25 @@ impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> { impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: Lookup) { if !self.in_validation_statement { - *ty = self.tcx.erase_regions(&{*ty}); + *ty = self.tcx.erase_regions(ty); } self.super_ty(ty); } - fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) { - *substs = self.tcx.erase_regions(&{*substs}); + fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) { + *region = self.tcx.types.re_erased; } - fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) { - match *rvalue { - Rvalue::Ref(ref mut r, _, _) => { - *r = self.tcx.types.re_erased; - } - Rvalue::Use(..) | - Rvalue::Repeat(..) | - Rvalue::Len(..) | - Rvalue::Cast(..) | - Rvalue::BinaryOp(..) | - Rvalue::CheckedBinaryOp(..) | - Rvalue::UnaryOp(..) | - Rvalue::Discriminant(..) | - Rvalue::NullaryOp(..) | - Rvalue::Aggregate(..) => { - // These variants don't contain regions. - } - } - self.super_rvalue(rvalue, location); + fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) { + *constant = self.tcx.erase_regions(constant); + } + + fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) { + *substs = self.tcx.erase_regions(substs); } fn visit_closure_substs(&mut self, - substs: &mut ClosureSubsts<'tcx>, + substs: &mut ty::ClosureSubsts<'tcx>, _: Location) { *substs = self.tcx.erase_regions(substs); } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 0fb34c96b06..a52656becd7 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -175,7 +175,10 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { span: source_info.span, ty: self.tcx.types.u32, literal: Literal::Value { - value: ConstVal::Integral(ConstInt::U32(state_disc)), + value: self.tcx.mk_const(ty::Const { + val: ConstVal::Integral(ConstInt::U32(state_disc)), + ty: self.tcx.types.u32 + }), }, }); Statement { @@ -553,7 +556,10 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: mir.span, ty: tcx.types.bool, literal: Literal::Value { - value: ConstVal::Bool(false), + value: tcx.mk_const(ty::Const { + val: ConstVal::Bool(false), + ty: tcx.types.bool + }), }, }), expected: true, @@ -603,7 +609,10 @@ fn create_generator_resume_function<'a, 'tcx>( span: mir.span, ty: tcx.types.bool, literal: Literal::Value { - value: ConstVal::Bool(false), + value: tcx.mk_const(ty::Const { + val: ConstVal::Bool(false), + ty: tcx.types.bool + }), }, }), expected: true, diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index f891c991321..5550fb2788e 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -20,6 +20,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; +use rustc::middle::const_val::ConstVal; use rustc::traits::{self, Reveal}; use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; use rustc::ty::cast::CastTy; @@ -622,10 +623,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } Operand::Constant(ref constant) => { - if let Literal::Item { def_id, substs: _ } = constant.literal { + if let Literal::Value { + value: &ty::Const { val: ConstVal::Unevaluated(def_id, _), ty } + } = constant.literal { // Don't peek inside trait associated constants. if self.tcx.trait_of_item(def_id).is_some() { - self.add_type(constant.ty); + self.add_type(ty); } else { let (bits, _) = self.tcx.at(constant.span).mir_const_qualif(def_id); @@ -635,7 +638,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Just in case the type is more specific than // the definition, e.g. impl associated const // with type parameters, take it into account. - self.qualif.restrict(constant.ty, self.tcx, self.param_env); + self.qualif.restrict(ty, self.tcx, self.param_env); } // Let `const fn` transitively have destructors, @@ -695,8 +698,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } _ => false } - } else if let ty::TyArray(_, 0) = ty.sty { - self.mode == Mode::Fn + } else if let ty::TyArray(_, len) = ty.sty { + len.val.to_const_int().unwrap().to_u64().unwrap() == 0 && + self.mode == Mode::Fn } else { false }; diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 1dcacb29c3e..0dff145ecbc 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -10,7 +10,7 @@ //! A pass that simplifies branches when their condition is known. -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt}; use rustc::middle::const_val::ConstVal; use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::*; @@ -40,7 +40,7 @@ impl MirPass for SimplifyBranches { TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant { literal: Literal::Value { ref value }, .. }), ref values, ref targets, .. } => { - if let Some(ref constint) = value.to_const_int() { + if let Some(ref constint) = value.val.to_const_int() { let (otherwise, targets) = targets.split_last().unwrap(); let mut ret = TerminatorKind::Goto { target: *otherwise }; for (v, t) in values.iter().zip(targets.iter()) { @@ -56,7 +56,7 @@ impl MirPass for SimplifyBranches { }, TerminatorKind::Assert { target, cond: Operand::Constant(box Constant { literal: Literal::Value { - value: ConstVal::Bool(cond) + value: &ty::Const { val: ConstVal::Bool(cond), .. } }, .. }), expected, .. } if cond == expected => { TerminatorKind::Goto { target: target } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 7fbeb9610f4..ab5998a3480 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -209,7 +209,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { LvalueTy::Ty { ty: match base_ty.sty { ty::TyArray(inner, size) => { - let min_size = (from as usize) + (to as usize); + let size = size.val.to_const_int().unwrap().to_u64().unwrap(); + let min_size = (from as u64) + (to as u64); if let Some(rest_size) = size.checked_sub(min_size) { tcx.mk_array(inner, rest_size) } else { @@ -572,7 +573,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { match operand { &Operand::Constant(box Constant { literal: Literal::Value { - value: ConstVal::Function(def_id, _), .. + value: &ty::Const { val: ConstVal::Function(def_id, _), .. }, .. }, .. }) => { Some(def_id) == self.tcx().lang_items().box_free_fn() |
