Skip to content

Commit f9c8a67

Browse files
authored
Rollup merge of #72879 - RalfJung:miri-tctx-at, r=oli-obk
Miri: avoid tracking current location three times Miri tracks the current instruction to execute in the call stack, but it also additionally has two `TyCtxtAt` that carry a `Span` that also tracks the current instruction. That is quite silly, so this PR uses `TyCtxt` instead, and then uses a method for computing the current span when a `TyCtxtAt` is needed. Having less redundant (semi-)global state seems like a good improvement to me. :D To keep the ConstProp errors the same, I had to add the option to `error_to_const_error` to overwrite the span. Also for some reason this changes cycle errors a bit -- not sure if we are now better or worse as giving those queries the right span. (It is unfortunately quite easy to accidentally use `DUMMY_SP` by calling the query on a `TyCtxt` instead of a `TyCtxtAt`.) r? @oli-obk @eddyb
2 parents d97e8ca + 2210abe commit f9c8a67

23 files changed

+141
-123
lines changed

src/librustc_middle/ty/util.rs

+1
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,7 @@ impl<'tcx> ty::TyS<'tcx> {
705705
/// optimization as well as the rules around static values. Note
706706
/// that the `Freeze` trait is not exposed to end users and is
707707
/// effectively an implementation detail.
708+
// FIXME: use `TyCtxtAt` instead of separate `Span`.
708709
pub fn is_freeze(
709710
&'tcx self,
710711
tcx: TyCtxt<'tcx>,

src/librustc_mir/const_eval/error.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::error::Error;
22
use std::fmt;
33

44
use rustc_middle::mir::AssertKind;
5-
use rustc_span::Symbol;
5+
use rustc_span::{Span, Symbol};
66

77
use super::InterpCx;
88
use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine};
@@ -53,8 +53,9 @@ impl Error for ConstEvalErrKind {}
5353
pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>(
5454
ecx: &InterpCx<'mir, 'tcx, M>,
5555
error: InterpErrorInfo<'tcx>,
56+
span: Option<Span>,
5657
) -> ConstEvalErr<'tcx> {
5758
error.print_backtrace();
5859
let stacktrace = ecx.generate_stacktrace();
59-
ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
60+
ConstEvalErr { error: error.kind, stacktrace, span: span.unwrap_or_else(|| ecx.cur_span()) }
6061
}

src/librustc_mir/const_eval/eval_queries.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
2727
body: &'mir mir::Body<'tcx>,
2828
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
2929
debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
30-
let tcx = ecx.tcx.tcx;
30+
let tcx = *ecx.tcx;
3131
let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
3232
assert!(!layout.is_unsized());
3333
let ret = ecx.allocate(layout, MemoryKind::Stack);
@@ -81,13 +81,14 @@ fn eval_body_using_ecx<'mir, 'tcx>(
8181
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
8282
pub(super) fn mk_eval_cx<'mir, 'tcx>(
8383
tcx: TyCtxt<'tcx>,
84-
span: Span,
84+
root_span: Span,
8585
param_env: ty::ParamEnv<'tcx>,
8686
can_access_statics: bool,
8787
) -> CompileTimeEvalContext<'mir, 'tcx> {
8888
debug!("mk_eval_cx: {:?}", param_env);
8989
InterpCx::new(
90-
tcx.at(span),
90+
tcx,
91+
root_span,
9192
param_env,
9293
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
9394
MemoryExtra { can_access_statics },
@@ -163,7 +164,7 @@ pub(super) fn op_to_const<'tcx>(
163164
0,
164165
),
165166
};
166-
let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
167+
let len = b.to_machine_usize(ecx).unwrap();
167168
let start = start.try_into().unwrap();
168169
let len: usize = len.try_into().unwrap();
169170
ConstValue::Slice { data, start, end: start + len }
@@ -212,7 +213,7 @@ fn validate_and_turn_into_const<'tcx>(
212213
})();
213214

214215
val.map_err(|error| {
215-
let err = error_to_const_error(&ecx, error);
216+
let err = error_to_const_error(&ecx, error, None);
216217
err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| {
217218
diag.note(note_on_undefined_behavior_error());
218219
diag.emit();
@@ -299,9 +300,9 @@ pub fn const_eval_raw_provider<'tcx>(
299300

300301
let is_static = tcx.is_static(def_id);
301302

302-
let span = tcx.def_span(cid.instance.def_id());
303303
let mut ecx = InterpCx::new(
304-
tcx.at(span),
304+
tcx,
305+
tcx.def_span(cid.instance.def_id()),
305306
key.param_env,
306307
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
307308
MemoryExtra { can_access_statics: is_static },
@@ -311,12 +312,15 @@ pub fn const_eval_raw_provider<'tcx>(
311312
res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body))
312313
.map(|place| RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, ty: place.layout.ty })
313314
.map_err(|error| {
314-
let err = error_to_const_error(&ecx, error);
315+
let err = error_to_const_error(&ecx, error, None);
315316
// errors in statics are always emitted as fatal errors
316317
if is_static {
317318
// Ensure that if the above error was either `TooGeneric` or `Reported`
318319
// an error must be reported.
319-
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
320+
let v = err.report_as_error(
321+
ecx.tcx.at(ecx.cur_span()),
322+
"could not evaluate static initializer",
323+
);
320324

321325
// If this is `Reveal:All`, then we need to make sure an error is reported but if
322326
// this is `Reveal::UserFacing`, then it's expected that we could get a
@@ -372,13 +376,16 @@ pub fn const_eval_raw_provider<'tcx>(
372376
// anything else (array lengths, enum initializers, constant patterns) are
373377
// reported as hard errors
374378
} else {
375-
err.report_as_error(ecx.tcx, "evaluation of constant value failed")
379+
err.report_as_error(
380+
ecx.tcx.at(ecx.cur_span()),
381+
"evaluation of constant value failed",
382+
)
376383
}
377384
}
378385
}
379386
} else {
380387
// use of broken constant from other crate
381-
err.report_as_error(ecx.tcx, "could not evaluate constant")
388+
err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")
382389
}
383390
})
384391
}

