about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs1
-rw-r--r--src/librustc_mir/const_eval.rs80
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs23
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs4
-rw-r--r--src/librustc_mir/transform/const_prop.rs6
-rw-r--r--src/test/ui/consts/match_ice.rs11
6 files changed, 44 insertions, 81 deletions
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index e6d6ef1d7a3..56d4342e6e1 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -59,7 +59,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     let field = const_field(
                         bx.tcx(),
                         ty::ParamEnv::reveal_all(),
-                        self.instance,
                         None,
                         mir::Field::new(field as usize),
                         c,
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 105856fecc7..25b0d1424ca 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -10,16 +10,15 @@ use rustc::hir::{self, def_id::DefId};
 use rustc::hir::def::Def;
 use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
 use rustc::mir;
-use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
+use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
 use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx};
 use rustc::ty::subst::Subst;
 use rustc::traits::Reveal;
-use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
 use rustc::util::common::ErrorReported;
 
 use syntax::ast::Mutability;
-use syntax::source_map::{Span, DUMMY_SP};
+use syntax::source_map::DUMMY_SP;
 
 use crate::interpret::{self,
     PlaceTy, MPlaceTy, MemPlace, OpTy, Operand, Immediate, Scalar, RawConst, ConstValue, Pointer,
@@ -35,56 +34,6 @@ const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
 /// Should be a power of two for performance reasons.
 const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
 
-/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
-/// The `EvalContext` is only meant to be used to query values from constants and statics.
-///
-/// This function is used during const propagation. We cannot use `mk_eval_cx`, because copy
-/// propagation happens *during* the computation of the MIR of the current function. So if we
-/// tried to call the `optimized_mir` query, we'd get a cycle error because we are (transitively)
-/// inside the `optimized_mir` query of the `Instance` given.
-///
-/// Since we are looking at the MIR of the function in an abstract manner, we don't have a
-/// `ParamEnv` available to us. This function creates a `ParamEnv` for the given instance.
-pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    mir: &'mir mir::Mir<'tcx>,
-    span: Span,
-) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
-    debug!("mk_borrowck_eval_cx: {:?}", instance);
-    let param_env = tcx.param_env(instance.def_id());
-    mk_eval_cx_inner(tcx, instance, mir, span, param_env)
-}
-
-/// This is just a helper function to reduce code duplication between `mk_borrowck_eval_cx` and
-/// `mk_eval_cx`. Do not call this function directly.
-fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    mir: &'mir mir::Mir<'tcx>,
-    span: Span,
-    param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
-    let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
-    // Insert a stack frame so any queries have the correct substs.
-    // We also avoid all the extra work performed by push_stack_frame,
-    // like initializing local variables
-    ecx.stack.push(interpret::Frame {
-        block: mir::START_BLOCK,
-        locals: IndexVec::new(),
-        local_layouts: IndexVec::new(),
-        instance,
-        span,
-        mir,
-        return_place: None,
-        return_to_block: StackPopCleanup::Goto(None), // never pop
-        stmt: 0,
-        extra: (),
-    });
-    Ok(ecx)
-}
-
-/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
 /// The `EvalContext` is only meant to be used to do field and index projections into constants for
 /// `simd_shuffle` and const patterns in match arms.
 ///
@@ -92,15 +41,12 @@ fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
 /// that inform us about the generic bounds of the constant. E.g. using an associated constant
 /// of a function's generic parameter will require knowledge about the bounds on the generic
 /// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
-fn mk_eval_cx<'a, 'tcx>(
+pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'tcx, 'tcx>> {
-    debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
-    let span = tcx.def_span(instance.def_id());
-    let mir = tcx.optimized_mir(instance.def.def_id());
-    mk_eval_cx_inner(tcx, instance, mir, span, param_env)
+) -> CompileTimeEvalContext<'a, 'mir, 'tcx> {
+    debug!("mk_eval_cx: {:?}", param_env);
+    EvalContext::new(tcx.at(DUMMY_SP), param_env, CompileTimeInterpreter::new())
 }
 
 pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
@@ -109,7 +55,7 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
     mir: &'mir mir::Mir<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
-    let mut ecx = mk_borrowck_eval_cx(tcx, cid.instance, mir, DUMMY_SP).unwrap();
+    let mut ecx = mk_eval_cx(tcx, param_env);
     eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
 }
 
@@ -530,13 +476,12 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
 pub fn const_field<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    instance: ty::Instance<'tcx>,
     variant: Option<VariantIdx>,
     field: mir::Field,
     value: ty::Const<'tcx>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
