]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/miri/src/stacked_borrows/diagnostics.rs
cleanup global imports a bit
[rust.git] / src / tools / miri / src / stacked_borrows / diagnostics.rs
index f307bf11edd362bb21a4836af2aa72e19816904a..023f6005419a603310a4fb44327b3d98c4b61903 100644 (file)
@@ -5,8 +5,9 @@
 use rustc_span::{Span, SpanData};
 use rustc_target::abi::Size;
 
-use crate::helpers::CurrentSpan;
-use crate::stacked_borrows::{err_sb_ub, AccessKind, GlobalStateInner, Permission, ProtectorKind};
+use crate::stacked_borrows::{
+    err_sb_ub, AccessKind, GlobalStateInner, Permission, ProtectorKind, Stack,
+};
 use crate::*;
 
 use rustc_middle::mir::interpret::InterpError;
@@ -110,42 +111,29 @@ pub struct TagHistory {
     pub protected: Option<(String, SpanData)>,
 }
 
-pub struct DiagnosticCxBuilder<'span, 'ecx, 'mir, 'tcx> {
+pub struct DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
     operation: Operation,
-    // 'span cannot be merged with any other lifetime since they appear invariantly, under the
-    // mutable ref.
-    current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
-    threads: &'ecx ThreadManager<'mir, 'tcx>,
+    machine: &'ecx MiriMachine<'mir, 'tcx>,
 }
 
-pub struct DiagnosticCx<'span, 'history, 'ecx, 'mir, 'tcx> {
+pub struct DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
     operation: Operation,
-    // 'span and 'history cannot be merged, since when we call `unbuild` we need
-    // to return the exact 'span that was used when calling `build`.
-    current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
-    threads: &'ecx ThreadManager<'mir, 'tcx>,
+    machine: &'ecx MiriMachine<'mir, 'tcx>,
     history: &'history mut AllocHistory,
     offset: Size,
 }
 
-impl<'span, 'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'span, 'ecx, 'mir, 'tcx> {
+impl<'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
     pub fn build<'history>(
         self,
         history: &'history mut AllocHistory,
         offset: Size,
-    ) -> DiagnosticCx<'span, 'history, 'ecx, 'mir, 'tcx> {
-        DiagnosticCx {
-            operation: self.operation,
-            current_span: self.current_span,
-            threads: self.threads,
-            history,
-            offset,
-        }
+    ) -> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
+        DiagnosticCx { operation: self.operation, machine: self.machine, history, offset }
     }
 
     pub fn retag(
-        current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
-        threads: &'ecx ThreadManager<'mir, 'tcx>,
+        machine: &'ecx MiriMachine<'mir, 'tcx>,
         cause: RetagCause,
         new_tag: SbTag,
         orig_tag: ProvenanceExtra,
@@ -154,46 +142,36 @@ pub fn retag(
         let operation =
             Operation::Retag(RetagOp { cause, new_tag, orig_tag, range, permission: None });
 
-        DiagnosticCxBuilder { current_span, threads, operation }
+        DiagnosticCxBuilder { machine, operation }
     }
 
     pub fn read(
-        current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
-        threads: &'ecx ThreadManager<'mir, 'tcx>,
+        machine: &'ecx MiriMachine<'mir, 'tcx>,
         tag: ProvenanceExtra,
         range: AllocRange,
     ) -> Self {
         let operation = Operation::Access(AccessOp { kind: AccessKind::Read, tag, range });
-        DiagnosticCxBuilder { current_span, threads, operation }
+        DiagnosticCxBuilder { machine, operation }
     }
 
     pub fn write(
-        current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
-        threads: &'ecx ThreadManager<'mir, 'tcx>,
+        machine: &'ecx MiriMachine<'mir, 'tcx>,
         tag: ProvenanceExtra,
         range: AllocRange,
     ) -> Self {
         let operation = Operation::Access(AccessOp { kind: AccessKind::Write, tag, range });
-        DiagnosticCxBuilder { current_span, threads, operation }
+        DiagnosticCxBuilder { machine, operation }
     }
 
-    pub fn dealloc(
-        current_span: &'span mut CurrentSpan<'ecx, 'mir, 'tcx>,
-        threads: &'ecx ThreadManager<'mir, 'tcx>,
-        tag: ProvenanceExtra,
-    ) -> Self {
+    pub fn dealloc(machine: &'ecx MiriMachine<'mir, 'tcx>, tag: ProvenanceExtra) -> Self {
         let operation = Operation::Dealloc(DeallocOp { tag });
-        DiagnosticCxBuilder { current_span, threads, operation }
+        DiagnosticCxBuilder { machine, operation }
     }
 }
 
-impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir, 'tcx> {
-    pub fn unbuild(self) -> DiagnosticCxBuilder<'span, 'ecx, 'mir, 'tcx> {
-        DiagnosticCxBuilder {
-            operation: self.operation,
-            current_span: self.current_span,
-            threads: self.threads,
-        }
+impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
+    pub fn unbuild(self) -> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
+        DiagnosticCxBuilder { machine: self.machine, operation: self.operation }
     }
 }
 