src/librustc_mir/interpret/cast.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
268268
(&ty::Array(_, length), &ty::Slice(_)) => {
269269
let ptr = self.read_immediate(src)?.to_scalar()?;
270270
// u64 cast is from usize to u64, which is always good
271-
let val = Immediate::new_slice(
272-
ptr,
273-
length.eval_usize(self.tcx.tcx, self.param_env),
274-
self,
275-
);
271+
let val =
272+
Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
276273
self.write_immediate(val, dest)
277274
}
278275
(&ty::Dynamic(..), &ty::Dynamic(..)) => {

src/librustc_mir/interpret/eval_context.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
3333
pub machine: M,
3434

3535
/// The results of the type checker, from rustc.
36+
/// The span in this is the "root" of the evaluation, i.e., the const
37+
/// we are evaluating (if this is CTFE).
3638
pub tcx: TyCtxtAt<'tcx>,
3739

3840
/// Bounds in scope for polymorphic evaluations.
@@ -202,7 +204,7 @@ where
202204
}
203205
}
204206

205-
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
207+
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
206208
type Ty = Ty<'tcx>;
207209
type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>;
208210

@@ -285,24 +287,28 @@ pub(super) fn from_known_layout<'tcx>(
285287

286288
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
287289
pub fn new(
288-
tcx: TyCtxtAt<'tcx>,
290+
tcx: TyCtxt<'tcx>,
291+
root_span: Span,
289292
param_env: ty::ParamEnv<'tcx>,
290293
machine: M,
291294
memory_extra: M::MemoryExtra,
292295
) -> Self {
293296
InterpCx {
294297
machine,
295-
tcx,
298+
tcx: tcx.at(root_span),
296299
param_env,
297300
memory: Memory::new(tcx, memory_extra),
298301
vtables: FxHashMap::default(),
299302
}
300303
}
301304

302305
#[inline(always)]
303-
pub fn set_span(&mut self, span: Span) {
304-
self.tcx.span = span;
305-
self.memory.tcx.span = span;
306+
pub fn cur_span(&self) -> Span {
307+
self.stack()
308+
.last()
309+
.and_then(|f| f.current_source_info())
310+
.map(|si| si.span)
311+
.unwrap_or(self.tcx.span)
306312
}
307313

308314
#[inline(always)]
@@ -385,7 +391,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
385391

386392
#[inline]
387393
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
388-
ty.is_freeze(*self.tcx, self.param_env, DUMMY_SP)
394+
ty.is_freeze(*self.tcx, self.param_env, self.tcx.span)
389395
}
390396

