Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 15a4f0a

Browse files
saethlinRalfJung
authored andcommitted
some CurrentSpan cleanup
1 parent 17fc52a commit 15a4f0a

File tree

3 files changed

+76
-58
lines changed

3 files changed

+76
-58
lines changed

src/helpers.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
877877

878878
impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
879879
pub fn current_span(&self, tcx: TyCtxt<'tcx>) -> CurrentSpan<'_, 'mir, 'tcx> {
880-
CurrentSpan { span: None, machine: self, tcx }
880+
CurrentSpan { current_frame_idx: None, machine: self, tcx }
881881
}
882882
}
883883

@@ -887,7 +887,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
887887
/// The result of that search is cached so that later calls are approximately free.
888888
#[derive(Clone)]
889889
pub struct CurrentSpan<'a, 'mir, 'tcx> {
890-
span: Option<Span>,
890+
current_frame_idx: Option<usize>,
891891
tcx: TyCtxt<'tcx>,
892892
machine: &'a Evaluator<'mir, 'tcx>,
893893
}
@@ -896,25 +896,19 @@ impl<'a, 'mir: 'a, 'tcx: 'a + 'mir> CurrentSpan<'a, 'mir, 'tcx> {
896896
/// Get the current span, skipping non-local frames.
897897
/// This function is backed by a cache, and can be assumed to be very fast.
898898
pub fn get(&mut self) -> Span {
899-
*self.span.get_or_insert_with(|| Self::current_span(self.tcx, self.machine))
899+
let idx = self.current_frame_idx();
900+
Self::frame_span(self.machine, idx)
900901
}
901902

902903
/// Similar to `CurrentSpan::get`, but retrieves the parent frame of the first non-local frame.
903904
/// This is useful when we are processing something which occurs on function-entry and we want
904905
/// to point at the call to the function, not the function definition generally.
905-
#[inline(never)]
906906
pub fn get_parent(&mut self) -> Span {
907-
let idx = Self::current_span_index(self.tcx, self.machine);
908-
Self::nth_span(self.machine, idx.wrapping_sub(1))
909-
}
910-
911-
#[inline(never)]
912-
fn current_span(tcx: TyCtxt<'_>, machine: &Evaluator<'_, '_>) -> Span {
913-
let idx = Self::current_span_index(tcx, machine);
914-
Self::nth_span(machine, idx)
907+
let idx = self.current_frame_idx();
908+
Self::frame_span(self.machine, idx.wrapping_sub(1))
915909
}
916910

