diff --git a/src/diagnostics.rs b/src/diagnostics.rs index a378df0ad82b..eafe56955d1f 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -178,20 +178,15 @@ pub fn report_error<'tcx, 'mir>( (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental")), (None, format!("see {url} for further information")), ]; - match history { - Some(TagHistory::Tagged {tag, created: (created_range, created_span), invalidated, protected }) => { - let msg = format!("{tag:?} was created by a retag at offsets {created_range:?}"); - helps.push((Some(*created_span), msg)); - if let Some((invalidated_range, invalidated_span)) = invalidated { - let msg = format!("{tag:?} was later invalidated at offsets {invalidated_range:?}"); - helps.push((Some(*invalidated_span), msg)); - } - if let Some((protecting_tag, protecting_tag_span, protection_span)) = protected { - helps.push((Some(*protecting_tag_span), format!("{tag:?} was protected due to {protecting_tag:?} which was created here"))); - helps.push((Some(*protection_span), format!("this protector is live for this call"))); - } + if let Some(TagHistory {created, invalidated, protected}) = history.clone() { + helps.push((Some(created.1), created.0)); + if let Some((msg, span)) = invalidated { + helps.push((Some(span), msg)); + } + if let Some([(protector_msg, protector_span), (protection_msg, protection_span)]) = protected { + helps.push((Some(protector_span), protector_msg)); + helps.push((Some(protection_span), protection_msg)); } - None => {} } helps } diff --git a/src/helpers.rs b/src/helpers.rs index d63bf97ad51d..6f6cbcc38a77 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -876,8 +876,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } impl<'mir, 'tcx> Evaluator<'mir, 'tcx> { - pub fn current_span(&self) -> CurrentSpan<'_, 'mir, 'tcx> { - CurrentSpan { span: None, machine: self } + pub fn current_span(&self, tcx: TyCtxt<'tcx>) -> CurrentSpan<'_, 'mir, 'tcx> { + CurrentSpan { span: None, machine: self, tcx } } } @@ -888,27 +888,61 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> { #[derive(Clone)] pub struct CurrentSpan<'a, 'mir, 'tcx> { span: Option, + tcx: TyCtxt<'tcx>, machine: &'a Evaluator<'mir, 'tcx>, } -impl<'a, 'mir, 'tcx> CurrentSpan<'a, 'mir, 'tcx> { +impl<'a, 'mir: 'a, 'tcx: 'a + 'mir> CurrentSpan<'a, 'mir, 'tcx> { + /// Get the current span, skipping non-local frames. + /// This function is backed by a cache, and can be assumed to be very fast. pub fn get(&mut self) -> Span { - *self.span.get_or_insert_with(|| Self::current_span(self.machine)) + *self.span.get_or_insert_with(|| Self::current_span(self.tcx, self.machine)) + } + + /// Similar to `CurrentSpan::get`, but retrieves the parent frame of the first non-local frame. + /// This is useful when we are processing something which occurs on function-entry and we want + /// to point at the call to the function, not the function definition generally. + #[inline(never)] + pub fn get_parent(&mut self) -> Span { + let idx = Self::current_span_index(self.tcx, self.machine); + Self::nth_span(self.machine, idx.wrapping_sub(1)) } #[inline(never)] - fn current_span(machine: &Evaluator<'_, '_>) -> Span { + fn current_span(tcx: TyCtxt<'_>, machine: &Evaluator<'_, '_>) -> Span { + let idx = Self::current_span_index(tcx, machine); + Self::nth_span(machine, idx) + } + + fn nth_span(machine: &Evaluator<'_, '_>, idx: usize) -> Span { + machine + .threads + .active_thread_stack() + .get(idx) + .map(Frame::current_span) + .unwrap_or(rustc_span::DUMMY_SP) + } + + // Find the position of the inner-most frame which is part of the crate being + // compiled/executed, part of the Cargo workspace, and is also not #[track_caller]. + fn current_span_index(tcx: TyCtxt<'_>, machine: &Evaluator<'_, '_>) -> usize { machine .threads .active_thread_stack() .iter() + .enumerate() .rev() - .find(|frame| { + .find_map(|(idx, frame)| { let def_id = frame.instance.def_id(); - def_id.is_local() || machine.local_crates.contains(&def_id.krate) + if (def_id.is_local() || machine.local_crates.contains(&def_id.krate)) + && !frame.instance.def.requires_caller_location(tcx) + { + Some(idx) + } else { + None + } }) - .map(|frame| frame.current_span()) - .unwrap_or(rustc_span::DUMMY_SP) + .unwrap_or(0) } } diff --git a/src/machine.rs b/src/machine.rs index 4dc091606739..7357731f3592 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -137,7 +137,7 @@ pub enum Provenance { } /// The "extra" information a pointer has over a regular AllocId. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq)] pub enum ProvenanceExtra { Concrete(SbTag), Wildcard, @@ -706,15 +706,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { } let alloc = alloc.into_owned(); - let stacks = ecx.machine.stacked_borrows.as_ref().map(|stacked_borrows| { - Stacks::new_allocation( - id, - alloc.size(), - stacked_borrows, - kind, - ecx.machine.current_span(), - ) - }); + let stacks = + ecx.machine.stacked_borrows.as_ref().map(|stacked_borrows| { + Stacks::new_allocation(id, alloc.size(), stacked_borrows, kind) + }); let race_alloc = ecx.machine.data_race.as_ref().map(|data_race| { data_race::AllocExtra::new_allocation( data_race, @@ -808,7 +803,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { #[inline(always)] fn before_memory_read( - _tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, machine: &Self, alloc_extra: &AllocExtra, (alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra), @@ -828,7 +823,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { prov_extra, range, machine.stacked_borrows.as_ref().unwrap(), - machine.current_span(), + machine.current_span(tcx), &machine.threads, )?; } @@ -840,7 +835,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { #[inline(always)] fn before_memory_write( - _tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra, (alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra), @@ -860,7 +855,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { prov_extra, range, machine.stacked_borrows.as_ref().unwrap(), - machine.current_span(), + machine.current_span(tcx), &machine.threads, )?; } @@ -872,7 +867,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { #[inline(always)] fn before_memory_deallocation( - _tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra, (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra), @@ -895,6 +890,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { prove_extra, range, machine.stacked_borrows.as_ref().unwrap(), + machine.current_span(tcx), &machine.threads, ) } else { diff --git a/src/stacked_borrows/diagnostics.rs b/src/stacked_borrows/diagnostics.rs index 6521f0772112..ac2783670cff 100644 --- a/src/stacked_borrows/diagnostics.rs +++ b/src/stacked_borrows/diagnostics.rs @@ -1,91 +1,294 @@ use smallvec::SmallVec; +use std::fmt; -use rustc_middle::mir::interpret::{AllocId, AllocRange}; +use rustc_middle::mir::interpret::{alloc_range, AllocId, AllocRange}; use rustc_span::{Span, SpanData}; use rustc_target::abi::Size; use crate::helpers::CurrentSpan; -use crate::stacked_borrows::{err_sb_ub, AccessKind}; +use crate::stacked_borrows::{err_sb_ub, AccessKind, GlobalStateInner, Permission}; use crate::*; use rustc_middle::mir::interpret::InterpError; #[derive(Clone, Debug)] pub struct AllocHistory { - // The time tags can be compressed down to one bit per event, by just storing a Vec - // where each bit is set to indicate if the event was a creation or a retag - current_time: usize, - creations: smallvec::SmallVec<[Event; 2]>, - invalidations: smallvec::SmallVec<[Event; 1]>, + id: AllocId, + creations: smallvec::SmallVec<[Creation; 1]>, + invalidations: smallvec::SmallVec<[Invalidation; 1]>, protectors: smallvec::SmallVec<[Protection; 1]>, } #[derive(Clone, Debug)] -struct Protection { - orig_tag: SbTag, - tag: SbTag, +struct Creation { + retag: RetagOp, span: Span, } +impl Creation { + fn generate_diagnostic(&self) -> (String, SpanData) { + let tag = self.retag.new_tag; + if let Some(perm) = self.retag.permission { + ( + format!( + "{tag:?} was created by a {:?} retag at offsets {:?}", + perm, self.retag.range, + ), + self.span.data(), + ) + } else { + assert!(self.retag.range.size == Size::ZERO); + ( + format!( + "{tag:?} would have been created here, but this is a zero-size retag ({:?}) so the tag in question does not exist anywhere", + self.retag.range, + ), + self.span.data(), + ) + } + } +} + #[derive(Clone, Debug)] -struct Event { - parent: Option, +struct Invalidation { tag: SbTag, range: AllocRange, span: Span, + cause: InvalidationCause, } -pub enum TagHistory { - Tagged { - tag: SbTag, - created: (AllocRange, SpanData), - invalidated: Option<(AllocRange, SpanData)>, - protected: Option<(SbTag, SpanData, SpanData)>, - }, +#[derive(Clone, Debug)] +enum InvalidationCause { + Access(AccessKind), + Retag(Permission, RetagCause), +} + +impl Invalidation { + fn generate_diagnostic(&self) -> (String, SpanData) { + ( + format!( + "{:?} was later invalidated at offsets {:?} by a {}", + self.tag, self.range, self.cause + ), + self.span.data(), + ) + } +} + +impl fmt::Display for InvalidationCause { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + InvalidationCause::Access(kind) => write!(f, "{}", kind), + InvalidationCause::Retag(perm, kind) => + if *kind == RetagCause::FnEntry { + write!(f, "{:?} FnEntry retag", perm) + } else { + write!(f, "{:?} retag", perm) + }, + } + } +} + +#[derive(Clone, Debug)] +struct Protection { + orig_tag: ProvenanceExtra, + tag: SbTag, + span: Span, +} + +#[derive(Clone)] +pub struct TagHistory { + pub created: (String, SpanData), + pub invalidated: Option<(String, SpanData)>, + pub protected: Option<([(String, SpanData); 2])>, +} + +pub struct DiagnosticCxBuilder<'ecx, 'mir, 'tcx> { + operation: Operation, + current_span: CurrentSpan<'ecx, 'mir, 'tcx>, + threads: &'ecx ThreadManager<'mir, 'tcx>, +} + +pub struct DiagnosticCx<'ecx, 'mir, 'tcx, 'history> { + operation: Operation, + current_span: CurrentSpan<'ecx, 'mir, 'tcx>, + threads: &'ecx ThreadManager<'mir, 'tcx>, + history: &'history mut AllocHistory, + offset: Size, +} + +impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> { + pub fn build( + self, + history: &'history mut AllocHistory, + offset: Size, + ) -> DiagnosticCx<'ecx, 'mir, 'tcx, 'history> { + DiagnosticCx { + operation: self.operation, + current_span: self.current_span, + threads: self.threads, + history, + offset, + } + } + + pub fn retag( + current_span: CurrentSpan<'ecx, 'mir, 'tcx>, + threads: &'ecx ThreadManager<'mir, 'tcx>, + cause: RetagCause, + new_tag: SbTag, + orig_tag: ProvenanceExtra, + range: AllocRange, + ) -> Self { + let operation = + Operation::Retag(RetagOp { cause, new_tag, orig_tag, range, permission: None }); + + DiagnosticCxBuilder { current_span, threads, operation } + } + + pub fn read( + current_span: CurrentSpan<'ecx, 'mir, 'tcx>, + threads: &'ecx ThreadManager<'mir, 'tcx>, + tag: ProvenanceExtra, + range: AllocRange, + ) -> Self { + let operation = Operation::Access(AccessOp { kind: AccessKind::Read, tag, range }); + DiagnosticCxBuilder { current_span, threads, operation } + } + + pub fn write( + current_span: CurrentSpan<'ecx, 'mir, 'tcx>, + threads: &'ecx ThreadManager<'mir, 'tcx>, + tag: ProvenanceExtra, + range: AllocRange, + ) -> Self { + let operation = Operation::Access(AccessOp { kind: AccessKind::Write, tag, range }); + DiagnosticCxBuilder { current_span, threads, operation } + } + + pub fn dealloc( + current_span: CurrentSpan<'ecx, 'mir, 'tcx>, + threads: &'ecx ThreadManager<'mir, 'tcx>, + tag: ProvenanceExtra, + ) -> Self { + let operation = Operation::Dealloc(DeallocOp { tag }); + DiagnosticCxBuilder { current_span, threads, operation } + } +} + +impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCx<'ecx, 'mir, 'tcx, 'history> { + pub fn unbuild(self) -> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> { + DiagnosticCxBuilder { + operation: self.operation, + current_span: self.current_span, + threads: self.threads, + } + } +} + +#[derive(Debug, Clone)] +enum Operation { + Retag(RetagOp), + Access(AccessOp), + Dealloc(DeallocOp), +} + +#[derive(Debug, Clone)] +struct RetagOp { + cause: RetagCause, + new_tag: SbTag, + orig_tag: ProvenanceExtra, + range: AllocRange, + permission: Option, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum RetagCause { + Normal, + FnReturn, + FnEntry, + TwoPhase, +} + +#[derive(Debug, Clone)] +struct AccessOp { + kind: AccessKind, + tag: ProvenanceExtra, + range: AllocRange, +} + +#[derive(Debug, Clone)] +struct DeallocOp { + tag: ProvenanceExtra, } impl AllocHistory { - pub fn new() -> Self { + pub fn new(id: AllocId) -> Self { Self { - current_time: 0, + id, creations: SmallVec::new(), invalidations: SmallVec::new(), protectors: SmallVec::new(), } } +} - pub fn log_creation( - &mut self, - parent: Option, - tag: SbTag, - range: AllocRange, - current_span: &mut CurrentSpan<'_, '_, '_>, - ) { - let span = current_span.get(); - self.creations.push(Event { parent, tag, range, span }); - self.current_time += 1; +impl<'ecx, 'mir, 'tcx, 'history> DiagnosticCx<'ecx, 'mir, 'tcx, 'history> { + pub fn start_grant(&mut self, perm: Permission) { + let Operation::Retag(op) = &mut self.operation else { + unreachable!("start_grant must only be called during a retag, this is: {:?}", self.operation) + }; + op.permission = Some(perm); + + let last_creation = &mut self.history.creations.last_mut().unwrap(); + match last_creation.retag.permission { + None => { + last_creation.retag.permission = Some(perm); + } + Some(previous) => + if previous != perm { + let previous_range = last_creation.retag.range; + last_creation.retag.range = alloc_range(previous_range.start, self.offset); + let mut new_event = last_creation.clone(); + new_event.retag.range = alloc_range(self.offset, previous_range.end()); + new_event.retag.permission = Some(perm); + self.history.creations.push(new_event); + }, + } } - pub fn log_invalidation( - &mut self, - tag: SbTag, - range: AllocRange, - current_span: &mut CurrentSpan<'_, '_, '_>, - ) { - let span = current_span.get(); - self.invalidations.push(Event { parent: None, tag, range, span }); - self.current_time += 1; + pub fn log_creation(&mut self) { + let Operation::Retag(op) = &self.operation else { + unreachable!("log_creation must only be called during a retag") + }; + self.history.creations.push(Creation { retag: op.clone(), span: self.current_span.get() }); } - pub fn log_protector( - &mut self, - orig_tag: SbTag, - tag: SbTag, - current_span: &mut CurrentSpan<'_, '_, '_>, - ) { - let span = current_span.get(); - self.protectors.push(Protection { orig_tag, tag, span }); - self.current_time += 1; + pub fn log_invalidation(&mut self, tag: SbTag) { + let mut span = self.current_span.get(); + let (range, cause) = match &self.operation { + Operation::Retag(RetagOp { cause, range, permission, .. }) => { + if *cause == RetagCause::FnEntry { + span = self.current_span.get_parent(); + } + (*range, InvalidationCause::Retag(permission.unwrap(), *cause)) + } + Operation::Access(AccessOp { kind, range, .. }) => + (*range, InvalidationCause::Access(*kind)), + _ => unreachable!("Tags can only be invalidated during a retag or access"), + }; + self.history.invalidations.push(Invalidation { tag, range, span, cause }); + } + + pub fn log_protector(&mut self) { + let Operation::Retag(op) = &self.operation else { + unreachable!("Protectors can only be created during a retag") + }; + self.history.protectors.push(Protection { + orig_tag: op.orig_tag, + tag: op.new_tag, + span: self.current_span.get(), + }); } pub fn get_logs_relevant_to( @@ -93,9 +296,48 @@ impl AllocHistory { tag: SbTag, protector_tag: Option, ) -> Option { + let Some(created) = self.history + .creations + .iter() + .rev() + .find_map(|event| { + // First, look for a Creation event where the tag and the offset matches. This + // ensrues that we pick the right Creation event when a retag isn't uniform due to + // Freeze. + let range = event.retag.range; + if event.retag.new_tag == tag + && self.offset >= range.start + && self.offset < (range.start + range.size) + { + Some(event.generate_diagnostic()) + } else { + None + } + }) + .or_else(|| { + // If we didn't find anything with a matching offset, just return the event where + // the tag was created. This branch is hit when we use a tag at an offset that + // doesn't have the tag. + self.history.creations.iter().rev().find_map(|event| { + if event.retag.new_tag == tag { + Some(event.generate_diagnostic()) + } else { + None + } + }) + }) else { + // But if we don't have a creation event, this is related to a wildcard, and there + // is really nothing we can do to help. + return None; + }; + + let invalidated = self.history.invalidations.iter().rev().find_map(|event| { + if event.tag == tag { Some(event.generate_diagnostic()) } else { None } + }); + let protected = protector_tag .and_then(|protector| { - self.protectors.iter().find_map(|protection| { + self.history.protectors.iter().find_map(|protection| { if protection.tag == protector { Some((protection.orig_tag, protection.span.data())) } else { @@ -104,77 +346,141 @@ impl AllocHistory { }) }) .and_then(|(tag, call_span)| { - self.creations.iter().rev().find_map(|event| { - if event.tag == tag { - Some((event.parent?, event.span.data(), call_span)) + self.history.creations.iter().rev().find_map(|event| { + if ProvenanceExtra::Concrete(event.retag.new_tag) == tag { + Some((event.retag.orig_tag, event.span.data(), call_span)) } else { None } }) + }) + .map(|(protecting_tag, protecting_tag_span, protection_span)| { + [ + ( + format!( + "{tag:?} was protected due to {protecting_tag:?} which was created here" + ), + protecting_tag_span, + ), + (format!("this protector is live for this call"), protection_span), + ] }); - let get_matching = |events: &[Event]| { - events.iter().rev().find_map(|event| { - if event.tag == tag { Some((event.range, event.span.data())) } else { None } - }) - }; - Some(TagHistory::Tagged { - tag, - created: get_matching(&self.creations)?, - invalidated: get_matching(&self.invalidations), - protected, - }) + Some(TagHistory { created, invalidated, protected }) } /// Report a descriptive error when `new` could not be granted from `derived_from`. - pub fn grant_error<'tcx>( - &self, - derived_from: ProvenanceExtra, - new: Item, - alloc_id: AllocId, - alloc_range: AllocRange, - error_offset: Size, - stack: &Stack, - ) -> InterpError<'tcx> { + pub fn grant_error(&self, perm: Permission, stack: &Stack) -> InterpError<'tcx> { + let Operation::Retag(op) = &self.operation else { + unreachable!("grant_error should only be called during a retag") + }; let action = format!( - "trying to reborrow from {derived_from:?} for {new_perm:?} permission at {alloc_id:?}[{offset:#x}]", - new_perm = new.perm(), - offset = error_offset.bytes(), + "trying to retag from {:?} for {:?} permission at {:?}[{:#x}]", + op.orig_tag, + perm, + self.history.id, + self.offset.bytes(), ); err_sb_ub( - format!("{}{}", action, error_cause(stack, derived_from)), - Some(operation_summary("a reborrow", alloc_id, alloc_range)), - derived_from.and_then(|derived_from| self.get_logs_relevant_to(derived_from, None)), + format!("{}{}", action, error_cause(stack, op.orig_tag)), + Some(operation_summary(&op.cause.summary(), self.history.id, op.range)), + op.orig_tag.and_then(|orig_tag| self.get_logs_relevant_to(orig_tag, None)), ) } /// Report a descriptive error when `access` is not permitted based on `tag`. - pub fn access_error<'tcx>( - &self, - access: AccessKind, - tag: ProvenanceExtra, - alloc_id: AllocId, - alloc_range: AllocRange, - error_offset: Size, - stack: &Stack, - ) -> InterpError<'tcx> { + pub fn access_error(&self, stack: &Stack) -> InterpError<'tcx> { + let Operation::Access(op) = &self.operation else { + unreachable!("access_error should only be called during an access") + }; let action = format!( "attempting a {access} using {tag:?} at {alloc_id:?}[{offset:#x}]", - offset = error_offset.bytes(), + access = op.kind, + tag = op.tag, + alloc_id = self.history.id, + offset = self.offset.bytes(), ); err_sb_ub( - format!("{}{}", action, error_cause(stack, tag)), - Some(operation_summary("an access", alloc_id, alloc_range)), - tag.and_then(|tag| self.get_logs_relevant_to(tag, None)), + format!("{}{}", action, error_cause(stack, op.tag)), + Some(operation_summary("an access", self.history.id, op.range)), + op.tag.and_then(|tag| self.get_logs_relevant_to(tag, None)), ) } + + pub fn protector_error(&self, item: &Item) -> InterpError<'tcx> { + let call_id = self + .threads + .all_stacks() + .flatten() + .map(|frame| { + frame.extra.stacked_borrows.as_ref().expect("we should have Stacked Borrows data") + }) + .find(|frame| frame.protected_tags.contains(&item.tag())) + .map(|frame| frame.call_id) + .unwrap(); // FIXME: Surely we should find something, but a panic seems wrong here? + match self.operation { + Operation::Dealloc(_) => + err_sb_ub( + format!( + "deallocating while item {:?} is protected by call {:?}", + item, call_id + ), + None, + None, + ), + Operation::Retag(RetagOp { orig_tag: tag, .. }) + | Operation::Access(AccessOp { tag, .. }) => + err_sb_ub( + format!( + "not granting access to tag {:?} because incompatible item {:?} is protected by call {:?}", + tag, item, call_id + ), + None, + tag.and_then(|tag| self.get_logs_relevant_to(tag, Some(item.tag()))), + ), + } + } + + pub fn dealloc_error(&self) -> InterpError<'tcx> { + let Operation::Dealloc(op) = &self.operation else { + unreachable!("dealloc_error should only be called during a deallocation") + }; + err_sb_ub( + format!( + "no item granting write access for deallocation to tag {:?} at {:?} found in borrow stack", + op.tag, self.history.id, + ), + None, + op.tag.and_then(|tag| self.get_logs_relevant_to(tag, None)), + ) + } + + #[inline(never)] + pub fn check_tracked_tag_popped(&self, item: &Item, global: &GlobalStateInner) { + if !global.tracked_pointer_tags.contains(&item.tag()) { + return; + } + let summary = match self.operation { + Operation::Dealloc(_) => None, + Operation::Access(AccessOp { kind, tag, .. }) => Some((tag, kind)), + Operation::Retag(RetagOp { orig_tag, permission, .. }) => { + let kind = match permission + .expect("start_grant should set the current permission before popping a tag") + { + Permission::SharedReadOnly => AccessKind::Read, + Permission::Unique => AccessKind::Write, + Permission::SharedReadWrite | Permission::Disabled => { + panic!("Only SharedReadOnly and Unique retags can pop tags"); + } + }; + Some((orig_tag, kind)) + } + }; + register_diagnostic(NonHaltingDiagnostic::PoppedPointerTag(*item, summary)); + } } -fn operation_summary( - operation: &'static str, - alloc_id: AllocId, - alloc_range: AllocRange, -) -> String { +fn operation_summary(operation: &str, alloc_id: AllocId, alloc_range: AllocRange) -> String { format!("this error occurs as part of {operation} at {alloc_id:?}{alloc_range:?}") } @@ -192,3 +498,15 @@ fn error_cause(stack: &Stack, prov_extra: ProvenanceExtra) -> &'static str { ", but no exposed tags have suitable permission in the borrow stack for this location" } } + +impl RetagCause { + fn summary(&self) -> String { + match self { + RetagCause::Normal => "retag", + RetagCause::FnEntry => "FnEntry retag", + RetagCause::FnReturn => "FnReturn retag", + RetagCause::TwoPhase => "two-phase retag", + } + .to_string() + } +} diff --git a/src/stacked_borrows/mod.rs b/src/stacked_borrows/mod.rs index b6b03f166999..6cb76e7b23aa 100644 --- a/src/stacked_borrows/mod.rs +++ b/src/stacked_borrows/mod.rs @@ -22,7 +22,7 @@ use smallvec::SmallVec; use crate::*; pub mod diagnostics; -use diagnostics::{AllocHistory, TagHistory}; +use diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, RetagCause, TagHistory}; mod item; pub use item::{Item, Permission}; @@ -142,11 +142,11 @@ pub enum RefKind { impl fmt::Display for RefKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - RefKind::Unique { two_phase: false } => write!(f, "unique"), - RefKind::Unique { two_phase: true } => write!(f, "unique (two-phase)"), - RefKind::Shared => write!(f, "shared"), - RefKind::Raw { mutable: true } => write!(f, "raw (mutable)"), - RefKind::Raw { mutable: false } => write!(f, "raw (constant)"), + RefKind::Unique { two_phase: false } => write!(f, "unique reference"), + RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"), + RefKind::Shared => write!(f, "shared reference"), + RefKind::Raw { mutable: true } => write!(f, "raw (mutable) pointer"), + RefKind::Raw { mutable: false } => write!(f, "raw (constant) pointer"), } } } @@ -285,94 +285,19 @@ impl<'tcx> Stack { /// currently checking. fn item_popped( item: &Item, - provoking_access: Option<(ProvenanceExtra, AllocRange, Size, AccessKind)>, // just for debug printing and error messages global: &GlobalStateInner, - alloc_history: &mut AllocHistory, - threads: &ThreadManager<'_, 'tcx>, + dcx: &mut DiagnosticCx<'_, '_, 'tcx, '_>, ) -> InterpResult<'tcx> { if !global.tracked_pointer_tags.is_empty() { - check_tracked(item, &provoking_access, global); - - #[inline(never)] // cold path - fn check_tracked( - item: &Item, - provoking_access: &Option<(ProvenanceExtra, AllocRange, Size, AccessKind)>, - global: &GlobalStateInner, - ) { - if global.tracked_pointer_tags.contains(&item.tag()) { - register_diagnostic(NonHaltingDiagnostic::PoppedPointerTag( - *item, - provoking_access.map(|(tag, _alloc_range, _size, access)| (tag, access)), - )); - } - } + dcx.check_tracked_tag_popped(item, global); } if !item.protected() { return Ok(()); } - // We store tags twice, once in global.protected_tags and once in each call frame. - // We do this because consulting a single global set in this function is faster - // than attempting to search all call frames in the program for the `FrameExtra` - // (if any) which is protecting the popped tag. - // - // This duplication trades off making `end_call` slower to make this function faster. This - // trade-off is profitable in practice for a combination of two reasons. - // 1. A single protected tag can (and does in some programs) protect thousands of `Item`s. - // Therefore, adding overhead to in function call/return is profitable even if it only - // saves a little work in this function. - // 2. Most frames protect only one or two tags. So this duplicative global turns a search - // which ends up about linear in the number of protected tags in the program into a - // constant time check (and a slow linear, because the tags in the frames aren't contiguous). if global.protected_tags.contains(&item.tag()) { - return Err(protector_error(item, &provoking_access, alloc_history, threads)); - - #[inline(never)] // cold path - fn protector_error<'tcx>( - item: &Item, - provoking_access: &Option<(ProvenanceExtra, AllocRange, Size, AccessKind)>, - alloc_history: &mut AllocHistory, - threads: &ThreadManager<'_, 'tcx>, - ) -> InterpErrorInfo<'tcx> { - // This path is cold because it is fatal to the program. So here it is fine to do the - // more expensive search to figure out which call is responsible for protecting this - // tag. - let call_id = threads - .all_stacks() - .flatten() - .map(|frame| { - frame - .extra - .stacked_borrows - .as_ref() - .expect("we should have Stacked Borrows data") - }) - .find(|frame| frame.protected_tags.contains(&item.tag())) - .map(|frame| frame.call_id) - .unwrap(); // FIXME: Surely we should find something, but a panic seems wrong here? - if let Some((tag, _alloc_range, _offset, _access)) = provoking_access { - err_sb_ub( - format!( - "not granting access to tag {:?} because incompatible item {:?} is protected by call {:?}", - tag, item, call_id - ), - None, - tag.and_then(|tag| { - alloc_history.get_logs_relevant_to(tag, Some(item.tag())) - }), - ) - } else { - err_sb_ub( - format!( - "deallocating while item {:?} is protected by call {:?}", - item, call_id - ), - None, - None, - ) - }.into() - } + return Err(dcx.protector_error(item).into()); } Ok(()) } @@ -385,19 +310,15 @@ impl<'tcx> Stack { &mut self, access: AccessKind, tag: ProvenanceExtra, - (alloc_id, alloc_range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages global: &mut GlobalStateInner, - current_span: &mut CurrentSpan<'_, '_, 'tcx>, - alloc_history: &mut AllocHistory, + dcx: &mut DiagnosticCx<'_, '_, 'tcx, '_>, exposed_tags: &FxHashSet, - threads: &ThreadManager<'_, 'tcx>, ) -> InterpResult<'tcx> { // Two main steps: Find granting item, remove incompatible items above. // Step 1: Find granting item. - let granting_idx = self.find_granting(access, tag, exposed_tags).map_err(|_| { - alloc_history.access_error(access, tag, alloc_id, alloc_range, offset, self) - })?; + let granting_idx = + self.find_granting(access, tag, exposed_tags).map_err(|_| dcx.access_error(self))?; // Step 2: Remove incompatible items above them. Make sure we do not remove protected // items. Behavior differs for reads and writes. @@ -416,14 +337,8 @@ impl<'tcx> Stack { 0 }; self.pop_items_after(first_incompatible_idx, |item| { - Stack::item_popped( - &item, - Some((tag, alloc_range, offset, access)), - global, - alloc_history, - threads, - )?; - alloc_history.log_invalidation(item.tag(), alloc_range, current_span); + Stack::item_popped(&item, global, dcx)?; + dcx.log_invalidation(item.tag()); Ok(()) })?; } else { @@ -443,14 +358,8 @@ impl<'tcx> Stack { 0 }; self.disable_uniques_starting_at(first_incompatible_idx, |item| { - Stack::item_popped( - &item, - Some((tag, alloc_range, offset, access)), - global, - alloc_history, - threads, - )?; - alloc_history.log_invalidation(item.tag(), alloc_range, current_span); + Stack::item_popped(&item, global, dcx)?; + dcx.log_invalidation(item.tag()); Ok(()) })?; } @@ -487,27 +396,18 @@ impl<'tcx> Stack { fn dealloc( &mut self, tag: ProvenanceExtra, - (alloc_id, _alloc_range, _offset): (AllocId, AllocRange, Size), // just for debug printing and error messages global: &GlobalStateInner, - alloc_history: &mut AllocHistory, + dcx: &mut DiagnosticCx<'_, '_, 'tcx, '_>, exposed_tags: &FxHashSet, - threads: &ThreadManager<'_, 'tcx>, ) -> InterpResult<'tcx> { // Step 1: Make sure there is a granting item. - self.find_granting(AccessKind::Write, tag, exposed_tags).map_err(|_| { - err_sb_ub(format!( - "no item granting write access for deallocation to tag {:?} at {:?} found in borrow stack", - tag, alloc_id, - ), - None, - tag.and_then(|tag| alloc_history.get_logs_relevant_to(tag, None)), - ) - })?; + self.find_granting(AccessKind::Write, tag, exposed_tags) + .map_err(|_| dcx.dealloc_error())?; // Step 2: Consider all items removed. This checks for protectors. for idx in (0..self.len()).rev() { let item = self.get(idx).unwrap(); - Stack::item_popped(&item, None, global, alloc_history, threads)?; + Stack::item_popped(&item, global, dcx)?; } Ok(()) } @@ -522,23 +422,21 @@ impl<'tcx> Stack { &mut self, derived_from: ProvenanceExtra, new: Item, - (alloc_id, alloc_range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages global: &mut GlobalStateInner, - current_span: &mut CurrentSpan<'_, '_, 'tcx>, - alloc_history: &mut AllocHistory, + dcx: &mut DiagnosticCx<'_, '_, 'tcx, '_>, exposed_tags: &FxHashSet, - threads: &ThreadManager<'_, 'tcx>, ) -> InterpResult<'tcx> { + dcx.start_grant(new.perm()); + // Figure out which access `perm` corresponds to. let access = if new.perm().grants(AccessKind::Write) { AccessKind::Write } else { AccessKind::Read }; // Now we figure out which item grants our parent (`derived_from`) this kind of access. // We use that to determine where to put the new item. - let granting_idx = - self.find_granting(access, derived_from, exposed_tags).map_err(|_| { - alloc_history.grant_error(derived_from, new, alloc_id, alloc_range, offset, self) - })?; + let granting_idx = self + .find_granting(access, derived_from, exposed_tags) + .map_err(|_| dcx.grant_error(new.perm(), self))?; // Compute where to put the new item. // Either way, we ensure that we insert the new item in a way such that between @@ -568,16 +466,7 @@ impl<'tcx> Stack { // A "safe" reborrow for a pointer that actually expects some aliasing guarantees. // Here, creating a reference actually counts as an access. // This ensures F2b for `Unique`, by removing offending `SharedReadOnly`. - self.access( - access, - derived_from, - (alloc_id, alloc_range, offset), - global, - current_span, - alloc_history, - exposed_tags, - threads, - )?; + self.access(access, derived_from, global, dcx, exposed_tags)?; // We insert "as far up as possible": We know only compatible items are remaining // on top of `derived_from`, and we want the new item at the top so that we @@ -596,14 +485,15 @@ impl<'tcx> Stack { /// Map per-stack operations to higher-level per-location-range operations. impl<'tcx> Stacks { - /// Creates new stack with initial tag. - fn new(size: Size, perm: Permission, tag: SbTag) -> Self { + /// Creates a new stack with an initial tag. For diagnostic purposes, we also need to know + /// the [`AllocId`] of the allocation this is associated with. + fn new(size: Size, perm: Permission, tag: SbTag, id: AllocId) -> Self { let item = Item::new(tag, perm, false); let stack = Stack::new(item); Stacks { stacks: RangeMap::new(size, stack), - history: AllocHistory::new(), + history: AllocHistory::new(id), exposed_tags: FxHashSet::default(), } } @@ -612,15 +502,17 @@ impl<'tcx> Stacks { fn for_each( &mut self, range: AllocRange, + mut dcx_builder: DiagnosticCxBuilder<'_, '_, 'tcx>, mut f: impl FnMut( - Size, &mut Stack, - &mut AllocHistory, + &mut DiagnosticCx<'_, '_, 'tcx, '_>, &mut FxHashSet, ) -> InterpResult<'tcx>, ) -> InterpResult<'tcx> { for (offset, stack) in self.stacks.iter_mut(range.start, range.size) { - f(offset, stack, &mut self.history, &mut self.exposed_tags)?; + let mut dcx = dcx_builder.build(&mut self.history, offset); + f(stack, &mut dcx, &mut self.exposed_tags)?; + dcx_builder = dcx.unbuild(); } Ok(()) } @@ -633,7 +525,6 @@ impl Stacks { size: Size, state: &GlobalState, kind: MemoryKind, - mut current_span: CurrentSpan<'_, '_, '_>, ) -> Self { let mut extra = state.borrow_mut(); let (base_tag, perm) = match kind { @@ -646,25 +537,18 @@ impl Stacks { // Everything else is shared by default. _ => (extra.base_ptr_tag(id), Permission::SharedReadWrite), }; - let mut stacks = Stacks::new(size, perm, base_tag); - stacks.history.log_creation( - None, - base_tag, - alloc_range(Size::ZERO, size), - &mut current_span, - ); - stacks + Stacks::new(size, perm, base_tag, id) } #[inline(always)] - pub fn before_memory_read<'tcx>( + pub fn before_memory_read<'tcx, 'mir>( &mut self, alloc_id: AllocId, tag: ProvenanceExtra, range: AllocRange, state: &GlobalState, - mut current_span: CurrentSpan<'_, '_, 'tcx>, - threads: &ThreadManager<'_, 'tcx>, + current_span: CurrentSpan<'_, 'mir, 'tcx>, + threads: &ThreadManager<'mir, 'tcx>, ) -> InterpResult<'tcx> { trace!( "read access with tag {:?}: {:?}, size {}", @@ -672,30 +556,22 @@ impl Stacks { Pointer::new(alloc_id, range.start), range.size.bytes() ); + let dcx = DiagnosticCxBuilder::read(current_span, threads, tag, range); let mut state = state.borrow_mut(); - self.for_each(range, |offset, stack, history, exposed_tags| { - stack.access( - AccessKind::Read, - tag, - (alloc_id, range, offset), - &mut state, - &mut current_span, - history, - exposed_tags, - threads, - ) + self.for_each(range, dcx, |stack, dcx, exposed_tags| { + stack.access(AccessKind::Read, tag, &mut state, dcx, exposed_tags) }) } #[inline(always)] - pub fn before_memory_write<'tcx>( + pub fn before_memory_write<'tcx, 'mir>( &mut self, alloc_id: AllocId, tag: ProvenanceExtra, range: AllocRange, state: &GlobalState, - mut current_span: CurrentSpan<'_, '_, 'tcx>, - threads: &ThreadManager<'_, 'tcx>, + current_span: CurrentSpan<'_, 'mir, 'tcx>, + threads: &ThreadManager<'mir, 'tcx>, ) -> InterpResult<'tcx> { trace!( "write access with tag {:?}: {:?}, size {}", @@ -703,34 +579,28 @@ impl Stacks { Pointer::new(alloc_id, range.start), range.size.bytes() ); + let dcx = DiagnosticCxBuilder::write(current_span, threads, tag, range); let mut state = state.borrow_mut(); - self.for_each(range, |offset, stack, history, exposed_tags| { - stack.access( - AccessKind::Write, - tag, - (alloc_id, range, offset), - &mut state, - &mut current_span, - history, - exposed_tags, - threads, - ) + self.for_each(range, dcx, |stack, dcx, exposed_tags| { + stack.access(AccessKind::Write, tag, &mut state, dcx, exposed_tags) }) } #[inline(always)] - pub fn before_memory_deallocation<'tcx>( + pub fn before_memory_deallocation<'tcx, 'mir>( &mut self, alloc_id: AllocId, tag: ProvenanceExtra, range: AllocRange, state: &GlobalState, - threads: &ThreadManager<'_, 'tcx>, + current_span: CurrentSpan<'_, 'mir, 'tcx>, + threads: &ThreadManager<'mir, 'tcx>, ) -> InterpResult<'tcx> { trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, range.size.bytes()); + let dcx = DiagnosticCxBuilder::dealloc(current_span, threads, tag); let state = state.borrow(); - self.for_each(range, |offset, stack, history, exposed_tags| { - stack.dealloc(tag, (alloc_id, range, offset), &state, history, exposed_tags, threads) + self.for_each(range, dcx, |stack, dcx, exposed_tags| { + stack.dealloc(tag, &state, dcx, exposed_tags) })?; Ok(()) } @@ -747,15 +617,15 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx place: &MPlaceTy<'tcx, Provenance>, size: Size, kind: RefKind, + retag_cause: RetagCause, // What caused this retag, for diagnostics only new_tag: SbTag, protect: bool, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); - let current_span = &mut this.machine.current_span(); // It is crucial that this gets called on all code paths, to ensure we track tag creation. let log_creation = |this: &MiriEvalContext<'mir, 'tcx>, - current_span: &mut CurrentSpan<'_, 'mir, 'tcx>, + current_span: CurrentSpan<'_, 'mir, 'tcx>, loc: Option<(AllocId, Size, ProvenanceExtra)>| // alloc_id, base_offset, orig_tag -> InterpResult<'tcx> { let global = this.machine.stacked_borrows.as_ref().unwrap().borrow(); @@ -771,14 +641,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx return Ok(()) }; - // The SB history tracking needs a parent tag, so skip if we come from a wildcard. - let ProvenanceExtra::Concrete(orig_tag) = orig_tag else { - // FIXME: should we log this? - return Ok(()) - }; - - let (_size, _align, kind) = this.get_alloc_info(alloc_id); - match kind { + let (_size, _align, alloc_kind) = this.get_alloc_info(alloc_id); + match alloc_kind { AllocKind::LiveData => { // This should have alloc_extra data, but `get_alloc_extra` can still fail // if converting this alloc_id from a global to a local one @@ -789,14 +653,18 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx .as_ref() .expect("we should have Stacked Borrows data") .borrow_mut(); - stacked_borrows.history.log_creation( - Some(orig_tag), - new_tag, - alloc_range(base_offset, size), + let dcx = DiagnosticCxBuilder::retag( current_span, + &this.machine.threads, + retag_cause, + new_tag, + orig_tag, + alloc_range(base_offset, size), ); + let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset); + dcx.log_creation(); if protect { - stacked_borrows.history.log_protector(orig_tag, new_tag, current_span); + dcx.log_protector(); } } AllocKind::Function | AllocKind::VTable | AllocKind::Dead => { @@ -806,6 +674,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx Ok(()) }; + let current_span = this.machine.current_span(*this.tcx); + if size == Size::ZERO { trace!( "reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})", @@ -829,6 +699,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx log_creation(this, current_span, None)?; return Ok(None); } + let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr)?; log_creation(this, current_span, Some((alloc_id, base_offset, orig_tag)))?; @@ -855,11 +726,22 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ); if protect { + // We store tags twice, once in global.protected_tags and once in each call frame. + // We do this because consulting a single global set in this function is faster + // than attempting to search all call frames in the program for the `FrameExtra` + // (if any) which is protecting the popped tag. + // + // This duplication trades off making `end_call` slower to make this function faster. This + // trade-off is profitable in practice for a combination of two reasons. + // 1. A single protected tag can (and does in some programs) protect thousands of `Item`s. + // Therefore, adding overhead to in function call/return is profitable even if it only + // saves a little work in this function. + // 2. Most frames protect only one or two tags. So this duplicative global turns a search + // which ends up about linear in the number of protected tags in the program into a + // constant time check (and a slow linear, because the tags in the frames aren't contiguous). this.frame_mut().extra.stacked_borrows.as_mut().unwrap().protected_tags.push(new_tag); this.machine.stacked_borrows.as_mut().unwrap().get_mut().protected_tags.insert(new_tag); } - // FIXME: can't hold the current span handle across the borrows of self above - let current_span = &mut this.machine.current_span(); // Update the stacks. // Make sure that raw pointers and mutable shared references are reborrowed "weak": @@ -906,26 +788,26 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx }; let item = Item::new(new_tag, perm, protected); let mut global = this.machine.stacked_borrows.as_ref().unwrap().borrow_mut(); - let threads = &this.machine.threads; - stacked_borrows.for_each(range, |offset, stack, history, exposed_tags| { - stack.grant( - orig_tag, - item, - (alloc_id, range, offset), - &mut global, - current_span, - history, - exposed_tags, - threads, - ) + let dcx = DiagnosticCxBuilder::retag( + this.machine.current_span(*this.tcx), + &this.machine.threads, + retag_cause, + new_tag, + orig_tag, + alloc_range(base_offset, size), + ); + stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| { + stack.grant(orig_tag, item, &mut global, dcx, exposed_tags) }) })?; return Ok(Some(alloc_id)); } }; + // Here we can avoid `borrow()` calls because we have mutable references. // Note that this asserts that the allocation is mutable -- but since we are creating a // mutable pointer, that seems reasonable. + let tcx = *this.tcx; let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?; let mut stacked_borrows = alloc_extra .stacked_borrows @@ -935,19 +817,16 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let item = Item::new(new_tag, perm, protect); let range = alloc_range(base_offset, size); let mut global = machine.stacked_borrows.as_ref().unwrap().borrow_mut(); - let threads = &machine.threads; - let current_span = &mut machine.current_span(); // `get_alloc_extra_mut` invalidated our old `current_span` - stacked_borrows.for_each(range, |offset, stack, history, exposed_tags| { - stack.grant( - orig_tag, - item, - (alloc_id, range, offset), - &mut global, - current_span, - history, - exposed_tags, - threads, - ) + let dcx = DiagnosticCxBuilder::retag( + machine.current_span(tcx), + &machine.threads, + retag_cause, + new_tag, + orig_tag, + alloc_range(base_offset, size), + ); + stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| { + stack.grant(orig_tag, item, &mut global, dcx, exposed_tags) })?; Ok(Some(alloc_id)) @@ -959,6 +838,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx &mut self, val: &ImmTy<'tcx, Provenance>, kind: RefKind, + retag_cause: RetagCause, // What caused this retag, for diagnostics only protect: bool, ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { let this = self.eval_context_mut(); @@ -977,7 +857,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let new_tag = this.machine.stacked_borrows.as_mut().unwrap().get_mut().new_ptr(); // Reborrow. - let alloc_id = this.reborrow(&place, size, kind, new_tag, protect)?; + let alloc_id = this.reborrow(&place, size, kind, retag_cause, new_tag, protect)?; // Adjust pointer. let new_place = place.map_provenance(|p| { @@ -1007,7 +887,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let retag_fields = this.machine.stacked_borrows.as_mut().unwrap().get_mut().retag_fields; - let mut visitor = RetagVisitor { ecx: this, kind, retag_fields }; + let retag_cause = match kind { + RetagKind::TwoPhase { .. } => RetagCause::TwoPhase, + RetagKind::FnEntry => RetagCause::FnEntry, + RetagKind::Raw | RetagKind::Default => RetagCause::Normal, + }; + let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields }; return visitor.visit_value(place); // Determine mutability and whether to add a protector. @@ -1036,6 +921,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx struct RetagVisitor<'ecx, 'mir, 'tcx> { ecx: &'ecx mut MiriEvalContext<'mir, 'tcx>, kind: RetagKind, + retag_cause: RetagCause, retag_fields: bool, } impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> { @@ -1044,10 +930,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx &mut self, place: &PlaceTy<'tcx, Provenance>, ref_kind: RefKind, + retag_cause: RetagCause, protector: bool, ) -> InterpResult<'tcx> { let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?; - let val = self.ecx.retag_reference(&val, ref_kind, protector)?; + let val = self.ecx.retag_reference(&val, ref_kind, retag_cause, protector)?; self.ecx.write_immediate(*val, place)?; Ok(()) } @@ -1068,13 +955,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx self.retag_place( place, RefKind::Unique { two_phase: false }, + self.retag_cause, /*protector*/ false, ) } fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { if let Some((ref_kind, protector)) = qualify(place.layout.ty, self.kind) { - self.retag_place(place, ref_kind, protector)?; + self.retag_place(place, ref_kind, self.retag_cause, protector)?; } else if matches!(place.layout.ty.kind(), ty::RawPtr(..)) { // Wide raw pointers *do* have fields and their types are strange. // vtables have a type like `&[*const (); 3]` or so! @@ -1117,6 +1005,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let val = this.retag_reference( &val, RefKind::Unique { two_phase: false }, + RetagCause::FnReturn, /*protector*/ true, )?; // And use reborrowed pointer for return place. diff --git a/tests/fail/box-cell-alias.stderr b/tests/fail/box-cell-alias.stderr index 705348ba0f06..1436afcd212b 100644 --- a/tests/fail/box-cell-alias.stderr +++ b/tests/fail/box-cell-alias.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/box-cell-alias.rs:LL:CC | LL | unsafe { (*ptr).set(20) }; | ^^^^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x1] + | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x0..0x1] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x1] +help: was created by a SharedReadWrite retag at offsets [0x0..0x1] --> $DIR/box-cell-alias.rs:LL:CC | LL | let ptr: *const Cell = &*val; | ^^^^^ -help: was later invalidated at offsets [0x0..0x1] +help: was later invalidated at offsets [0x0..0x1] by a Unique retag --> $DIR/box-cell-alias.rs:LL:CC | LL | let res = helper(val, ptr); diff --git a/tests/fail/stacked_borrows/alias_through_mutation.stderr b/tests/fail/stacked_borrows/alias_through_mutation.stderr index ec985cb26a99..74d1e4ebbcb8 100644 --- a/tests/fail/stacked_borrows/alias_through_mutation.stderr +++ b/tests/fail/stacked_borrows/alias_through_mutation.stderr @@ -9,12 +9,12 @@ LL | let _val = *target_alias; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/alias_through_mutation.rs:LL:CC | LL | *x = &mut *(target as *mut _); | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/alias_through_mutation.rs:LL:CC | LL | *target = 13; diff --git a/tests/fail/stacked_borrows/aliasing_mut1.stderr b/tests/fail/stacked_borrows/aliasing_mut1.stderr index b821d1e6edb4..e3f05f3350a5 100644 --- a/tests/fail/stacked_borrows/aliasing_mut1.stderr +++ b/tests/fail/stacked_borrows/aliasing_mut1.stderr @@ -6,7 +6,7 @@ LL | pub fn safe(_x: &mut i32, _y: &mut i32) {} | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/aliasing_mut1.rs:LL:CC | LL | let xraw: *mut i32 = unsafe { mem::transmute(&mut x) }; diff --git a/tests/fail/stacked_borrows/aliasing_mut2.stderr b/tests/fail/stacked_borrows/aliasing_mut2.stderr index 594b578fc09a..94c2ffa07f71 100644 --- a/tests/fail/stacked_borrows/aliasing_mut2.stderr +++ b/tests/fail/stacked_borrows/aliasing_mut2.stderr @@ -6,7 +6,7 @@ LL | pub fn safe(_x: &i32, _y: &mut i32) {} | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/aliasing_mut2.rs:LL:CC | LL | let xref = &mut x; diff --git a/tests/fail/stacked_borrows/aliasing_mut3.stderr b/tests/fail/stacked_borrows/aliasing_mut3.stderr index 0bb7b8d3a85c..0fa31260323f 100644 --- a/tests/fail/stacked_borrows/aliasing_mut3.stderr +++ b/tests/fail/stacked_borrows/aliasing_mut3.stderr @@ -1,24 +1,24 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/aliasing_mut3.rs:LL:CC | LL | pub fn safe(_x: &mut i32, _y: &i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of FnEntry retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/aliasing_mut3.rs:LL:CC | LL | safe_raw(xraw, xshr); | ^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag --> $DIR/aliasing_mut3.rs:LL:CC | -LL | pub fn safe(_x: &mut i32, _y: &i32) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | safe_raw(xraw, xshr); + | ^^^^^^^^^^^^^^^^^^^^ = note: backtrace: = note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC note: inside `main` at $DIR/aliasing_mut3.rs:LL:CC diff --git a/tests/fail/stacked_borrows/aliasing_mut4.stderr b/tests/fail/stacked_borrows/aliasing_mut4.stderr index 0c7d85ae5756..f48d39b2e49f 100644 --- a/tests/fail/stacked_borrows/aliasing_mut4.stderr +++ b/tests/fail/stacked_borrows/aliasing_mut4.stderr @@ -6,7 +6,7 @@ LL | pub fn safe(_x: &i32, _y: &mut Cell) {} | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/aliasing_mut4.rs:LL:CC | LL | let xref = &mut x; diff --git a/tests/fail/stacked_borrows/box_exclusive_violation1.stderr b/tests/fail/stacked_borrows/box_exclusive_violation1.stderr index 7214ef27be33..dfe49d7f0892 100644 --- a/tests/fail/stacked_borrows/box_exclusive_violation1.stderr +++ b/tests/fail/stacked_borrows/box_exclusive_violation1.stderr @@ -9,12 +9,12 @@ LL | *LEAK = 7; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/box_exclusive_violation1.rs:LL:CC | LL | LEAK = x as *const _ as *mut _; | ^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/box_exclusive_violation1.rs:LL:CC | LL | *our = 5; diff --git a/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr b/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr index 6e78ed6c7298..c0fc247cd4a2 100644 --- a/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr +++ b/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr @@ -9,12 +9,12 @@ LL | v1[1] = 5; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0xc] +help: was created by a Unique retag at offsets [0x0..0xc] --> $DIR/buggy_as_mut_slice.rs:LL:CC | LL | let v1 = safe::as_mut_slice(&v); | ^^^^^^^^^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0xc] +help: was later invalidated at offsets [0x0..0xc] by a Unique retag --> $DIR/buggy_as_mut_slice.rs:LL:CC | LL | unsafe { from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len()) } diff --git a/tests/fail/stacked_borrows/buggy_split_at_mut.rs b/tests/fail/stacked_borrows/buggy_split_at_mut.rs index db64d559c517..8a1ea86d6338 100644 --- a/tests/fail/stacked_borrows/buggy_split_at_mut.rs +++ b/tests/fail/stacked_borrows/buggy_split_at_mut.rs @@ -19,7 +19,7 @@ mod safe { fn main() { let mut array = [1, 2, 3, 4]; let (a, b) = safe::split_at_mut(&mut array, 0); - //~^ ERROR: /reborrow .* tag does not exist in the borrow stack/ + //~^ ERROR: /retag .* tag does not exist in the borrow stack/ a[1] = 5; b[1] = 6; } diff --git a/tests/fail/stacked_borrows/buggy_split_at_mut.stderr b/tests/fail/stacked_borrows/buggy_split_at_mut.stderr index 41ab9cfa92ae..b4c5140882f3 100644 --- a/tests/fail/stacked_borrows/buggy_split_at_mut.stderr +++ b/tests/fail/stacked_borrows/buggy_split_at_mut.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/buggy_split_at_mut.rs:LL:CC | LL | let (a, b) = safe::split_at_mut(&mut array, 0); | ^ | | - | trying to reborrow from for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x10] + | trying to retag from for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x0..0x10] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x10] +help: was created by a Unique retag at offsets [0x0..0x10] --> $DIR/buggy_split_at_mut.rs:LL:CC | LL | from_raw_parts_mut(ptr, len - mid), // BUG: should be "mid" instead of "len - mid" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x10] +help: was later invalidated at offsets [0x0..0x10] by a Unique retag --> $DIR/buggy_split_at_mut.rs:LL:CC | LL | from_raw_parts_mut(ptr.offset(mid as isize), len - mid), diff --git a/tests/fail/stacked_borrows/fnentry_invalidation.rs b/tests/fail/stacked_borrows/fnentry_invalidation.rs new file mode 100644 index 000000000000..37214bebb828 --- /dev/null +++ b/tests/fail/stacked_borrows/fnentry_invalidation.rs @@ -0,0 +1,20 @@ +// Test that spans displayed in diagnostics identify the function call, not the function +// definition, as the location of invalidation due to FnEntry retag. Technically the FnEntry retag +// occurs inside the function, but what the user wants to know is which call produced the +// invalidation. +fn main() { + let mut x = 0i32; + let z = &mut x as *mut i32; + x.do_bad(); + unsafe { + let _oof = *z; //~ ERROR: /read access .* tag does not exist in the borrow stack/ + } +} + +trait Bad { + fn do_bad(&mut self) { + // who knows + } +} + +impl Bad for i32 {} diff --git a/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/tests/fail/stacked_borrows/fnentry_invalidation.stderr new file mode 100644 index 000000000000..a66fd3200347 --- /dev/null +++ b/tests/fail/stacked_borrows/fnentry_invalidation.stderr @@ -0,0 +1,28 @@ +error: Undefined Behavior: attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + --> $DIR/fnentry_invalidation.rs:LL:CC + | +LL | let _oof = *z; + | ^^ + | | + | attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of an access at ALLOC[0x0..0x4] + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] + --> $DIR/fnentry_invalidation.rs:LL:CC + | +LL | let z = &mut x as *mut i32; + | ^^^^^^ +help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag + --> $DIR/fnentry_invalidation.rs:LL:CC + | +LL | x.do_bad(); + | ^^^^^^^^^^ + = note: backtrace: + = note: inside `main` at $DIR/fnentry_invalidation.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/tests/fail/stacked_borrows/illegal_read1.stderr b/tests/fail/stacked_borrows/illegal_read1.stderr index 3f4ade9a712f..6e9d491137c8 100644 --- a/tests/fail/stacked_borrows/illegal_read1.stderr +++ b/tests/fail/stacked_borrows/illegal_read1.stderr @@ -9,12 +9,12 @@ LL | let _val = *xref; // ...but any use of raw will invalidate our ref. | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/illegal_read1.rs:LL:CC | LL | let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still ok... | ^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a read access --> $DIR/illegal_read1.rs:LL:CC | LL | let _val = unsafe { *xraw }; diff --git a/tests/fail/stacked_borrows/illegal_read2.stderr b/tests/fail/stacked_borrows/illegal_read2.stderr index cb0ac5602782..fb1f9ec6a884 100644 --- a/tests/fail/stacked_borrows/illegal_read2.stderr +++ b/tests/fail/stacked_borrows/illegal_read2.stderr @@ -9,12 +9,12 @@ LL | let _val = *xref; // ...but any use of raw will invalidate our ref. | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/illegal_read2.rs:LL:CC | LL | let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still ok... | ^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a SharedReadOnly retag --> $DIR/illegal_read2.rs:LL:CC | LL | let shr = unsafe { &*xraw }; diff --git a/tests/fail/stacked_borrows/illegal_read3.stderr b/tests/fail/stacked_borrows/illegal_read3.stderr index bdeca5f7ec86..55ab8877999c 100644 --- a/tests/fail/stacked_borrows/illegal_read3.stderr +++ b/tests/fail/stacked_borrows/illegal_read3.stderr @@ -9,12 +9,12 @@ LL | let _val = *xref2; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/illegal_read3.rs:LL:CC | LL | let xref2 = &mut *xref1; | ^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a read access --> $DIR/illegal_read3.rs:LL:CC | LL | let _val = unsafe { *xref1.r }; diff --git a/tests/fail/stacked_borrows/illegal_read4.stderr b/tests/fail/stacked_borrows/illegal_read4.stderr index 59c2088c0c85..3bb064e2f416 100644 --- a/tests/fail/stacked_borrows/illegal_read4.stderr +++ b/tests/fail/stacked_borrows/illegal_read4.stderr @@ -9,12 +9,12 @@ LL | let _illegal = *xref2; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/illegal_read4.rs:LL:CC | LL | let xref2 = unsafe { &mut *xraw }; | ^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a read access --> $DIR/illegal_read4.rs:LL:CC | LL | let _val = unsafe { *xraw }; // use the raw again, this invalidates xref2 *even* with the special read except for uniq refs diff --git a/tests/fail/stacked_borrows/illegal_read5.stderr b/tests/fail/stacked_borrows/illegal_read5.stderr index d1506f199684..e060463cf1d3 100644 --- a/tests/fail/stacked_borrows/illegal_read5.stderr +++ b/tests/fail/stacked_borrows/illegal_read5.stderr @@ -9,12 +9,12 @@ LL | let _val = *xref; // the mutable one is dead and gone | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [$HEX..$HEX] +help: was created by a Unique retag at offsets [$HEX..$HEX] --> $DIR/illegal_read5.rs:LL:CC | LL | let xref: &mut i32 = &mut *refmut; | ^^^^^^^^^^^^ -help: was later invalidated at offsets [$HEX..$HEX] +help: was later invalidated at offsets [$HEX..$HEX] by a read access --> $DIR/illegal_read5.rs:LL:CC | LL | mem::forget(unsafe { ptr::read(xshr) }); // but after reading through the shared ref diff --git a/tests/fail/stacked_borrows/illegal_read6.stderr b/tests/fail/stacked_borrows/illegal_read6.stderr index 5abea6f611a4..8ef720925646 100644 --- a/tests/fail/stacked_borrows/illegal_read6.stderr +++ b/tests/fail/stacked_borrows/illegal_read6.stderr @@ -9,12 +9,12 @@ LL | let _val = *raw; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/illegal_read6.rs:LL:CC | LL | let raw = x as *mut _; | ^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a Unique retag --> $DIR/illegal_read6.rs:LL:CC | LL | let x = &mut *x; // kill `raw` diff --git a/tests/fail/stacked_borrows/illegal_read7.rs b/tests/fail/stacked_borrows/illegal_read7.rs index c0d3816f4475..1901e8e4e348 100644 --- a/tests/fail/stacked_borrows/illegal_read7.rs +++ b/tests/fail/stacked_borrows/illegal_read7.rs @@ -17,6 +17,6 @@ fn main() { // without invalidating `x`. That would be bad! It would mean that creating `shr` // leaked `x` to `raw`. let _val = ptr::read(raw); - let _val = *x.get_mut(); //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + let _val = *x.get_mut(); //~ ERROR: /retag .* tag does not exist in the borrow stack/ } } diff --git a/tests/fail/stacked_borrows/illegal_read7.stderr b/tests/fail/stacked_borrows/illegal_read7.stderr index 11335df4da0a..5c42b0a5863c 100644 --- a/tests/fail/stacked_borrows/illegal_read7.stderr +++ b/tests/fail/stacked_borrows/illegal_read7.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/illegal_read7.rs:LL:CC | LL | let _val = *x.get_mut(); | ^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of two-phase retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/illegal_read7.rs:LL:CC | LL | let x = &mut *raw; | ^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a read access --> $DIR/illegal_read7.rs:LL:CC | LL | let _val = ptr::read(raw); diff --git a/tests/fail/stacked_borrows/illegal_read8.stderr b/tests/fail/stacked_borrows/illegal_read8.stderr index ef150e84f274..c962d1c3e403 100644 --- a/tests/fail/stacked_borrows/illegal_read8.stderr +++ b/tests/fail/stacked_borrows/illegal_read8.stderr @@ -9,12 +9,12 @@ LL | let _fail = *y1; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/illegal_read8.rs:LL:CC | LL | let y1: &i32 = mem::transmute(&*x); // launder lifetimes | ^^^^^^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/illegal_read8.rs:LL:CC | LL | *y2 += 1; diff --git a/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr b/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr index 7c77c62575d7..4607a9dbf675 100644 --- a/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr +++ b/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr @@ -9,6 +9,16 @@ LL | let _val = *root2; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a Unique retag at offsets [0x0..0x4] + --> $DIR/illegal_read_despite_exposed1.rs:LL:CC + | +LL | let root2 = &mut *exposed_ptr; + | ^^^^^^^^^^^^^^^^^ +help: was later invalidated at offsets [0x0..0x4] by a write access + --> $DIR/illegal_read_despite_exposed1.rs:LL:CC + | +LL | *exposed_ptr = 0; + | ^^^^^^^^^^^^^^^^ = note: backtrace: = note: inside `main` at $DIR/illegal_read_despite_exposed1.rs:LL:CC diff --git a/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr b/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr index 4fbbd4c6bede..4bf0df7d0625 100644 --- a/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr +++ b/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr @@ -9,6 +9,16 @@ LL | let _val = *root2; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a Unique retag at offsets [0x0..0x4] + --> $DIR/illegal_read_despite_exposed2.rs:LL:CC + | +LL | let root2 = &mut *exposed_ptr; + | ^^^^^^^^^^^^^^^^^ +help: was later invalidated at offsets [0x0..0x4] by a read access + --> $DIR/illegal_read_despite_exposed2.rs:LL:CC + | +LL | let _val = *exposed_ptr; + | ^^^^^^^^^^^^ = note: backtrace: = note: inside `main` at $DIR/illegal_read_despite_exposed2.rs:LL:CC diff --git a/tests/fail/stacked_borrows/illegal_write1.stderr b/tests/fail/stacked_borrows/illegal_write1.stderr index f93972051692..55ba9aab9bf4 100644 --- a/tests/fail/stacked_borrows/illegal_write1.stderr +++ b/tests/fail/stacked_borrows/illegal_write1.stderr @@ -9,7 +9,7 @@ LL | unsafe { *x = 42 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/illegal_write1.rs:LL:CC | LL | let x: *mut u32 = xref as *const _ as *mut _; diff --git a/tests/fail/stacked_borrows/illegal_write2.stderr b/tests/fail/stacked_borrows/illegal_write2.stderr index 92dacf214f8c..ceb4ce040b89 100644 --- a/tests/fail/stacked_borrows/illegal_write2.stderr +++ b/tests/fail/stacked_borrows/illegal_write2.stderr @@ -9,12 +9,12 @@ LL | unsafe { *target2 = 13 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/illegal_write2.rs:LL:CC | LL | let target2 = target as *mut _; | ^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a Unique retag --> $DIR/illegal_write2.rs:LL:CC | LL | drop(&mut *target); // reborrow diff --git a/tests/fail/stacked_borrows/illegal_write3.stderr b/tests/fail/stacked_borrows/illegal_write3.stderr index bb6d189f8520..e091e25190bb 100644 --- a/tests/fail/stacked_borrows/illegal_write3.stderr +++ b/tests/fail/stacked_borrows/illegal_write3.stderr @@ -9,7 +9,7 @@ LL | unsafe { *ptr = 42 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/illegal_write3.rs:LL:CC | LL | let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag diff --git a/tests/fail/stacked_borrows/illegal_write4.stderr b/tests/fail/stacked_borrows/illegal_write4.stderr index 97301d64deb3..d66585ff7f14 100644 --- a/tests/fail/stacked_borrows/illegal_write4.stderr +++ b/tests/fail/stacked_borrows/illegal_write4.stderr @@ -9,12 +9,12 @@ LL | let _val = *reference; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/illegal_write4.rs:LL:CC | LL | let reference = unsafe { &*raw }; // freeze | ^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a Unique retag --> $DIR/illegal_write4.rs:LL:CC | LL | let _mut_ref: &mut i32 = unsafe { mem::transmute(raw) }; // &mut, with raw tag diff --git a/tests/fail/stacked_borrows/illegal_write5.stderr b/tests/fail/stacked_borrows/illegal_write5.stderr index 9cb32d7bdfd1..319c2d77062c 100644 --- a/tests/fail/stacked_borrows/illegal_write5.stderr +++ b/tests/fail/stacked_borrows/illegal_write5.stderr @@ -9,12 +9,12 @@ LL | let _val = *xref; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/illegal_write5.rs:LL:CC | LL | let xref = unsafe { &mut *xraw }; | ^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/illegal_write5.rs:LL:CC | LL | unsafe { *xraw = 15 }; diff --git a/tests/fail/stacked_borrows/illegal_write6.stderr b/tests/fail/stacked_borrows/illegal_write6.stderr index 42f7b3f8b54b..56576b1ff39b 100644 --- a/tests/fail/stacked_borrows/illegal_write6.stderr +++ b/tests/fail/stacked_borrows/illegal_write6.stderr @@ -6,7 +6,7 @@ LL | unsafe { *y = 2 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/illegal_write6.rs:LL:CC | LL | let p = x as *mut u32; diff --git a/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr b/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr index 0f5834077b3d..aa436b544126 100644 --- a/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr +++ b/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr @@ -9,6 +9,16 @@ LL | let _val = *root2; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] + --> $DIR/illegal_write_despite_exposed1.rs:LL:CC + | +LL | let root2 = &*exposed_ptr; + | ^^^^^^^^^^^^^ +help: was later invalidated at offsets [0x0..0x4] by a write access + --> $DIR/illegal_write_despite_exposed1.rs:LL:CC + | +LL | *exposed_ptr = 0; + | ^^^^^^^^^^^^^^^^ = note: backtrace: = note: inside `main` at $DIR/illegal_write_despite_exposed1.rs:LL:CC diff --git a/tests/fail/stacked_borrows/interior_mut1.rs b/tests/fail/stacked_borrows/interior_mut1.rs index fda203910a44..6911238fc53e 100644 --- a/tests/fail/stacked_borrows/interior_mut1.rs +++ b/tests/fail/stacked_borrows/interior_mut1.rs @@ -12,6 +12,6 @@ fn main() { *c.get() = UnsafeCell::new(1); // invalidates inner_shr // stack: [c: SharedReadWrite] - let _val = *inner_shr.get(); //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + let _val = *inner_shr.get(); //~ ERROR: /retag .* tag does not exist in the borrow stack/ } } diff --git a/tests/fail/stacked_borrows/interior_mut1.stderr b/tests/fail/stacked_borrows/interior_mut1.stderr index a2643841eac1..3aaca3892a54 100644 --- a/tests/fail/stacked_borrows/interior_mut1.stderr +++ b/tests/fail/stacked_borrows/interior_mut1.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/interior_mut1.rs:LL:CC | LL | let _val = *inner_shr.get(); | ^^^^^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/interior_mut1.rs:LL:CC | LL | let inner_shr = &*inner_uniq; // adds a SharedReadWrite | ^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/interior_mut1.rs:LL:CC | LL | *c.get() = UnsafeCell::new(1); // invalidates inner_shr diff --git a/tests/fail/stacked_borrows/interior_mut2.rs b/tests/fail/stacked_borrows/interior_mut2.rs index 7f8c16c488e7..5e9d177cd038 100644 --- a/tests/fail/stacked_borrows/interior_mut2.rs +++ b/tests/fail/stacked_borrows/interior_mut2.rs @@ -25,6 +25,6 @@ fn main() { // stack: [c: SharedReadWrite] // now this does not work any more - let _val = *inner_shr.get(); //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + let _val = *inner_shr.get(); //~ ERROR: /retag .* tag does not exist in the borrow stack/ } } diff --git a/tests/fail/stacked_borrows/interior_mut2.stderr b/tests/fail/stacked_borrows/interior_mut2.stderr index 0dbf6e2ea9f9..b0141cc34fb6 100644 --- a/tests/fail/stacked_borrows/interior_mut2.stderr +++ b/tests/fail/stacked_borrows/interior_mut2.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/interior_mut2.rs:LL:CC | LL | let _val = *inner_shr.get(); | ^^^^^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/interior_mut2.rs:LL:CC | LL | let inner_shr = &*inner_uniq; | ^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/interior_mut2.rs:LL:CC | LL | *c.get() = UnsafeCell::new(0); // now inner_shr gets invalidated diff --git a/tests/fail/stacked_borrows/invalidate_against_barrier1.stderr b/tests/fail/stacked_borrows/invalidate_against_barrier1.stderr index 4a1b14e46094..378f7b7d1ef5 100644 --- a/tests/fail/stacked_borrows/invalidate_against_barrier1.stderr +++ b/tests/fail/stacked_borrows/invalidate_against_barrier1.stderr @@ -6,7 +6,7 @@ LL | let _val = unsafe { *x }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/invalidate_against_barrier1.rs:LL:CC | LL | let xraw = &mut x as *mut _; diff --git a/tests/fail/stacked_borrows/invalidate_against_barrier2.stderr b/tests/fail/stacked_borrows/invalidate_against_barrier2.stderr index c6f158316f51..0352b671823e 100644 --- a/tests/fail/stacked_borrows/invalidate_against_barrier2.stderr +++ b/tests/fail/stacked_borrows/invalidate_against_barrier2.stderr @@ -6,7 +6,7 @@ LL | unsafe { *x = 0 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/invalidate_against_barrier2.rs:LL:CC | LL | let xraw = &mut x as *mut _; diff --git a/tests/fail/stacked_borrows/load_invalid_mut.rs b/tests/fail/stacked_borrows/load_invalid_mut.rs index 4e3a16b96d02..5c99c82da6d6 100644 --- a/tests/fail/stacked_borrows/load_invalid_mut.rs +++ b/tests/fail/stacked_borrows/load_invalid_mut.rs @@ -8,5 +8,5 @@ fn main() { let xref = unsafe { &mut *xraw }; let xref_in_mem = Box::new(xref); let _val = unsafe { *xraw }; // invalidate xref - let _val = *xref_in_mem; //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + let _val = *xref_in_mem; //~ ERROR: /retag .* tag does not exist in the borrow stack/ } diff --git a/tests/fail/stacked_borrows/load_invalid_mut.stderr b/tests/fail/stacked_borrows/load_invalid_mut.stderr index f8e03c631eee..43b6ce8d895e 100644 --- a/tests/fail/stacked_borrows/load_invalid_mut.stderr +++ b/tests/fail/stacked_borrows/load_invalid_mut.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/load_invalid_mut.rs:LL:CC | LL | let _val = *xref_in_mem; | ^^^^^^^^^^^^ | | - | trying to reborrow from for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/load_invalid_mut.rs:LL:CC | LL | let xref_in_mem = Box::new(xref); | ^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a read access --> $DIR/load_invalid_mut.rs:LL:CC | LL | let _val = unsafe { *xraw }; // invalidate xref diff --git a/tests/fail/stacked_borrows/load_invalid_shr.rs b/tests/fail/stacked_borrows/load_invalid_shr.rs index fb279e4710d1..8f94cc07a24f 100644 --- a/tests/fail/stacked_borrows/load_invalid_shr.rs +++ b/tests/fail/stacked_borrows/load_invalid_shr.rs @@ -8,5 +8,5 @@ fn main() { let xref = unsafe { &*xraw }; let xref_in_mem = Box::new(xref); unsafe { *xraw = 42 }; // unfreeze - let _val = *xref_in_mem; //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + let _val = *xref_in_mem; //~ ERROR: /retag .* tag does not exist in the borrow stack/ } diff --git a/tests/fail/stacked_borrows/load_invalid_shr.stderr b/tests/fail/stacked_borrows/load_invalid_shr.stderr index a9546c9a7680..2177ebdd7021 100644 --- a/tests/fail/stacked_borrows/load_invalid_shr.stderr +++ b/tests/fail/stacked_borrows/load_invalid_shr.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/load_invalid_shr.rs:LL:CC | LL | let _val = *xref_in_mem; | ^^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/load_invalid_shr.rs:LL:CC | LL | let xref_in_mem = Box::new(xref); | ^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/load_invalid_shr.rs:LL:CC | LL | unsafe { *xraw = 42 }; // unfreeze diff --git a/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr b/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr index acc904794fb5..42f872eac62f 100644 --- a/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr +++ b/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr @@ -9,12 +9,12 @@ LL | *LEAK = 7; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/mut_exclusive_violation1.rs:LL:CC | LL | LEAK = x as *const _ as *mut _; | ^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/mut_exclusive_violation1.rs:LL:CC | LL | *our = 5; diff --git a/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr b/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr index 5bbf9bc51847..1952172d927b 100644 --- a/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr +++ b/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr @@ -9,12 +9,12 @@ LL | let _val = *raw1; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/mut_exclusive_violation2.rs:LL:CC | LL | let raw1 = ptr1.as_mut(); | ^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a Unique retag --> $DIR/mut_exclusive_violation2.rs:LL:CC | LL | let _raw2 = ptr2.as_mut(); diff --git a/tests/fail/stacked_borrows/newtype_retagging.stderr b/tests/fail/stacked_borrows/newtype_retagging.stderr index d9aebecfda73..2d26787231dc 100644 --- a/tests/fail/stacked_borrows/newtype_retagging.stderr +++ b/tests/fail/stacked_borrows/newtype_retagging.stderr @@ -6,7 +6,7 @@ LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/newtype_retagging.rs:LL:CC | LL | let ptr = Box::into_raw(Box::new(0i32)); diff --git a/tests/fail/stacked_borrows/outdated_local.stderr b/tests/fail/stacked_borrows/outdated_local.stderr index d2ada6458631..e111a8227b2a 100644 --- a/tests/fail/stacked_borrows/outdated_local.stderr +++ b/tests/fail/stacked_borrows/outdated_local.stderr @@ -9,12 +9,12 @@ LL | assert_eq!(unsafe { *y }, 1); | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/outdated_local.rs:LL:CC | LL | let y: *const i32 = &x; | ^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/outdated_local.rs:LL:CC | LL | x = 1; // this invalidates y by reactivating the lowermost uniq borrow for this local diff --git a/tests/fail/stacked_borrows/pass_invalid_mut.rs b/tests/fail/stacked_borrows/pass_invalid_mut.rs index 55c93981e3cd..8db2c149b17e 100644 --- a/tests/fail/stacked_borrows/pass_invalid_mut.rs +++ b/tests/fail/stacked_borrows/pass_invalid_mut.rs @@ -6,5 +6,5 @@ fn main() { let xraw = x as *mut _; let xref = unsafe { &mut *xraw }; let _val = unsafe { *xraw }; // invalidate xref - foo(xref); //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + foo(xref); //~ ERROR: /retag .* tag does not exist in the borrow stack/ } diff --git a/tests/fail/stacked_borrows/pass_invalid_mut.stderr b/tests/fail/stacked_borrows/pass_invalid_mut.stderr index f254fd16dcbe..5fd977805445 100644 --- a/tests/fail/stacked_borrows/pass_invalid_mut.stderr +++ b/tests/fail/stacked_borrows/pass_invalid_mut.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/pass_invalid_mut.rs:LL:CC | LL | foo(xref); | ^^^^ | | - | trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of two-phase retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/pass_invalid_mut.rs:LL:CC | LL | let xref = unsafe { &mut *xraw }; | ^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a read access --> $DIR/pass_invalid_mut.rs:LL:CC | LL | let _val = unsafe { *xraw }; // invalidate xref diff --git a/tests/fail/stacked_borrows/pass_invalid_shr.rs b/tests/fail/stacked_borrows/pass_invalid_shr.rs index db8e6681e0de..903c2733107b 100644 --- a/tests/fail/stacked_borrows/pass_invalid_shr.rs +++ b/tests/fail/stacked_borrows/pass_invalid_shr.rs @@ -6,5 +6,5 @@ fn main() { let xraw = x as *mut _; let xref = unsafe { &*xraw }; unsafe { *xraw = 42 }; // unfreeze - foo(xref); //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + foo(xref); //~ ERROR: /retag .* tag does not exist in the borrow stack/ } diff --git a/tests/fail/stacked_borrows/pass_invalid_shr.stderr b/tests/fail/stacked_borrows/pass_invalid_shr.stderr index 28500836aa8d..0f0df02babb5 100644 --- a/tests/fail/stacked_borrows/pass_invalid_shr.stderr +++ b/tests/fail/stacked_borrows/pass_invalid_shr.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/pass_invalid_shr.rs:LL:CC | LL | foo(xref); | ^^^^ | | - | trying to reborrow from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/pass_invalid_shr.rs:LL:CC | LL | let xref = unsafe { &*xraw }; | ^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a write access --> $DIR/pass_invalid_shr.rs:LL:CC | LL | unsafe { *xraw = 42 }; // unfreeze diff --git a/tests/fail/stacked_borrows/pointer_smuggling.stderr b/tests/fail/stacked_borrows/pointer_smuggling.stderr index 66427bdf64d6..43d689a0f4bb 100644 --- a/tests/fail/stacked_borrows/pointer_smuggling.stderr +++ b/tests/fail/stacked_borrows/pointer_smuggling.stderr @@ -9,12 +9,12 @@ LL | let _x = unsafe { *PTR }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x1] +help: was created by a SharedReadWrite retag at offsets [0x0..0x1] --> $DIR/pointer_smuggling.rs:LL:CC | LL | PTR = x; | ^ -help: was later invalidated at offsets [0x0..0x1] +help: was later invalidated at offsets [0x0..0x1] by a write access --> $DIR/pointer_smuggling.rs:LL:CC | LL | *val = 2; // this invalidates any raw ptrs `fun1` might have created. diff --git a/tests/fail/stacked_borrows/raw_tracking.stderr b/tests/fail/stacked_borrows/raw_tracking.stderr index 2028a9114272..fc846f6d9f6a 100644 --- a/tests/fail/stacked_borrows/raw_tracking.stderr +++ b/tests/fail/stacked_borrows/raw_tracking.stderr @@ -9,12 +9,12 @@ LL | unsafe { *raw1 = 13 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/raw_tracking.rs:LL:CC | LL | let raw1 = &mut l as *mut _; | ^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a Unique retag --> $DIR/raw_tracking.rs:LL:CC | LL | let raw2 = &mut l as *mut _; // invalidates raw1 diff --git a/tests/fail/stacked_borrows/return_invalid_mut.rs b/tests/fail/stacked_borrows/return_invalid_mut.rs index 1f379d4a77e7..7d9a6f11aff9 100644 --- a/tests/fail/stacked_borrows/return_invalid_mut.rs +++ b/tests/fail/stacked_borrows/return_invalid_mut.rs @@ -3,7 +3,7 @@ fn foo(x: &mut (i32, i32)) -> &mut i32 { let xraw = x as *mut (i32, i32); let ret = unsafe { &mut (*xraw).1 }; let _val = unsafe { *xraw }; // invalidate xref - ret //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + ret //~ ERROR: /retag .* tag does not exist in the borrow stack/ } fn main() { diff --git a/tests/fail/stacked_borrows/return_invalid_mut.stderr b/tests/fail/stacked_borrows/return_invalid_mut.stderr index 7c8007044370..c9194208e5dd 100644 --- a/tests/fail/stacked_borrows/return_invalid_mut.stderr +++ b/tests/fail/stacked_borrows/return_invalid_mut.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_mut.rs:LL:CC | LL | ret | ^^^ | | - | trying to reborrow from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x4..0x8] + | trying to retag from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x4..0x8] +help: was created by a Unique retag at offsets [0x4..0x8] --> $DIR/return_invalid_mut.rs:LL:CC | LL | let ret = unsafe { &mut (*xraw).1 }; | ^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x8] +help: was later invalidated at offsets [0x0..0x8] by a read access --> $DIR/return_invalid_mut.rs:LL:CC | LL | let _val = unsafe { *xraw }; // invalidate xref diff --git a/tests/fail/stacked_borrows/return_invalid_mut_option.rs b/tests/fail/stacked_borrows/return_invalid_mut_option.rs index da3401260e1e..7fa9cf77d44b 100644 --- a/tests/fail/stacked_borrows/return_invalid_mut_option.rs +++ b/tests/fail/stacked_borrows/return_invalid_mut_option.rs @@ -10,7 +10,7 @@ fn foo(x: &mut (i32, i32)) -> Option<&mut i32> { fn main() { match foo(&mut (1, 2)) { - Some(_x) => {} //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + Some(_x) => {} //~ ERROR: /retag .* tag does not exist in the borrow stack/ None => {} } } diff --git a/tests/fail/stacked_borrows/return_invalid_mut_option.stderr b/tests/fail/stacked_borrows/return_invalid_mut_option.stderr index cab997b47357..789d0a3aa829 100644 --- a/tests/fail/stacked_borrows/return_invalid_mut_option.stderr +++ b/tests/fail/stacked_borrows/return_invalid_mut_option.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_mut_option.rs:LL:CC | LL | Some(_x) => {} | ^^ | | - | trying to reborrow from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x4..0x8] + | trying to retag from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x4..0x8] +help: was created by a Unique retag at offsets [0x4..0x8] --> $DIR/return_invalid_mut_option.rs:LL:CC | LL | let ret = Some(ret); | ^^^ -help: was later invalidated at offsets [0x0..0x8] +help: was later invalidated at offsets [0x0..0x8] by a read access --> $DIR/return_invalid_mut_option.rs:LL:CC | LL | let _val = unsafe { *xraw }; // invalidate xref diff --git a/tests/fail/stacked_borrows/return_invalid_mut_tuple.rs b/tests/fail/stacked_borrows/return_invalid_mut_tuple.rs index 2184d20b1cfa..c94fef90542f 100644 --- a/tests/fail/stacked_borrows/return_invalid_mut_tuple.rs +++ b/tests/fail/stacked_borrows/return_invalid_mut_tuple.rs @@ -8,5 +8,5 @@ fn foo(x: &mut (i32, i32)) -> (&mut i32,) { } fn main() { - foo(&mut (1, 2)).0; //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + foo(&mut (1, 2)).0; //~ ERROR: /retag .* tag does not exist in the borrow stack/ } diff --git a/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr b/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr index 46ef6a737a63..f7fc75bfd098 100644 --- a/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr +++ b/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_mut_tuple.rs:LL:CC | LL | foo(&mut (1, 2)).0; | ^^^^^^^^^^^^^^^^^^ | | - | trying to reborrow from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x4..0x8] + | trying to retag from for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x4..0x8] +help: was created by a Unique retag at offsets [0x4..0x8] --> $DIR/return_invalid_mut_tuple.rs:LL:CC | LL | let ret = (unsafe { &mut (*xraw).1 },); | ^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x8] +help: was later invalidated at offsets [0x0..0x8] by a read access --> $DIR/return_invalid_mut_tuple.rs:LL:CC | LL | let _val = unsafe { *xraw }; // invalidate xref diff --git a/tests/fail/stacked_borrows/return_invalid_shr.rs b/tests/fail/stacked_borrows/return_invalid_shr.rs index b1d16c025ebf..45526498dadf 100644 --- a/tests/fail/stacked_borrows/return_invalid_shr.rs +++ b/tests/fail/stacked_borrows/return_invalid_shr.rs @@ -3,7 +3,7 @@ fn foo(x: &mut (i32, i32)) -> &i32 { let xraw = x as *mut (i32, i32); let ret = unsafe { &(*xraw).1 }; unsafe { *xraw = (42, 23) }; // unfreeze - ret //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + ret //~ ERROR: /retag .* tag does not exist in the borrow stack/ } fn main() { diff --git a/tests/fail/stacked_borrows/return_invalid_shr.stderr b/tests/fail/stacked_borrows/return_invalid_shr.stderr index 6f745b69fc72..fef83c478fe9 100644 --- a/tests/fail/stacked_borrows/return_invalid_shr.stderr +++ b/tests/fail/stacked_borrows/return_invalid_shr.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_shr.rs:LL:CC | LL | ret | ^^^ | | - | trying to reborrow from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x4..0x8] + | trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x4..0x8] +help: was created by a SharedReadOnly retag at offsets [0x4..0x8] --> $DIR/return_invalid_shr.rs:LL:CC | LL | let ret = unsafe { &(*xraw).1 }; | ^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x8] +help: was later invalidated at offsets [0x0..0x8] by a write access --> $DIR/return_invalid_shr.rs:LL:CC | LL | unsafe { *xraw = (42, 23) }; // unfreeze diff --git a/tests/fail/stacked_borrows/return_invalid_shr_option.rs b/tests/fail/stacked_borrows/return_invalid_shr_option.rs index e9faa945206e..3a028ceed86a 100644 --- a/tests/fail/stacked_borrows/return_invalid_shr_option.rs +++ b/tests/fail/stacked_borrows/return_invalid_shr_option.rs @@ -9,7 +9,7 @@ fn foo(x: &mut (i32, i32)) -> Option<&i32> { fn main() { match foo(&mut (1, 2)) { - Some(_x) => {} //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + Some(_x) => {} //~ ERROR: /retag .* tag does not exist in the borrow stack/ None => {} } } diff --git a/tests/fail/stacked_borrows/return_invalid_shr_option.stderr b/tests/fail/stacked_borrows/return_invalid_shr_option.stderr index 2441c9aa1c51..cc316aaf44ec 100644 --- a/tests/fail/stacked_borrows/return_invalid_shr_option.stderr +++ b/tests/fail/stacked_borrows/return_invalid_shr_option.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_shr_option.rs:LL:CC | LL | Some(_x) => {} | ^^ | | - | trying to reborrow from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x4..0x8] + | trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x4..0x8] +help: was created by a SharedReadOnly retag at offsets [0x4..0x8] --> $DIR/return_invalid_shr_option.rs:LL:CC | LL | let ret = Some(unsafe { &(*xraw).1 }); | ^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x8] +help: was later invalidated at offsets [0x0..0x8] by a write access --> $DIR/return_invalid_shr_option.rs:LL:CC | LL | unsafe { *xraw = (42, 23) }; // unfreeze diff --git a/tests/fail/stacked_borrows/return_invalid_shr_tuple.rs b/tests/fail/stacked_borrows/return_invalid_shr_tuple.rs index 11eb4de56c9f..e4536626dbf2 100644 --- a/tests/fail/stacked_borrows/return_invalid_shr_tuple.rs +++ b/tests/fail/stacked_borrows/return_invalid_shr_tuple.rs @@ -8,5 +8,5 @@ fn foo(x: &mut (i32, i32)) -> (&i32,) { } fn main() { - foo(&mut (1, 2)).0; //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + foo(&mut (1, 2)).0; //~ ERROR: /retag .* tag does not exist in the borrow stack/ } diff --git a/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr b/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr index 5102f7cb53c4..f6be5d0e53a0 100644 --- a/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr +++ b/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> $DIR/return_invalid_shr_tuple.rs:LL:CC | LL | foo(&mut (1, 2)).0; | ^^^^^^^^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x4..0x8] + | trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x4..0x8] +help: was created by a SharedReadOnly retag at offsets [0x4..0x8] --> $DIR/return_invalid_shr_tuple.rs:LL:CC | LL | let ret = (unsafe { &(*xraw).1 },); | ^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x8] +help: was later invalidated at offsets [0x0..0x8] by a write access --> $DIR/return_invalid_shr_tuple.rs:LL:CC | LL | unsafe { *xraw = (42, 23) }; // unfreeze diff --git a/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.rs b/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.rs index 01b2775d9d36..2450ec4b4a1d 100644 --- a/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.rs +++ b/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.rs @@ -11,6 +11,6 @@ fn main() { let y: &mut Cell = mem::transmute(&mut *x); // launder lifetime let shr_rw = &*x; // thanks to interior mutability this will be a SharedReadWrite shr_rw.set(1); - y.get_mut(); //~ ERROR: /reborrow .* tag does not exist in the borrow stack/ + y.get_mut(); //~ ERROR: /retag .* tag does not exist in the borrow stack/ } } diff --git a/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr b/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr index a412add67e02..3f5f2c66ae1f 100644 --- a/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr +++ b/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr @@ -1,20 +1,20 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> $DIR/shared_rw_borrows_are_weak1.rs:LL:CC | LL | y.get_mut(); | ^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x0..0x4] + | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of two-phase retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> $DIR/shared_rw_borrows_are_weak1.rs:LL:CC | LL | let y: &mut Cell = mem::transmute(&mut *x); // launder lifetime | ^^^^^^^^^^^^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] +help: was later invalidated at offsets [0x0..0x4] by a Unique retag --> $DIR/shared_rw_borrows_are_weak1.rs:LL:CC | LL | shr_rw.set(1); diff --git a/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr b/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr index 2c0117577f2e..0a551fe824b5 100644 --- a/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr +++ b/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr @@ -9,12 +9,12 @@ LL | let _val = *y; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [$HEX..$HEX] +help: was created by a SharedReadOnly retag at offsets [$HEX..$HEX] --> $DIR/shared_rw_borrows_are_weak2.rs:LL:CC | LL | let y: &i32 = mem::transmute(&*x.borrow()); // launder lifetime | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: was later invalidated at offsets [$HEX..$HEX] +help: was later invalidated at offsets [$HEX..$HEX] by a Unique retag --> $DIR/shared_rw_borrows_are_weak2.rs:LL:CC | LL | shr_rw.replace(1); diff --git a/tests/fail/stacked_borrows/shr_frozen_violation1.stderr b/tests/fail/stacked_borrows/shr_frozen_violation1.stderr index 47799b18e1f9..9ae8461e13ea 100644 --- a/tests/fail/stacked_borrows/shr_frozen_violation1.stderr +++ b/tests/fail/stacked_borrows/shr_frozen_violation1.stderr @@ -9,7 +9,7 @@ LL | *(x as *const i32 as *mut i32) = 7; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x4] +help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> $DIR/shr_frozen_violation1.rs:LL:CC | LL | *(x as *const i32 as *mut i32) = 7; diff --git a/tests/fail/stacked_borrows/track_caller.rs b/tests/fail/stacked_borrows/track_caller.rs new file mode 100644 index 000000000000..3455eb4684ea --- /dev/null +++ b/tests/fail/stacked_borrows/track_caller.rs @@ -0,0 +1,17 @@ +// This is a copy of illegal_read1.rs, but with #[track_caller] on the test. +// This test only checks that our diagnostics do not display the contents of callee. + +#[rustfmt::skip] // rustfmt bug: https://github.com/rust-lang/rustfmt/issues/5391 +fn main() { + let mut x = 15; + let xraw = &mut x as *mut _; + let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still ok... + callee(xraw); + let _val = *xref; // ...but any use of raw will invalidate our ref. + //~^ ERROR: /read access .* tag does not exist in the borrow stack/ +} + +#[track_caller] +fn callee(xraw: *mut i32) { + let _val = unsafe { *xraw }; +} diff --git a/tests/fail/stacked_borrows/track_caller.stderr b/tests/fail/stacked_borrows/track_caller.stderr new file mode 100644 index 000000000000..5ad22305910a --- /dev/null +++ b/tests/fail/stacked_borrows/track_caller.stderr @@ -0,0 +1,28 @@ +error: Undefined Behavior: attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + --> $DIR/track_caller.rs:LL:CC + | +LL | let _val = *xref; // ...but any use of raw will invalidate our ref. + | ^^^^^ + | | + | attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of an access at ALLOC[0x0..0x4] + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a Unique retag at offsets [0x0..0x4] + --> $DIR/track_caller.rs:LL:CC + | +LL | let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still ok... + | ^^^^^^^^^^ +help: was later invalidated at offsets [0x0..0x4] by a read access + --> $DIR/track_caller.rs:LL:CC + | +LL | callee(xraw); + | ^^^^^^^^^^^^ + = note: backtrace: + = note: inside `main` at $DIR/track_caller.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/tests/fail/stacked_borrows/transmute-is-no-escape.stderr b/tests/fail/stacked_borrows/transmute-is-no-escape.stderr index b48abb3df709..eaac77034cce 100644 --- a/tests/fail/stacked_borrows/transmute-is-no-escape.stderr +++ b/tests/fail/stacked_borrows/transmute-is-no-escape.stderr @@ -9,7 +9,7 @@ LL | unsafe { *raw = 13 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x4..0x8] +help: was created by a SharedReadWrite retag at offsets [0x4..0x8] --> $DIR/transmute-is-no-escape.rs:LL:CC | LL | let raw = (&mut x[1] as *mut i32).wrapping_offset(-1); diff --git a/tests/fail/stacked_borrows/unescaped_static.stderr b/tests/fail/stacked_borrows/unescaped_static.stderr index 018ff77b2e93..7b210ed9314e 100644 --- a/tests/fail/stacked_borrows/unescaped_static.stderr +++ b/tests/fail/stacked_borrows/unescaped_static.stderr @@ -9,7 +9,7 @@ LL | let _val = unsafe { *ptr_to_first.add(1) }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x1] +help: was created by a SharedReadOnly retag at offsets [0x0..0x1] --> $DIR/unescaped_static.rs:LL:CC | LL | let ptr_to_first = &ARRAY[0] as *const u8; diff --git a/tests/fail/stacked_borrows/zst_slice.rs b/tests/fail/stacked_borrows/zst_slice.rs index 11065186fc49..77daa9c9811a 100644 --- a/tests/fail/stacked_borrows/zst_slice.rs +++ b/tests/fail/stacked_borrows/zst_slice.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-strict-provenance -//@error-pattern: /reborrow .* tag does not exist in the borrow stack/ +//@error-pattern: /retag .* tag does not exist in the borrow stack/ fn main() { unsafe { diff --git a/tests/fail/stacked_borrows/zst_slice.stderr b/tests/fail/stacked_borrows/zst_slice.stderr index d47e967b543b..6d0e785cea76 100644 --- a/tests/fail/stacked_borrows/zst_slice.stderr +++ b/tests/fail/stacked_borrows/zst_slice.stderr @@ -1,15 +1,15 @@ -error: Undefined Behavior: trying to reborrow from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location --> RUSTLIB/core/src/slice/mod.rs:LL:CC | LL | unsafe { &*index.get_unchecked(self) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | trying to reborrow from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of a reborrow at ALLOC[0x4..0x8] + | trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a retag at offsets [0x0..0x0] +help: would have been created here, but this is a zero-size retag ([0x0..0x0]) so the tag in question does not exist anywhere --> $DIR/zst_slice.rs:LL:CC | LL | assert_eq!(*s.get_unchecked(1), 2);