391397
pub fn load_mir(
@@ -554,7 +560,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
554560
let size = size.align_to(align);
555561

556562
// Check if this brought us over the size limit.
557-
if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
563+
if size.bytes() >= self.tcx.data_layout.obj_size_bound() {
558564
throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
559565
}
560566
Ok(Some((size, align)))
@@ -570,7 +576,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
570576
let elem = layout.field(self, 0)?;
571577

572578
// Make sure the slice is not too big.
573-
let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| {
579+
let size = elem.size.checked_mul(len, self).ok_or_else(|| {
574580
err_ub!(InvalidMeta("slice is bigger than largest supported object"))
575581
})?;
576582
Ok(Some((size, elem.align.abi)))

src/librustc_mir/interpret/intern.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
111111
if let InternMode::Static(mutability) = mode {
112112
// For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
113113
// no interior mutability.
114-
let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx.tcx, ecx.param_env, ecx.tcx.span));
114+
let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env, ecx.tcx.span));
115115
// For statics, allocation mutability is the combination of the place mutability and
116116
// the type mutability.
117117
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
@@ -253,8 +253,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
253253
// caused (by somehow getting a mutable reference in a `const`).
254254
if ref_mutability == Mutability::Mut {
255255
match referenced_ty.kind {
256-
ty::Array(_, n)
257-
if n.eval_usize(tcx.tcx, self.ecx.param_env) == 0 => {}
256+
ty::Array(_, n) if n.eval_usize(*tcx, self.ecx.param_env) == 0 => {}
258257
ty::Slice(_)
259258
if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)?
260259
== 0 => {}

src/librustc_mir/interpret/intrinsics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
347347
let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
348348
let elem = args[2];
349349
let input = args[0];
350-
let (len, e_ty) = input.layout.ty.simd_size_and_type(self.tcx.tcx);
350+
let (len, e_ty) = input.layout.ty.simd_size_and_type(*self.tcx);
351351
assert!(
352352
index < len,
353353
"Index `{}` must be in bounds of vector type `{}`: `[0, {})`",
@@ -374,7 +374,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
374374
}
375375
sym::simd_extract => {
376376
let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
377-
let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx.tcx);
377+
let (len, e_ty) = args[0].layout.ty.simd_size_and_type(*self.tcx);
378378
assert!(
379379
index < len,
380380
"index `{}` is out-of-bounds of vector type `{}` with length `{}`",

src/librustc_mir/interpret/memory.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::ptr;
1414

1515
use rustc_ast::ast::Mutability;
1616
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
17-
use rustc_middle::ty::{self, query::TyCtxtAt, Instance, ParamEnv};
17+
use rustc_middle::ty::{self, Instance, ParamEnv, TyCtxt};
1818
use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
1919

2020
use super::{
@@ -115,7 +115,7 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
115115
pub extra: M::MemoryExtra,
116116

117117
/// Lets us implement `HasDataLayout`, which is awfully convenient.
118-
pub tcx: TyCtxtAt<'tcx>,
118+
pub tcx: TyCtxt<'tcx>,
119119
}
120120

121121
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> {
@@ -126,7 +126,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>
126126
}
127127

128128
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
129-
pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self {
129+
pub fn new(tcx: TyCtxt<'tcx>, extra: M::MemoryExtra) -> Self {
130130
Memory {
131131
alloc_map: M::MemoryMap::default(),
132132
extra_fn_ptr_map: FxHashMap::default(),
@@ -425,7 +425,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
425425
/// `M::tag_allocation`.
426426
fn get_global_alloc(
427427
memory_extra: &M::MemoryExtra,
428-
tcx: TyCtxtAt<'tcx>,
428+
tcx: TyCtxt<'tcx>,
429429
id: AllocId,
430430
is_write: bool,
431431
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>> {
@@ -455,7 +455,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
455455
throw_unsup!(ReadForeignStatic(def_id))
456456
}
457457
trace!("get_global_alloc: Need to compute {:?}", def_id);
458-
let instance = Instance::mono(tcx.tcx, def_id);
458+
let instance = Instance::mono(tcx, def_id);
459459
let gid = GlobalId { instance, promoted: None };
460460
// Use the raw query here to break validation cycles. Later uses of the static
461461
// will call the full query anyway.
@@ -664,14 +664,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
664664
pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
665665
// Cannot be a closure because it is generic in `Tag`, `Extra`.
666666
fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>(
667-
tcx: TyCtxtAt<'tcx>,
667+
tcx: TyCtxt<'tcx>,
668668
allocs_to_print: &mut VecDeque<AllocId>,
669669
alloc: &Allocation<Tag, Extra>,
670670
) {
671671
for &(_, target_id) in alloc.relocations().values() {
672672
allocs_to_print.push_back(target_id);
673673
}
674-
pretty::write_allocation(tcx.tcx, alloc, &mut std::io::stderr()).unwrap();
674+
pretty::write_allocation(tcx, alloc, &mut std::io::stderr()).unwrap();
675675
}
676676

677677
allocs.sort();
@@ -820,7 +820,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
820820
return Ok(());
821821
}
822822
};
823-
let tcx = self.tcx.tcx;
823+
let tcx = self.tcx;
824824
self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
825825
}
826826

@@ -846,7 +846,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
846846
return Ok(());
847847
}
848848
};
849-
let tcx = self.tcx.tcx;
849+
let tcx = self.tcx;
850850
let allocation = self.get_raw_mut(ptr.alloc_id)?;
851851

852852
for idx in 0..len {
@@ -888,7 +888,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
888888
let relocations =
889889
self.get_raw(src.alloc_id)?.prepare_relocation_copy(self, src, size, dest, length);
890890

891-
let tcx = self.tcx.tcx;
891+
let tcx = self.tcx;
892892

893893
// This checks relocation edges on the src.
894894
let src_bytes =

src/librustc_mir/interpret/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -651,12 +651,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
651651
// Convert discriminant to variant index, and catch invalid discriminants.
652652
let index = match op.layout.ty.kind {
653653
ty::Adt(adt, _) => {
654-
adt.discriminants(self.tcx.tcx).find(|(_, var)| var.val == discr_bits)
654+
adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
655655
}
656656
ty::Generator(def_id, substs, _) => {
657657
let substs = substs.as_generator();
658658
substs
659-
.discriminants(def_id, self.tcx.tcx)
659+
.discriminants(def_id, *self.tcx)
660660
.find(|(_, var)| var.val == discr_bits)
661661
}
662662
_ => bug!("tagged layout for non-adt non-generator"),

0 commit comments

Comments
 (0)