917-
fn nth_span(machine: &Evaluator<'_, '_>, idx: usize) -> Span {
911+
fn frame_span(machine: &Evaluator<'_, '_>, idx: usize) -> Span {
918912
machine
919913
.threads
920914
.active_thread_stack()
@@ -923,9 +917,16 @@ impl<'a, 'mir: 'a, 'tcx: 'a + 'mir> CurrentSpan<'a, 'mir, 'tcx> {
923917
.unwrap_or(rustc_span::DUMMY_SP)
924918
}
925919

920+
fn current_frame_idx(&mut self) -> usize {
921+
*self
922+
.current_frame_idx
923+
.get_or_insert_with(|| Self::compute_current_frame_index(self.tcx, self.machine))
924+
}
925+
926926
// Find the position of the inner-most frame which is part of the crate being
927927
// compiled/executed, part of the Cargo workspace, and is also not #[track_caller].
928-
fn current_span_index(tcx: TyCtxt<'_>, machine: &Evaluator<'_, '_>) -> usize {
928+
#[inline(never)]
929+
fn compute_current_frame_index(tcx: TyCtxt<'_>, machine: &Evaluator<'_, '_>) -> usize {
929930
machine
930931
.threads
931932
.active_thread_stack()

src/stacked_borrows/diagnostics.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,26 +103,30 @@ pub struct TagHistory {
103103
pub protected: Option<([(String, SpanData); 2])>,
104104
}
105105

106-
pub struct DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
106+
pub struct DiagnosticCxBuilder<'span, 'ecx, 'mir, 'tcx> {
107107
operation: Operation,
108-
current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
108+
// 'span cannot be merged with any other lifetime since they appear invariantly, under the
109+
// mutable ref.
110+
current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
109111
threads: &'ecx ThreadManager<'mir, 'tcx>,
110112
}
111113

112-
pub struct DiagnosticCx<'ecx, 'mir, 'tcx, 'history> {
114+
pub struct DiagnosticCx<'span, 'history, 'ecx, 'mir, 'tcx> {
113115
operation: Operation,
114-
current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
116+
// 'span and 'history cannot be merged, since when we call `unbuild` we need
117+
// to return the exact 'span that was used when calling `build`.
118+
current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
115119
threads: &'ecx ThreadManager<'mir, 'tcx>,
116120
history: &'history mut AllocHistory,
117121
offset: Size,
118122
}
119123

120-
impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
121-
pub fn build(
124+
impl<'span, 'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'span, 'ecx, 'mir, 'tcx> {
125+
pub fn build<'history>(
122126
self,
123127
history: &'history mut AllocHistory,
124128
offset: Size,
125-
) -> DiagnosticCx<'ecx, 'mir, 'tcx, 'history> {
129+
) -> DiagnosticCx<'span, 'history, 'ecx, 'mir, 'tcx> {
126130
DiagnosticCx {
127131
operation: self.operation,
128132
current_span: self.current_span,
@@ -133,7 +137,7 @@ impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
133137
}
134138

135139
pub fn retag(
136-
current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
140+
current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
137141
threads: &'ecx ThreadManager<'mir, 'tcx>,
138142
cause: RetagCause,
139143
new_tag: SbTag,
@@ -147,7 +151,7 @@ impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
147151
}
148152

149153
pub fn read(
150-
current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
154+
current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
151155
threads: &'ecx ThreadManager<'mir, 'tcx>,
152156
tag: ProvenanceExtra,
153157
range: AllocRange,
@@ -157,7 +161,7 @@ impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
157161
}
158162

159163
pub fn write(
160-
current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
164+
current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
161165
threads: &'ecx ThreadManager<'mir, 'tcx>,
162166
tag: ProvenanceExtra,
163167
range: AllocRange,
@@ -167,7 +171,7 @@ impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
167171
}
168172

169173
pub fn dealloc(
170-
current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
174+
current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
171175
threads: &'ecx ThreadManager<'mir, 'tcx>,
172176
tag: ProvenanceExtra,
173177
) -> Self {
@@ -176,8 +180,8 @@ impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
176180
}
177181
}
178182

179-
impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCx<'ecx, 'mir, 'tcx, 'history> {
180-
pub fn unbuild(self) -> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
183+
impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir, 'tcx> {
184+
pub fn unbuild(self) -> DiagnosticCxBuilder<'span, 'ecx, 'mir, 'tcx> {
181185
DiagnosticCxBuilder {
182186
operation: self.operation,
183187
current_span: self.current_span,
@@ -233,7 +237,7 @@ impl AllocHistory {
233237
}
234238
}
235239

236-
impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCx<'ecx, 'mir, 'tcx, 'history> {
240+
impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir, 'tcx> {
237241
pub fn start_grant(&mut self, perm: Permission) {
238242
let Operation::Retag(op) = &mut self.operation else {
239243
unreachable!("start_grant must only be called during a retag, this is: {:?}", self.operation)
@@ -247,6 +251,7 @@ impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCx<'ecx, 'mir, 'tcx, 'history> {
247251
}
248252
Some(previous) =>
249253
if previous != perm {
254+
// 'Split up' the creation event.
250255
let previous_range = last_creation.retag.range;
251256
last_creation.retag.range = alloc_range(previous_range.start, self.offset);
252257
let mut new_event = last_creation.clone();

src/stacked_borrows/mod.rs

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ impl<'tcx> Stack {
286286
fn item_popped(
287287
item: &Item,
288288
global: &GlobalStateInner,
289-
dcx: &mut DiagnosticCx<'_, '_, 'tcx, '_>,
289+
dcx: &mut DiagnosticCx<'_, '_, '_, '_, 'tcx>,
290290
) -> InterpResult<'tcx> {
291291
if !global.tracked_pointer_tags.is_empty() {
292292
dcx.check_tracked_tag_popped(item, global);
@@ -324,7 +324,7 @@ impl<'tcx> Stack {
324324
access: AccessKind,
325325
tag: ProvenanceExtra,
326326
global: &mut GlobalStateInner,
327-
dcx: &mut DiagnosticCx<'_, '_, 'tcx, '_>,
327+
dcx: &mut DiagnosticCx<'_, '_, '_, '_, 'tcx>,
328328
exposed_tags: &FxHashSet<SbTag>,
329329
) -> InterpResult<'tcx> {
330330
// Two main steps: Find granting item, remove incompatible items above.
@@ -410,7 +410,7 @@ impl<'tcx> Stack {
410410
&mut self,
411411
tag: ProvenanceExtra,
412412
global: &GlobalStateInner,
413-
dcx: &mut DiagnosticCx<'_, '_, 'tcx, '_>,
413+
dcx: &mut DiagnosticCx<'_, '_, '_, '_, 'tcx>,
414414
exposed_tags: &FxHashSet<SbTag>,
415415
) -> InterpResult<'tcx> {
416416
// Step 1: Make sure there is a granting item.
@@ -436,7 +436,7 @@ impl<'tcx> Stack {
436436
derived_from: ProvenanceExtra,
437437
new: Item,
438438
global: &mut GlobalStateInner,
439-
dcx: &mut DiagnosticCx<'_, '_, 'tcx, '_>,
439+
dcx: &mut DiagnosticCx<'_, '_, '_, '_, 'tcx>,
440440
exposed_tags: &FxHashSet<SbTag>,
441441
) -> InterpResult<'tcx> {
442442
dcx.start_grant(new.perm());
@@ -515,10 +515,10 @@ impl<'tcx> Stacks {
515515
fn for_each(
516516
&mut self,
517517
range: AllocRange,
518-
mut dcx_builder: DiagnosticCxBuilder<'_, '_, 'tcx>,
518+
mut dcx_builder: DiagnosticCxBuilder<'_, '_, '_, 'tcx>,
519519
mut f: impl FnMut(
520520
&mut Stack,
521-
&mut DiagnosticCx<'_, '_, 'tcx, '_>,
521+
&mut DiagnosticCx<'_, '_, '_, '_, 'tcx>,
522522
&mut FxHashSet<SbTag>,
523523
) -> InterpResult<'tcx>,
524524
) -> InterpResult<'tcx> {
@@ -554,63 +554,66 @@ impl Stacks {
554554
}
555555

556556
#[inline(always)]
557-
pub fn before_memory_read<'tcx, 'mir>(
557+
pub fn before_memory_read<'tcx, 'mir, 'ecx>(
558558
&mut self,
559559
alloc_id: AllocId,
560560
tag: ProvenanceExtra,
561561
range: AllocRange,
562562
state: &GlobalState,
563-
current_span: CurrentSpan<'_, 'mir, 'tcx>,
564-
threads: &ThreadManager<'mir, 'tcx>,
565-
) -> InterpResult<'tcx> {
563+
mut current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
564+
threads: &'ecx ThreadManager<'mir, 'tcx>,
565+
) -> InterpResult<'tcx>
566+
where
567+
'tcx: 'ecx,
568+
{
566569
trace!(
567570
"read access with tag {:?}: {:?}, size {}",
568571
tag,
569572
Pointer::new(alloc_id, range.start),
570573
range.size.bytes()
571574
);
572-
let dcx = DiagnosticCxBuilder::read(current_span, threads, tag, range);
575+
let dcx = DiagnosticCxBuilder::read(&mut current_span, threads, tag, range);
573576
let mut state = state.borrow_mut();
574577
self.for_each(range, dcx, |stack, dcx, exposed_tags| {
575578
stack.access(AccessKind::Read, tag, &mut state, dcx, exposed_tags)
576579
})
577580
}
578581

579582
#[inline(always)]
580-
pub fn before_memory_write<'tcx, 'mir>(
583+
pub fn before_memory_write<'tcx, 'mir, 'ecx>(
581584
&mut self,
582585
alloc_id: AllocId,
583586
tag: ProvenanceExtra,
584587
range: AllocRange,
585588
state: &GlobalState,
586-
current_span: CurrentSpan<'_, 'mir, 'tcx>,
587-
threads: &ThreadManager<'mir, 'tcx>,
589+
mut current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
590+
threads: &'ecx ThreadManager<'mir, 'tcx>,
588591
) -> InterpResult<'tcx> {
589592
trace!(
590593
"write access with tag {:?}: {:?}, size {}",
591594
tag,
592595
Pointer::new(alloc_id, range.start),
593596
range.size.bytes()
594597
);
595-
let dcx = DiagnosticCxBuilder::write(current_span, threads, tag, range);
598+
let dcx = DiagnosticCxBuilder::write(&mut current_span, threads, tag, range);
596599
let mut state = state.borrow_mut();
597600
self.for_each(range, dcx, |stack, dcx, exposed_tags| {
598601
stack.access(AccessKind::Write, tag, &mut state, dcx, exposed_tags)
599602
})
600603
}
601604

602605
#[inline(always)]
603-
pub fn before_memory_deallocation<'tcx, 'mir>(
606+
pub fn before_memory_deallocation<'tcx, 'mir, 'ecx>(
604607
&mut self,
605608
alloc_id: AllocId,
606609
tag: ProvenanceExtra,
607610
range: AllocRange,
608611
state: &GlobalState,
609-
current_span: CurrentSpan<'_, 'mir, 'tcx>,
610-
threads: &ThreadManager<'mir, 'tcx>,
612+
mut current_span: CurrentSpan<'ecx, 'mir, 'tcx>,
613+
threads: &'ecx ThreadManager<'mir, 'tcx>,
611614
) -> InterpResult<'tcx> {
612615
trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, range.size.bytes());
613-
let dcx = DiagnosticCxBuilder::dealloc(current_span, threads, tag);
616+
let dcx = DiagnosticCxBuilder::dealloc(&mut current_span, threads, tag);
614617
let state = state.borrow();
615618
self.for_each(range, dcx, |stack, dcx, exposed_tags| {
616619
stack.dealloc(tag, &state, dcx, exposed_tags)
@@ -621,8 +624,11 @@ impl Stacks {
621624

622625
/// Retagging/reborrowing. There is some policy in here, such as which permissions
623626
/// to grant for which references, and when to add protectors.
624-
impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
625-
trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
627+
impl<'mir: 'ecx, 'tcx: 'mir, 'ecx> EvalContextPrivExt<'mir, 'tcx, 'ecx>
628+
for crate::MiriEvalContext<'mir, 'tcx>
629+
{
630+
}
631+
trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriEvalContextExt<'mir, 'tcx> {
626632
/// Returns the `AllocId` the reborrow was done in, if some actual borrow stack manipulation
627633
/// happened.
628634
fn reborrow(
@@ -635,11 +641,9 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
635641
protect: bool,
636642
) -> InterpResult<'tcx, Option<AllocId>> {
637643
let this = self.eval_context_mut();
638-
let current_span = this.machine.current_span(*this.tcx);
639644

640645
// It is crucial that this gets called on all code paths, to ensure we track tag creation.
641646
let log_creation = |this: &MiriEvalContext<'mir, 'tcx>,
642-
current_span: CurrentSpan<'_, 'mir, 'tcx>,
643647
loc: Option<(AllocId, Size, ProvenanceExtra)>| // alloc_id, base_offset, orig_tag
644648
-> InterpResult<'tcx> {
645649
let global = this.machine.stacked_borrows.as_ref().unwrap().borrow();
@@ -658,6 +662,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
658662
let (_size, _align, alloc_kind) = this.get_alloc_info(alloc_id);
659663
match alloc_kind {
660664
AllocKind::LiveData => {
665+
let current_span = &mut this.machine.current_span(*this.tcx);
661666
// This should have alloc_extra data, but `get_alloc_extra` can still fail
662667
// if converting this alloc_id from a global to a local one
663668
// uncovers a non-supported `extern static`.
@@ -667,9 +672,12 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
667672
.as_ref()
668673
.expect("we should have Stacked Borrows data")
669674
.borrow_mut();
670-
let dcx = DiagnosticCxBuilder::retag(
675+
let threads = &this.machine.threads;
676+
// Note that we create a *second* `DiagnosticCxBuilder` below for the actual retag.
677+
// FIXME: can this be done cleaner?
678+
let dcx = DiagnosticCxBuilder::retag(
671679
current_span,
672-
&this.machine.threads,
680+
threads,
673681
retag_cause,
674682
new_tag,
675683
orig_tag,
@@ -704,16 +712,16 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
704712
// Dangling slices are a common case here; it's valid to get their length but with raw
705713
// pointer tagging for example all calls to get_unchecked on them are invalid.
706714
if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr) {
707-
log_creation(this, current_span, Some((alloc_id, base_offset, orig_tag)))?;
715+
log_creation(this, Some((alloc_id, base_offset, orig_tag)))?;
708716
return Ok(Some(alloc_id));
709717
}
710718
// This pointer doesn't come with an AllocId. :shrug:
711-
log_creation(this, current_span, None)?;
719+
log_creation(this, None)?;
712720
return Ok(None);
713721
}
714722

715723
let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr)?;
716-
log_creation(this, current_span, Some((alloc_id, base_offset, orig_tag)))?;
724+
log_creation(this, Some((alloc_id, base_offset, orig_tag)))?;
717725

718726
// Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
719727
let (alloc_size, _) = this.get_live_alloc_size_and_align(alloc_id)?;
@@ -770,6 +778,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
770778
.as_ref()
771779
.expect("we should have Stacked Borrows data")
772780
.borrow_mut();
781+
// FIXME: can't share this with the current_span inside log_creation
782+
let mut current_span = this.machine.current_span(*this.tcx);
773783
this.visit_freeze_sensitive(place, size, |mut range, frozen| {
774784
// Adjust range.
775785
range.start += base_offset;
@@ -789,7 +799,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
789799
let item = Item::new(new_tag, perm, protected);
790800
let mut global = this.machine.stacked_borrows.as_ref().unwrap().borrow_mut();
791801
let dcx = DiagnosticCxBuilder::retag(
792-
this.machine.current_span(*this.tcx),
802+
&mut current_span, // FIXME avoid this `clone`
793803
&this.machine.threads,
794804
retag_cause,
795805
new_tag,
@@ -817,8 +827,10 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
817827
let item = Item::new(new_tag, perm, protect);
818828
let range = alloc_range(base_offset, size);
819829
let mut global = machine.stacked_borrows.as_ref().unwrap().borrow_mut();
830+
// FIXME: can't share this with the current_span inside log_creation
831+
let current_span = &mut machine.current_span(tcx);
820832
let dcx = DiagnosticCxBuilder::retag(
821-
machine.current_span(tcx), // `get_alloc_extra_mut` invalidated our old `current_span`
833+
current_span,
822834
&machine.threads,
823835
retag_cause,
824836
new_tag,

0 commit comments

Comments
 (0)