Skip to content

Commit c5b89bf

Browse files
committed
Auto merge of #57606 - oli-obk:shrink, r=<try>
Get rid of the fake stack frame for reading from constants r? @RalfJung fixes the ice in #53708 but still keeps around the wrong "non-exhaustive match" error cc @varkor
2 parents 33e6df4 + b805232 commit c5b89bf

File tree

12 files changed

+91
-99
lines changed

12 files changed

+91
-99
lines changed

src/librustc_codegen_ssa/mir/constant.rs

-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
5959
let field = const_field(
6060
bx.tcx(),
6161
ty::ParamEnv::reveal_all(),
62-
self.instance,
6362
None,
6463
mir::Field::new(field as usize),
6564
c,

src/librustc_mir/const_eval.rs

+13-65
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ use rustc::hir::{self, def_id::DefId};
1010
use rustc::hir::def::Def;
1111
use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
1212
use rustc::mir;
13-
use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
13+
use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
1414
use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx};
1515
use rustc::ty::subst::Subst;
1616
use rustc::traits::Reveal;
17-
use rustc_data_structures::indexed_vec::IndexVec;
1817
use rustc_data_structures::fx::FxHashMap;
1918
use rustc::util::common::ErrorReported;
2019

@@ -35,54 +34,6 @@ const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
3534
/// Should be a power of two for performance reasons.
3635
const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
3736

38-
/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
39-
/// The `EvalContext` is only meant to be used to query values from constants and statics.
40-
///
41-
/// This function is used during const propagation. We cannot use `mk_eval_cx`, because copy
42-
/// propagation happens *during* the computation of the MIR of the current function. So if we
43-
/// tried to call the `optimized_mir` query, we'd get a cycle error because we are (transitively)
44-
/// inside the `optimized_mir` query of the `Instance` given.
45-
///
46-
/// Since we are looking at the MIR of the function in an abstract manner, we don't have a
47-
/// `ParamEnv` available to us. This function creates a `ParamEnv` for the given instance.
48-
pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
49-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
50-
instance: Instance<'tcx>,
51-
mir: &'mir mir::Mir<'tcx>,
52-
span: Span,
53-
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
54-
debug!("mk_borrowck_eval_cx: {:?}", instance);
55-
let param_env = tcx.param_env(instance.def_id());
56-
mk_eval_cx_inner(tcx, instance, mir, span, param_env)
57-
}
58-
59-
/// This is just a helper function to reduce code duplication between `mk_borrowck_eval_cx` and
60-
/// `mk_eval_cx`. Do not call this function directly.
61-
fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
62-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
63-
instance: Instance<'tcx>,
64-
mir: &'mir mir::Mir<'tcx>,
65-
span: Span,
66-
param_env: ty::ParamEnv<'tcx>,
67-
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
68-
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
69-
// Insert a stack frame so any queries have the correct substs.
70-
// We also avoid all the extra work performed by push_stack_frame,
71-
// like initializing local variables
72-
ecx.stack.push(interpret::Frame {
73-
block: mir::START_BLOCK,
74-
locals: IndexVec::new(),
75-
instance,
76-
span,
77-
mir,
78-
return_place: None,
79-
return_to_block: StackPopCleanup::Goto(None), // never pop
80-
stmt: 0,
81-
extra: (),
82-
});
83-
Ok(ecx)
84-
}
85-
8637
/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
8738
/// The `EvalContext` is only meant to be used to do field and index projections into constants for
8839
/// `simd_shuffle` and const patterns in match arms.
@@ -91,15 +42,13 @@ fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
9142
/// that inform us about the generic bounds of the constant. E.g. using an associated constant
9243
/// of a function's generic parameter will require knowledge about the bounds on the generic
9344
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
94-
fn mk_eval_cx<'a, 'tcx>(
45+
pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>(
9546
tcx: TyCtxt<'a, 'tcx, 'tcx>,
96-
instance: Instance<'tcx>,
47+
span: Span,
9748
param_env: ty::ParamEnv<'tcx>,
98-
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'tcx, 'tcx>> {
99-
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
100-
let span = tcx.def_span(instance.def_id());
101-
let mir = tcx.optimized_mir(instance.def.def_id());
102-
mk_eval_cx_inner(tcx, instance, mir, span, param_env)
49+
) -> CompileTimeEvalContext<'a, 'mir, 'tcx> {
50+
debug!("mk_eval_cx: {:?}", param_env);
51+
EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
10352
}
10453

10554
pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
@@ -108,7 +57,8 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
10857
mir: &'mir mir::Mir<'tcx>,
10958
param_env: ty::ParamEnv<'tcx>,
11059
) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
111-
let mut ecx = mk_borrowck_eval_cx(tcx, cid.instance, mir, DUMMY_SP).unwrap();
60+
let span = tcx.def_span(cid.instance.def_id());
61+
let mut ecx = mk_eval_cx(tcx, span, param_env);
11262
eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
11363
}
11464