-    trace!("const_field: {:?}, {:?}, {:?}", instance, field, value);
-    let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
+    trace!("const_field: {:?}, {:?}", field, value);
+    let ecx = mk_eval_cx(tcx, param_env);
     let result = (|| {
         // get the operand again
         let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?;
@@ -561,11 +506,10 @@ pub fn const_field<'a, 'tcx>(
 pub fn const_variant_index<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    instance: ty::Instance<'tcx>,
     val: ty::Const<'tcx>,
 ) -> EvalResult<'tcx, VariantIdx> {
-    trace!("const_variant_index: {:?}, {:?}", instance, val);
-    let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
+    trace!("const_variant_index: {:?}", val);
+    let ecx = mk_eval_cx(tcx, param_env);
     let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?;
     Ok(ecx.read_discriminant(op)?.1)
 }
@@ -585,7 +529,7 @@ fn validate_and_turn_into_const<'a, 'tcx>(
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
     let cid = key.value;
-    let ecx = mk_eval_cx(tcx, cid.instance, key.param_env).unwrap();
+    let ecx = mk_eval_cx(tcx, key.param_env);
     let val = (|| {
         let op = ecx.raw_const_to_mplace(constant)?.into();
         // FIXME: Once the visitor infrastructure landed, change validation to
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 188a1120442..9cc5c93de41 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -427,13 +427,24 @@ pub enum Constructor<'tcx> {
 }
 
 impl<'tcx> Constructor<'tcx> {
-    fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
+    fn variant_index_for_adt<'a>(
+        &self,
+        cx: &MatchCheckCtxt<'a, 'tcx>,
+        adt: &'tcx ty::AdtDef,
+    ) -> VariantIdx {
         match self {
             &Variant(vid) => adt.variant_index_with_id(vid),
             &Single => {
                 assert!(!adt.is_enum());
                 VariantIdx::new(0)
             }
+            &ConstantValue(c) => {
+                ::const_eval::const_variant_index(
+                    cx.tcx,
+                    cx.param_env,
+                    c,
+                ).unwrap()
+            },
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt)
         }
     }
@@ -567,7 +578,7 @@ impl<'tcx> Witness<'tcx> {
                             PatternKind::Variant {
                                 adt_def: adt,
                                 substs,
-                                variant_index: ctor.variant_index_for_adt(adt),
+                                variant_index: ctor.variant_index_for_adt(cx, adt),
                                 subpatterns: pats
                             }
                         } else {
@@ -1329,7 +1340,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
 ///
 /// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3.
 /// A struct pattern's arity is the number of fields it contains, etc.
-fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
+fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> u64 {
     debug!("constructor_arity({:#?}, {:?})", ctor, ty);
     match ty.sty {
         ty::Tuple(ref fs) => fs.len() as u64,
@@ -1340,7 +1351,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
         },
         ty::Ref(..) => 1,
         ty::Adt(adt, _) => {
-            adt.variants[ctor.variant_index_for_adt(adt)].fields.len() as u64
+            adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.len() as u64
         }
         _ => 0
     }
@@ -1351,7 +1362,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
 ///
 /// For instance, a tuple pattern (43u32, 'a') has sub pattern types [u32, char].
 fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
-                                             ctor: &Constructor,
+                                             ctor: &Constructor<'tcx>,
                                              ty: Ty<'tcx>) -> Vec<Ty<'tcx>>
 {
     debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
@@ -1368,7 +1379,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
                 // Use T as the sub pattern type of Box<T>.
                 vec![substs.type_at(0)]
             } else {
-                adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
+                adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.iter().map(|field| {
                     let is_visible = adt.is_enum()
                         || field.vis.is_accessible_from(cx.module, cx.tcx);
                     if is_visible {
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 8991a90737c..cdaffe5d456 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -885,7 +885,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         let adt_subpattern = |i, variant_opt| {
             let field = Field::new(i);
             let val = const_field(
-                self.tcx, self.param_env, instance,
+                self.tcx, self.param_env,
                 variant_opt, field, cv,
             ).expect("field access failed");
             self.const_to_pat(instance, val, id, span)
@@ -928,7 +928,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             },
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
                 let variant_index = const_variant_index(
-                    self.tcx, self.param_env, instance, cv
+                    self.tcx, self.param_env, cv
                 ).expect("const_variant_index failed");
                 let subpatterns = adt_subpatterns(
                     adt_def.variants[variant_index].fields.len(),
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 03d6d3868c9..fba74514f04 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -20,7 +20,7 @@ use rustc::ty::layout::{
 
 use interpret::{self, EvalContext, ScalarMaybeUndef, Immediate, OpTy, MemoryKind};
 use const_eval::{
-    CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_borrowck_eval_cx,
+    CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
     lazy_const_to_op,
 };
 use transform::{MirPass, MirSource};
@@ -110,9 +110,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
         source: MirSource,
     ) -> ConstPropagator<'a, 'mir, 'tcx> {
         let param_env = tcx.param_env(source.def_id);
-        let substs = Substs::identity_for_item(tcx, source.def_id);
-        let instance = Instance::new(source.def_id, substs);
-        let ecx = mk_borrowck_eval_cx(tcx, instance, mir, DUMMY_SP).unwrap();
+        let ecx = mk_eval_cx(tcx, param_env);
         ConstPropagator {
             ecx,
             mir,
diff --git a/src/test/ui/consts/match_ice.rs b/src/test/ui/consts/match_ice.rs
new file mode 100644
index 00000000000..c785317778b
--- /dev/null
+++ b/src/test/ui/consts/match_ice.rs
@@ -0,0 +1,11 @@
+// compile-pass
+// https://github.com/rust-lang/rust/issues/53708
+
+struct S;
+
+fn main() {
+    const C: &S = &S;
+    match C {
+        C => {}
+    }
+}