From e547f359bb079a45f299b496a69ab7d22d7ce1b0 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 14 Jan 2019 17:54:00 +0100 Subject: [PATCH 1/4] Get rid of the fake stack frame --- src/librustc_codegen_ssa/mir/constant.rs | 1 - src/librustc_mir/const_eval.rs | 78 ++++-------------------- src/librustc_mir/hair/pattern/_match.rs | 23 +++++-- src/librustc_mir/hair/pattern/mod.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 6 +- src/test/ui/consts/match_ice.rs | 11 ++++ 6 files changed, 44 insertions(+), 79 deletions(-) create mode 100644 src/test/ui/consts/match_ice.rs diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index e6d6ef1d7a38b..56d4342e6e161 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 f5f4048167938..fdda5aa7f89d8 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,54 +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(), - 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. @@ -91,15 +42,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>( @@ -108,7 +56,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) } @@ -529,13 +477,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, 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)?; @@ -560,11 +507,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) } @@ -584,7 +530,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 188a112044298..9cc5c93de41d8 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> { 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. 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 8991a90737c7e..cdaffe5d45673 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 03d6d3868c9f0..fba74514f044f 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 0000000000000..c785317778b3c --- /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 => {} + } +} From 21a06522ab8a45e17cce96e3d42babac7dc3f202 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 14 Jan 2019 17:54:35 +0100 Subject: [PATCH 2/4] Bail out on overly generic substitutions --- src/librustc_mir/interpret/cast.rs | 6 +--- src/librustc_mir/interpret/eval_context.rs | 42 ++++++++++++++++------ src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/place.rs | 5 +-- src/librustc_mir/interpret/step.rs | 4 +-- 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 190a381cf52a5..c3b71be8354da 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -109,11 +109,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // The src operand does not matter, just its type match src.layout.ty.sty { ty::Closure(def_id, substs) => { - let substs = self.tcx.subst_and_normalize_erasing_regions( - self.substs(), - ty::ParamEnv::reveal_all(), - &substs, - ); + let substs = self.subst_and_normalize_erasing_regions(substs)?; let instance = ty::Instance::resolve_closure( *self.tcx, def_id, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 19362b6cfdb1c..29dcd64eec846 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -214,11 +214,21 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc self.frame().mir } - pub fn substs(&self) -> &'tcx Substs<'tcx> { - if let Some(frame) = self.stack.last() { - frame.instance.substs - } else { - Substs::empty() + pub(super) fn subst_and_normalize_erasing_regions>( + &self, + substs: T, + ) -> EvalResult<'tcx, T> { + match self.stack.last() { + Some(frame) => Ok(self.tcx.subst_and_normalize_erasing_regions( + frame.instance.substs, + self.param_env, + &substs, + )), + None => if substs.needs_subst() { + err!(TooGeneric).into() + } else { + Ok(substs) + }, } } @@ -228,13 +238,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc substs: &'tcx Substs<'tcx> ) -> EvalResult<'tcx, ty::Instance<'tcx>> { trace!("resolve: {:?}, {:#?}", def_id, substs); - trace!("substs: {:#?}", self.substs()); trace!("param_env: {:#?}", self.param_env); - let substs = self.tcx.subst_and_normalize_erasing_regions( - self.substs(), - self.param_env, - &substs, - ); + let substs = self.subst_and_normalize_erasing_regions(substs)?; + trace!("substs: {:#?}", substs); ty::Instance::resolve( *self.tcx, self.param_env, @@ -274,6 +280,20 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } } + pub fn monomorphize_in_frame + Subst<'tcx>>( + &self, + t: T, + ) -> EvalResult<'tcx, T> { + match self.stack.last() { + Some(frame) => Ok(self.monomorphize(t, frame.instance.substs)), + None => if t.needs_subst() { + err!(TooGeneric).into() + } else { + Ok(t) + }, + } + } + pub fn monomorphize + Subst<'tcx>>( &self, t: T, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 04e0955ad6172..5a08a9e3abf1c 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -514,7 +514,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> Constant(ref constant) => { let layout = from_known_layout(layout, || { - let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs()); + let ty = self.monomorphize_in_frame(mir_op.ty(self.mir(), *self.tcx))?; self.layout_of(ty) })?; let op = self.const_value_to_op(*constant.literal)?; diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 962e0b7a74201..f3a948a6ca3e7 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -9,6 +9,7 @@ use rustc::hir; use rustc::mir; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; +use rustc::ty::TypeFoldable; use super::{ GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic, @@ -583,8 +584,8 @@ where } Static(ref static_) => { - let ty = self.monomorphize(static_.ty, self.substs()); - let layout = self.layout_of(ty)?; + assert!(!static_.ty.needs_subst()); + let layout = self.layout_of(static_.ty)?; let instance = ty::Instance::mono(*self.tcx, static_.def_id); let cid = GlobalId { instance, diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 2de8b3c1afdf3..f1b4e6a5055b6 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -248,7 +248,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } NullaryOp(mir::NullOp::SizeOf, ty) => { - let ty = self.monomorphize(ty, self.substs()); + let ty = self.monomorphize_in_frame(ty)?; let layout = self.layout_of(ty)?; assert!(!layout.is_unsized(), "SizeOf nullary MIR operator called for unsized type"); @@ -260,7 +260,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } Cast(kind, ref operand, cast_ty) => { - debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty); + debug_assert_eq!(self.monomorphize_in_frame(cast_ty)?, dest.layout.ty); let src = self.eval_operand(operand, None)?; self.cast(src, kind, dest)?; } From 87bef9216bcb923792f0ec4d1e59994932627945 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 14 Jan 2019 19:50:49 +0100 Subject: [PATCH 3/4] Span fixup --- src/librustc_mir/const_eval.rs | 14 ++++++++------ src/librustc_mir/transform/const_prop.rs | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index fdda5aa7f89d8..6d690fde7e01d 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -18,7 +18,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc::util::common::ErrorReported; use syntax::ast::Mutability; -use syntax::source_map::DUMMY_SP; +use syntax::source_map::{Span, DUMMY_SP}; use crate::interpret::{self, PlaceTy, MPlaceTy, MemPlace, OpTy, Operand, Immediate, Scalar, RawConst, ConstValue, Pointer, @@ -44,10 +44,11 @@ const DETECTOR_SNAPSHOT_PERIOD: isize = 256; /// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument. pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, + span: Span, param_env: ty::ParamEnv<'tcx>, ) -> CompileTimeEvalContext<'a, 'mir, 'tcx> { debug!("mk_eval_cx: {:?}", param_env); - EvalContext::new(tcx.at(DUMMY_SP), param_env, CompileTimeInterpreter::new()) + EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new()) } pub(crate) fn eval_promoted<'a, 'mir, 'tcx>( @@ -56,7 +57,8 @@ 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_eval_cx(tcx, param_env); + let span = tcx.def_span(cid.instance.def_id()); + let mut ecx = mk_eval_cx(tcx, span, param_env); eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env) } @@ -482,7 +484,7 @@ pub fn const_field<'a, 'tcx>( value: ty::Const<'tcx>, ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { trace!("const_field: {:?}, {:?}", field, value); - let ecx = mk_eval_cx(tcx, param_env); + let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env); let result = (|| { // get the operand again let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?; @@ -510,7 +512,7 @@ pub fn const_variant_index<'a, 'tcx>( val: ty::Const<'tcx>, ) -> EvalResult<'tcx, VariantIdx> { trace!("const_variant_index: {:?}", val); - let ecx = mk_eval_cx(tcx, param_env); + let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env); let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?; Ok(ecx.read_discriminant(op)?.1) } @@ -530,7 +532,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, key.param_env); + let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), 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/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index fba74514f044f..dc556a15cd855 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -110,7 +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 ecx = mk_eval_cx(tcx, param_env); + let ecx = mk_eval_cx(tcx, tcx.def_span(source.def_id), param_env); ConstPropagator { ecx, mir, From b805232372f1cb6c01916957d886c72bef43e6b3 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 14 Jan 2019 19:51:00 +0100 Subject: [PATCH 4/4] Add regression test --- src/test/ui/consts/match_ice.rs | 5 ++--- src/test/ui/consts/match_ice.stderr | 9 +++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/consts/match_ice.stderr diff --git a/src/test/ui/consts/match_ice.rs b/src/test/ui/consts/match_ice.rs index c785317778b3c..53c5782a4c70e 100644 --- a/src/test/ui/consts/match_ice.rs +++ b/src/test/ui/consts/match_ice.rs @@ -1,11 +1,10 @@ -// compile-pass // https://github.com/rust-lang/rust/issues/53708 struct S; fn main() { const C: &S = &S; - match C { - C => {} + match C { //~ ERROR non-exhaustive + C => {} // this is a common bug around constants and references in patterns } } diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr new file mode 100644 index 0000000000000..e6e04e2c46276 --- /dev/null +++ b/src/test/ui/consts/match_ice.stderr @@ -0,0 +1,9 @@ +error[E0004]: non-exhaustive patterns: `&S` not covered + --> $DIR/match_ice.rs:7:11 + | +LL | match C { //~ ERROR non-exhaustive + | ^ pattern `&S` not covered + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`.