@@ -529,13 +479,12 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
529479
pub fn const_field<'a, 'tcx>(
530480
tcx: TyCtxt<'a, 'tcx, 'tcx>,
531481
param_env: ty::ParamEnv<'tcx>,
532-
instance: ty::Instance<'tcx>,
533482
variant: Option<VariantIdx>,
534483
field: mir::Field,
535484
value: ty::Const<'tcx>,
536485
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
537-
trace!("const_field: {:?}, {:?}, {:?}", instance, field, value);
538-
let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
486+
trace!("const_field: {:?}, {:?}", field, value);
487+
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
539488
let result = (|| {
540489
// get the operand again
541490
let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?;
@@ -560,11 +509,10 @@ pub fn const_field<'a, 'tcx>(
560509
pub fn const_variant_index<'a, 'tcx>(
561510
tcx: TyCtxt<'a, 'tcx, 'tcx>,
562511
param_env: ty::ParamEnv<'tcx>,
563-
instance: ty::Instance<'tcx>,
564512
val: ty::Const<'tcx>,
565513
) -> EvalResult<'tcx, VariantIdx> {
566-
trace!("const_variant_index: {:?}, {:?}", instance, val);
567-
let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
514+
trace!("const_variant_index: {:?}", val);
515+
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
568516
let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?;
569517
Ok(ecx.read_discriminant(op)?.1)
570518
}
@@ -584,7 +532,7 @@ fn validate_and_turn_into_const<'a, 'tcx>(
584532
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
585533
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
586534
let cid = key.value;
587-
let ecx = mk_eval_cx(tcx, cid.instance, key.param_env).unwrap();
535+
let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env);
588536
let val = (|| {
589537
let op = ecx.raw_const_to_mplace(constant)?.into();
590538
// FIXME: Once the visitor infrastructure landed, change validation to

src/librustc_mir/hair/pattern/_match.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,24 @@ pub enum Constructor<'tcx> {
427427
}
428428

429429
impl<'tcx> Constructor<'tcx> {
430-
fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
430+
fn variant_index_for_adt<'a>(
431+
&self,
432+
cx: &MatchCheckCtxt<'a, 'tcx>,
433+
adt: &'tcx ty::AdtDef,
434+
) -> VariantIdx {
431435
match self {
432436
&Variant(vid) => adt.variant_index_with_id(vid),
433437
&Single => {
434438
assert!(!adt.is_enum());
435439
VariantIdx::new(0)
436440
}
441+
&ConstantValue(c) => {
442+
::const_eval::const_variant_index(
443+
cx.tcx,
444+
cx.param_env,
445+
c,
446+
).unwrap()
447+
},
437448
_ => bug!("bad constructor {:?} for adt {:?}", self, adt)
438449
}
439450
}
@@ -567,7 +578,7 @@ impl<'tcx> Witness<'tcx> {
567578
PatternKind::Variant {
568579
adt_def: adt,
569580
substs,
570-
variant_index: ctor.variant_index_for_adt(adt),
581+
variant_index: ctor.variant_index_for_adt(cx, adt),
571582
subpatterns: pats
572583
}
573584
} else {
@@ -1329,7 +1340,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
13291340
///
13301341
/// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3.
13311342
/// A struct pattern's arity is the number of fields it contains, etc.
1332-
fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
1343+
fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> u64 {
13331344
debug!("constructor_arity({:#?}, {:?})", ctor, ty);
13341345
match ty.sty {
13351346
ty::Tuple(ref fs) => fs.len() as u64,
@@ -1340,7 +1351,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
13401351
},
13411352
ty::Ref(..) => 1,
13421353
ty::Adt(adt, _) => {
1343-
adt.variants[ctor.variant_index_for_adt(adt)].fields.len() as u64
1354+
adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.len() as u64
13441355
}
13451356
_ => 0
13461357
}
@@ -1351,7 +1362,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
13511362
///
13521363
/// For instance, a tuple pattern (43u32, 'a') has sub pattern types [u32, char].
13531364
fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
1354-
ctor: &Constructor,
1365+
ctor: &Constructor<'tcx>,
13551366
ty: Ty<'tcx>) -> Vec<Ty<'tcx>>
13561367
{
13571368
debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
@@ -1368,7 +1379,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
13681379
// Use T as the sub pattern type of Box<T>.
13691380
vec![substs.type_at(0)]
13701381
} else {
1371-
adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
1382+
adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.iter().map(|field| {
13721383
let is_visible = adt.is_enum()
13731384
|| field.vis.is_accessible_from(cx.module, cx.tcx);
13741385
if is_visible {

src/librustc_mir/hair/pattern/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
885885
let adt_subpattern = |i, variant_opt| {
886886
let field = Field::new(i);
887887
let val = const_field(
888-
self.tcx, self.param_env, instance,
888+
self.tcx, self.param_env,
889889
variant_opt, field, cv,
890890
).expect("field access failed");
891891
self.const_to_pat(instance, val, id, span)
@@ -928,7 +928,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
928928
},
929929
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
930930
let variant_index = const_variant_index(
931-
self.tcx, self.param_env, instance, cv
931+
self.tcx, self.param_env, cv
932932
).expect("const_variant_index failed");
933933
let subpatterns = adt_subpatterns(
934934
adt_def.variants[variant_index].fields.len(),

src/librustc_mir/interpret/cast.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
109109
// The src operand does not matter, just its type
110110
match src.layout.ty.sty {
111111
ty::Closure(def_id, substs) => {
112-
let substs = self.tcx.subst_and_normalize_erasing_regions(
113-
self.substs(),
114-
ty::ParamEnv::reveal_all(),
115-
&substs,
116-
);
112+
let substs = self.subst_and_normalize_erasing_regions(substs)?;
117113
let instance = ty::Instance::resolve_closure(
118114
*self.tcx,
119115
def_id,

src/librustc_mir/interpret/eval_context.rs

+31-11
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,21 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
214214
self.frame().mir
215215
}
216216

217-
pub fn substs(&self) -> &'tcx Substs<'tcx> {
218-
if let Some(frame) = self.stack.last() {
219-
frame.instance.substs
220-
} else {
221-
Substs::empty()
217+
pub(super) fn subst_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
218+
&self,
219+
substs: T,
220+
) -> EvalResult<'tcx, T> {
221+
match self.stack.last() {
222+
Some(frame) => Ok(self.tcx.subst_and_normalize_erasing_regions(
223+
frame.instance.substs,
224+
self.param_env,
225+
&substs,
226+
)),
227+
None => if substs.needs_subst() {
228+
err!(TooGeneric).into()
229+
} else {
230+
Ok(substs)
231+
},
222232
}
223233
}
224234

@@ -228,13 +238,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
228238
substs: &'tcx Substs<'tcx>
229239
) -> EvalResult<'tcx, ty::Instance<'tcx>> {
230240
trace!("resolve: {:?}, {:#?}", def_id, substs);
231-
trace!("substs: {:#?}", self.substs());
232241
trace!("param_env: {:#?}", self.param_env);
233-
let substs = self.tcx.subst_and_normalize_erasing_regions(
234-
self.substs(),
235-
self.param_env,
236-
&substs,
237-
);
242+
let substs = self.subst_and_normalize_erasing_regions(substs)?;
243+
trace!("substs: {:#?}", substs);
238244
ty::Instance::resolve(
239245
*self.tcx,
240246
self.param_env,
@@ -274,6 +280,20 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
274280
}
275281
}
276282

283+
pub fn monomorphize_in_frame<T: TypeFoldable<'tcx> + Subst<'tcx>>(
284+
&self,
285+
t: T,
286+
) -> EvalResult<'tcx, T> {
287+
match self.stack.last() {
288+
Some(frame) => Ok(self.monomorphize(t, frame.instance.substs)),
289+
None => if t.needs_subst() {
290+
err!(TooGeneric).into()
291+
} else {
292+
Ok(t)
293+
},
294+
}
295+
}
296+
277297
pub fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>(
278298
&self,
279299
t: T,

src/librustc_mir/interpret/operand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
514514

515515
Constant(ref constant) => {
516516
let layout = from_known_layout(layout, || {
517-
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
517+
let ty = self.monomorphize_in_frame(mir_op.ty(self.mir(), *self.tcx))?;
518518
self.layout_of(ty)
519519
})?;
520520
let op = self.const_value_to_op(*constant.literal)?;

src/librustc_mir/interpret/place.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc::hir;
99
use rustc::mir;
1010
use rustc::ty::{self, Ty};
1111
use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx};
12+
use rustc::ty::TypeFoldable;
1213

1314
use super::{
1415
GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic,
@@ -583,8 +584,8 @@ where
583584
}
584585

585586
Static(ref static_) => {
586-
let ty = self.monomorphize(static_.ty, self.substs());
587-
let layout = self.layout_of(ty)?;
587+
assert!(!static_.ty.needs_subst());
588+
let layout = self.layout_of(static_.ty)?;
588589
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
589590
let cid = GlobalId {
590591
instance,

src/librustc_mir/interpret/step.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
248248
}
249249

250250
NullaryOp(mir::NullOp::SizeOf, ty) => {
251-
let ty = self.monomorphize(ty, self.substs());
251+
let ty = self.monomorphize_in_frame(ty)?;
252252
let layout = self.layout_of(ty)?;
253253
assert!(!layout.is_unsized(),
254254
"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>
260260
}
261261

262262
Cast(kind, ref operand, cast_ty) => {
263-
debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty);
263+
debug_assert_eq!(self.monomorphize_in_frame(cast_ty)?, dest.layout.ty);
264264
let src = self.eval_operand(operand, None)?;
265265
self.cast(src, kind, dest)?;
266266
}

src/librustc_mir/transform/const_prop.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc::ty::layout::{
2020

2121
use interpret::{self, EvalContext, ScalarMaybeUndef, Immediate, OpTy, MemoryKind};
2222
use const_eval::{
23-
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_borrowck_eval_cx,
23+
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
2424
lazy_const_to_op,
2525
};
2626
use transform::{MirPass, MirSource};
@@ -110,9 +110,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
110110
source: MirSource,
111111
) -> ConstPropagator<'a, 'mir, 'tcx> {
112112
let param_env = tcx.param_env(source.def_id);
113-
let substs = Substs::identity_for_item(tcx, source.def_id);
114-
let instance = Instance::new(source.def_id, substs);
115-
let ecx = mk_borrowck_eval_cx(tcx, instance, mir, DUMMY_SP).unwrap();
113+
let ecx = mk_eval_cx(tcx, tcx.def_span(source.def_id), param_env);
116114
ConstPropagator {
117115
ecx,
118116
mir,

src/test/ui/consts/match_ice.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// https://github.com/rust-lang/rust/issues/53708
2+
3+
struct S;
4+
5+
fn main() {
6+
const C: &S = &S;
7+
match C { //~ ERROR non-exhaustive
8+
C => {} // this is a common bug around constants and references in patterns
9+
}
10+
}

src/test/ui/consts/match_ice.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0004]: non-exhaustive patterns: `&S` not covered
2+
--> $DIR/match_ice.rs:7:11
3+
|
4+
LL | match C { //~ ERROR non-exhaustive
5+
| ^ pattern `&S` not covered
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0004`.

0 commit comments

Comments
 (0)