about summary refs log tree commit diff
path: root/src/librustc_mir/transform
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-12 04:14:07 +0000
committerbors <bors@rust-lang.org>2017-09-12 04:14:07 +0000
commit3cb24bd37bcc46ecbb1f5f3f96f9d1de0aa7e92d (patch)
tree0b6b7342122257fbe0d5f38ca38142776cef7542 /src/librustc_mir/transform
parent11f64d8f881a8bd994210efc1d3ff1982abf9df3 (diff)
parent57ebd28fdb69d7cc4df3de343664e6698a4b55f0 (diff)
downloadrust-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.rs7
-rw-r--r--src/librustc_mir/transform/erase_regions.rs35
-rw-r--r--src/librustc_mir/transform/generator.rs15
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs14
-rw-r--r--src/librustc_mir/transform/simplify_branches.rs6
-rw-r--r--src/librustc_mir/transform/type_check.rs5
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()