@@ -234,10 +212,10 @@ struct DeallocOp {
 }
 
 impl AllocHistory {
-    pub fn new(id: AllocId, item: Item, current_span: &mut CurrentSpan<'_, '_, '_>) -> Self {
+    pub fn new(id: AllocId, item: Item, machine: &MiriMachine<'_, '_>) -> Self {
         Self {
             id,
-            base: (item, current_span.get()),
+            base: (item, machine.current_span()),
             creations: SmallVec::new(),
             invalidations: SmallVec::new(),
             protectors: SmallVec::new(),
@@ -245,7 +223,7 @@ pub fn new(id: AllocId, item: Item, current_span: &mut CurrentSpan<'_, '_, '_>)
     }
 }
 
-impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir, 'tcx> {
+impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
     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)
@@ -274,15 +252,17 @@ 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() });
+        self.history
+            .creations
+            .push(Creation { retag: op.clone(), span: self.machine.current_span() });
     }
 
     pub fn log_invalidation(&mut self, tag: SbTag) {
-        let mut span = self.current_span.get();
+        let mut span = self.machine.current_span();
         let (range, cause) = match &self.operation {
             Operation::Retag(RetagOp { cause, range, permission, .. }) => {
                 if *cause == RetagCause::FnEntry {
-                    span = self.current_span.get_caller();
+                    span = self.machine.caller_span();
                 }
                 (*range, InvalidationCause::Retag(permission.unwrap(), *cause))
             }
@@ -301,7 +281,9 @@ 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 { tag: op.new_tag, span: self.current_span.get() });
+        self.history
+            .protectors
+            .push(Protection { tag: op.new_tag, span: self.machine.current_span() });
     }
 
     pub fn get_logs_relevant_to(
@@ -373,10 +355,12 @@ pub fn get_logs_relevant_to(
 
     /// Report a descriptive error when `new` could not be granted from `derived_from`.
     #[inline(never)] // This is only called on fatal code paths
-    pub(super) fn grant_error(&self, perm: Permission, stack: &Stack) -> InterpError<'tcx> {
+    pub(super) fn grant_error(&self, stack: &Stack) -> InterpError<'tcx> {
         let Operation::Retag(op) = &self.operation else {
             unreachable!("grant_error should only be called during a retag")
         };
+        let perm =
+            op.permission.expect("`start_grant` must be called before calling `grant_error`");
         let action = format!(
             "trying to retag from {:?} for {:?} permission at {:?}[{:#x}]",
             op.orig_tag,
@@ -394,8 +378,11 @@ pub(super) fn grant_error(&self, perm: Permission, stack: &Stack) -> InterpError
     /// Report a descriptive error when `access` is not permitted based on `tag`.
     #[inline(never)] // This is only called on fatal code paths
     pub(super) 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")
+        // Deallocation and retagging also do an access as part of their thing, so handle that here, too.
+        let op = match &self.operation {
+            Operation::Access(op) => op,
+            Operation::Retag(_) => return self.grant_error(stack),
+            Operation::Dealloc(_) => return self.dealloc_error(stack),
         };
         let action = format!(
             "attempting a {access} using {tag:?} at {alloc_id:?}[{offset:#x}]",
@@ -418,6 +405,7 @@ pub(super) fn protector_error(&self, item: &Item, kind: ProtectorKind) -> Interp
             ProtectorKind::StrongProtector => "strongly protected",
         };
         let call_id = self
+            .machine
             .threads
             .all_stacks()
             .flatten()
@@ -447,14 +435,16 @@ pub(super) fn protector_error(&self, item: &Item, kind: ProtectorKind) -> Interp
     }
 
     #[inline(never)] // This is only called on fatal code paths
-    pub fn dealloc_error(&self) -> InterpError<'tcx> {
+    pub fn dealloc_error(&self, stack: &Stack) -> 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,
+                "attempting deallocation using {tag:?} at {alloc_id:?}{cause}",
+                tag = op.tag,
+                alloc_id = self.history.id,
+                cause = error_cause(stack, op.tag),
             ),
             None,
             op.tag.and_then(|tag| self.get_logs_relevant_to(tag, None)),
@@ -482,9 +472,7 @@ pub fn check_tracked_tag_popped(&self, item: &Item, global: &GlobalStateInner) {
                 Some((orig_tag, kind))
             }
         };
-        self.current_span
-            .machine()
-            .emit_diagnostic(NonHaltingDiagnostic::PoppedPointerTag(*item, summary));
+        self.machine.emit_diagnostic(NonHaltingDiagnostic::PoppedPointerTag(*item, summary));
     }
 }