From b75ba509f54add50b1af8b73de59e73aca7d2767 Mon Sep 17 00:00:00 2001 From: OneProg Date: Wed, 30 Jul 2025 20:37:42 +0300 Subject: [PATCH 1/5] The text of the error that occurs when the order of formatting arguments is incorrect is clearer --- compiler/rustc_parse_format/src/lib.rs | 7 +- .../clippy_lints/src/disallowed_macros.rs | 1 - .../src/needless_pass_by_value.rs | 4 +- src/tools/miri/cargo-miri/src/arg.rs | 28 ++-- src/tools/miri/cargo-miri/src/phases.rs | 7 +- src/tools/miri/cargo-miri/src/setup.rs | 9 +- src/tools/miri/src/alloc/alloc_bytes.rs | 5 +- src/tools/miri/src/bin/log/tracing_chrome.rs | 55 ++------ src/tools/miri/src/bin/miri.rs | 19 ++- src/tools/miri/src/borrow_tracker/mod.rs | 74 +++++----- .../stacked_borrows/diagnostics.rs | 38 ++--- .../borrow_tracker/stacked_borrows/stack.rs | 5 +- .../tree_borrows/diagnostics.rs | 8 +- .../src/borrow_tracker/tree_borrows/mod.rs | 58 ++++---- .../src/borrow_tracker/tree_borrows/perms.rs | 47 ++++--- .../borrow_tracker/tree_borrows/tree/tests.rs | 46 +++--- src/tools/miri/src/clock.rs | 20 +-- src/tools/miri/src/concurrency/data_race.rs | 5 +- src/tools/miri/src/concurrency/thread.rs | 73 +++++----- .../miri/src/concurrency/vector_clock.rs | 28 ++-- .../src/data_structures/range_object_map.rs | 5 +- src/tools/miri/src/diagnostics.rs | 121 ++++++++-------- src/tools/miri/src/eval.rs | 54 ++++--- src/tools/miri/src/helpers.rs | 43 +++--- src/tools/miri/src/intrinsics/atomic.rs | 15 +- src/tools/miri/src/intrinsics/mod.rs | 30 ++-- src/tools/miri/src/machine.rs | 29 ++-- src/tools/miri/src/math.rs | 20 +-- src/tools/miri/src/shims/backtrace.rs | 5 +- src/tools/miri/src/shims/foreign_items.rs | 20 +-- src/tools/miri/src/shims/global_ctor.rs | 23 +-- src/tools/miri/src/shims/io_error.rs | 25 ++-- src/tools/miri/src/shims/native_lib/mod.rs | 15 +- .../miri/src/shims/native_lib/trace/child.rs | 9 +- .../miri/src/shims/native_lib/trace/parent.rs | 132 +++++++++--------- src/tools/miri/src/shims/time.rs | 10 +- .../miri/src/shims/unix/foreign_items.rs | 66 ++++----- .../src/shims/unix/freebsd/foreign_items.rs | 7 +- src/tools/miri/src/shims/unix/fs.rs | 51 ++++--- src/tools/miri/src/shims/unix/macos/sync.rs | 20 ++- src/tools/miri/src/shims/unix/sync.rs | 36 ++--- src/tools/miri/src/shims/windows/handle.rs | 15 +- src/tools/miri/src/shims/x86/avx.rs | 5 +- 43 files changed, 660 insertions(+), 633 deletions(-) diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 8e4da7923fcb5..40055b6f4272f 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -859,8 +859,11 @@ impl<'input> Parser<'input> { 0, ParseError { description: "expected format parameter to occur after `:`".to_owned(), - note: None, - label: format!("expected `{}` to occur after `:`", alignment), + note: Some( + "See https://doc.rust-lang.org/std/fmt/index.html#syntax for more details" + .to_string(), + ), + label: format!("expected `{}` to occur in its correct place", alignment), span: range, secondary_label: None, suggestion: Suggestion::None, diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs index 23e7c7251cf15..044903ce57537 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs @@ -1,4 +1,3 @@ - use clippy_config::Conf; use clippy_config::types::{DisallowedPath, create_disallowed_map}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 7b057998063f9..a28e9a279d708 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -311,9 +311,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { /// Functions marked with these attributes must have the exact signature. pub(crate) fn requires_exact_signature(attrs: &[Attribute]) -> bool { - attrs.iter().any(|attr| { - attr.is_proc_macro_attr() - }) + attrs.iter().any(|attr| attr.is_proc_macro_attr()) } #[derive(Default)] diff --git a/src/tools/miri/cargo-miri/src/arg.rs b/src/tools/miri/cargo-miri/src/arg.rs index d7216060358cb..2f9723e87c9f5 100644 --- a/src/tools/miri/cargo-miri/src/arg.rs +++ b/src/tools/miri/cargo-miri/src/arg.rs @@ -45,7 +45,7 @@ impl<'s, I: Iterator>> Iterator for ArgSplitFlagValue<'_, I> } // These branches cannot be merged if we want to avoid the allocation in the `Borrowed` branch. match &arg { - Cow::Borrowed(arg) => + Cow::Borrowed(arg) => { if let Some(suffix) = arg.strip_prefix(self.name) { // Strip leading `name`. if suffix.is_empty() { @@ -55,8 +55,9 @@ impl<'s, I: Iterator>> Iterator for ArgSplitFlagValue<'_, I> // This argument is `name=value`; get the value. return Some(Ok(Cow::Borrowed(suffix))); } - }, - Cow::Owned(arg) => + } + } + Cow::Owned(arg) => { if let Some(suffix) = arg.strip_prefix(self.name) { // Strip leading `name`. if suffix.is_empty() { @@ -67,7 +68,8 @@ impl<'s, I: Iterator>> Iterator for ArgSplitFlagValue<'_, I> // here as a `String` cannot be subsliced (what would the lifetime be?). return Some(Ok(Cow::Owned(suffix.to_owned()))); } - }, + } + } } Some(Err(arg)) } @@ -78,11 +80,9 @@ impl<'a, I: Iterator + 'a> ArgSplitFlagValue<'a, I> { args: I, name: &'a str, ) -> impl Iterator> + 'a { - ArgSplitFlagValue::new(args.map(Cow::Owned), name).map(|x| { - match x { - Ok(s) => Ok(s.into_owned()), - Err(s) => Err(s.into_owned()), - } + ArgSplitFlagValue::new(args.map(Cow::Owned), name).map(|x| match x { + Ok(s) => Ok(s.into_owned()), + Err(s) => Err(s.into_owned()), }) } } @@ -92,12 +92,10 @@ impl<'x: 'a, 'a, I: Iterator + 'a> ArgSplitFlagValue<'a, I> { args: I, name: &'a str, ) -> impl Iterator> + 'a { - ArgSplitFlagValue::new(args.map(Cow::Borrowed), name).map(|x| { - match x { - Ok(Cow::Borrowed(s)) => Ok(s), - Err(Cow::Borrowed(s)) => Err(s), - _ => panic!("iterator converted borrowed to owned"), - } + ArgSplitFlagValue::new(args.map(Cow::Borrowed), name).map(|x| match x { + Ok(Cow::Borrowed(s)) => Ok(s), + Err(Cow::Borrowed(s)) => Err(s), + _ => panic!("iterator converted borrowed to owned"), }) } } diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index efb9053f69a5a..2f413d5eb7b49 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -85,10 +85,9 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { "setup" => MiriCommand::Setup, "test" | "t" | "run" | "r" | "nextest" => MiriCommand::Forward(subcommand), "clean" => MiriCommand::Clean, - _ => - show_error!( - "`cargo miri` supports the following subcommands: `run`, `test`, `nextest`, `clean`, and `setup`." - ), + _ => show_error!( + "`cargo miri` supports the following subcommands: `run`, `test`, `nextest`, `clean`, and `setup`." + ), }; let verbose = num_arg_flag("-v") + num_arg_flag("--verbose"); let quiet = has_arg_flag("-q") || has_arg_flag("--quiet"); diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index e399f66fbc9cd..7bcb80f9b671c 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -73,10 +73,12 @@ pub fn setup( None => // No-std heuristic taken from rust/src/bootstrap/config.rs // (https://github.com/rust-lang/rust/blob/25b5af1b3a0b9e2c0c57b223b2d0e3e203869b2c/src/bootstrap/config.rs#L549-L555). + { target.contains("-none") || target.contains("nvptx") || target.contains("switch") - || target.contains("-uefi"), + || target.contains("-uefi") + } Some(val) => val != "0", }; let sysroot_config = if no_std { @@ -168,13 +170,14 @@ pub fn setup( .when_build_required(notify) .build_from_source(&rust_src); match status { - Ok(SysrootStatus::AlreadyCached) => + Ok(SysrootStatus::AlreadyCached) => { if !quiet && show_setup { eprintln!( "A sysroot for Miri is already available in `{}`.", sysroot_dir.display() ); - }, + } + } Ok(SysrootStatus::SysrootBuilt) => { // Print what `notify` prepared. eprint!("{after_build_output}"); diff --git a/src/tools/miri/src/alloc/alloc_bytes.rs b/src/tools/miri/src/alloc/alloc_bytes.rs index 5d00d3eafcb5d..edb4b07f8952e 100644 --- a/src/tools/miri/src/alloc/alloc_bytes.rs +++ b/src/tools/miri/src/alloc/alloc_bytes.rs @@ -54,8 +54,9 @@ impl Drop for MiriAllocBytes { unsafe { match self.params.clone() { MiriAllocParams::Global => alloc::dealloc(self.ptr, alloc_layout), - MiriAllocParams::Isolated(alloc) => - alloc.borrow_mut().dealloc(self.ptr, alloc_layout), + MiriAllocParams::Isolated(alloc) => { + alloc.borrow_mut().dealloc(self.ptr, alloc_layout) + } } } } diff --git a/src/tools/miri/src/bin/log/tracing_chrome.rs b/src/tools/miri/src/bin/log/tracing_chrome.rs index 3379816550cfe..5840a33b997a5 100644 --- a/src/tools/miri/src/bin/log/tracing_chrome.rs +++ b/src/tools/miri/src/bin/log/tracing_chrome.rs @@ -25,20 +25,20 @@ // should not be included if the "tracing" feature is disabled. extern crate tracing_core; -use tracing_core::{field::Field, span, Event, Subscriber}; +use tracing_core::{Event, Subscriber, field::Field, span}; use tracing_subscriber::{ + Layer, layer::Context, registry::{LookupSpan, SpanRef}, - Layer, }; -use serde_json::{json, Value as JsonValue}; +use serde_json::{Value as JsonValue, json}; use std::{ marker::PhantomData, path::Path, sync::{ - atomic::{AtomicUsize, Ordering}, Arc, Mutex, + atomic::{AtomicUsize, Ordering}, }, }; @@ -308,10 +308,7 @@ fn create_default_writer() -> Box { Box::new( std::fs::File::create(format!( "./trace-{}.json", - std::time::SystemTime::UNIX_EPOCH - .elapsed() - .unwrap() - .as_micros() + std::time::SystemTime::UNIX_EPOCH.elapsed().unwrap().as_micros() )) .expect("Failed to create trace file."), ) @@ -325,9 +322,7 @@ where let (tx, rx) = mpsc::channel(); OUT.with(|val| val.replace(Some(tx.clone()))); - let out_writer = builder - .out_writer - .unwrap_or_else(|| create_default_writer()); + let out_writer = builder.out_writer.unwrap_or_else(|| create_default_writer()); let handle = std::thread::spawn(move || { let mut write = BufWriter::new(out_writer); @@ -437,10 +432,7 @@ where write.flush().unwrap(); }); - let guard = FlushGuard { - sender: tx.clone(), - handle: Cell::new(Some(handle)), - }; + let guard = FlushGuard { sender: tx.clone(), handle: Cell::new(Some(handle)) }; let layer = ChromeLayer { out: Arc::new(Mutex::new(tx)), start: std::time::Instant::now(), @@ -488,19 +480,12 @@ where None } } - EventOrSpan::Span(s) => s - .extensions() - .get::() - .map(|e| &e.args) - .cloned(), + EventOrSpan::Span(s) => s.extensions().get::().map(|e| &e.args).cloned(), }; let name = name.unwrap_or_else(|| meta.name().into()); let target = target.unwrap_or_else(|| meta.target().into()); - let (file, line) = if self.include_locations { - (meta.file(), meta.line()) - } else { - (None, None) - }; + let (file, line) = + if self.include_locations { (meta.file(), meta.line()) } else { (None, None) }; if new_thread { let name = match std::thread::current().name() { @@ -510,14 +495,7 @@ where self.send_message(Message::NewThread(tid, name)); } - Callsite { - tid, - name, - target, - file, - line, - args, - } + Callsite { tid, name, target, file, line, args } } fn get_root_id(&self, span: SpanRef) -> Option { @@ -534,7 +512,7 @@ where } else { None } - }, + } TraceStyle::Async => Some( span.scope() .from_root() @@ -543,7 +521,7 @@ where .unwrap_or(span) .id() .into_u64() - .cast_signed() // the comment above explains the cast + .cast_signed(), // the comment above explains the cast ), } } @@ -622,9 +600,7 @@ where if self.include_args { let mut args = Object::new(); attrs.record(&mut JsonVisitor { object: &mut args }); - ctx.span(id).unwrap().extensions_mut().insert(ArgsWrapper { - args: Arc::new(args), - }); + ctx.span(id).unwrap().extensions_mut().insert(ArgsWrapper { args: Arc::new(args) }); } if let TraceStyle::Threaded = self.trace_style { return; @@ -650,8 +626,7 @@ struct JsonVisitor<'a> { impl<'a> tracing_subscriber::field::Visit for JsonVisitor<'a> { fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) { - self.object - .insert(field.name().to_owned(), format!("{value:?}").into()); + self.object.insert(field.name().to_owned(), format!("{value:?}").into()); } } diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index ae1b25f8857a0..0e670a1feadd9 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -516,10 +516,9 @@ fn main() { Some(BorrowTrackerMethod::TreeBorrows(params)) => { params.precise_interior_mut = false; } - _ => - fatal_error!( - "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-no-precise-interior-mut`" - ), + _ => fatal_error!( + "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-no-precise-interior-mut`" + ), }; } else if arg == "-Zmiri-disable-data-race-detector" { miri_config.data_race_detector = false; @@ -541,12 +540,12 @@ fn main() { "abort" => miri::IsolatedOp::Reject(miri::RejectOpWith::Abort), "hide" => miri::IsolatedOp::Reject(miri::RejectOpWith::NoWarning), "warn" => miri::IsolatedOp::Reject(miri::RejectOpWith::Warning), - "warn-nobacktrace" => - miri::IsolatedOp::Reject(miri::RejectOpWith::WarningWithoutBacktrace), - _ => - fatal_error!( - "-Zmiri-isolation-error must be `abort`, `hide`, `warn`, or `warn-nobacktrace`" - ), + "warn-nobacktrace" => { + miri::IsolatedOp::Reject(miri::RejectOpWith::WarningWithoutBacktrace) + } + _ => fatal_error!( + "-Zmiri-isolation-error must be `abort`, `hide`, `warn`, or `warn-nobacktrace`" + ), }; } else if arg == "-Zmiri-ignore-leaks" { miri_config.ignore_leaks = true; diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index ec6c2c60ca9c6..abb21c8200dda 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -262,14 +262,12 @@ impl GlobalStateInner { ) -> AllocState { let _span = enter_trace_span!(borrow_tracker::new_allocation, ?id, ?alloc_size, ?kind); match self.borrow_tracker_method { - BorrowTrackerMethod::StackedBorrows => - AllocState::StackedBorrows(Box::new(RefCell::new(Stacks::new_allocation( - id, alloc_size, self, kind, machine, - )))), - BorrowTrackerMethod::TreeBorrows { .. } => - AllocState::TreeBorrows(Box::new(RefCell::new(Tree::new_allocation( - id, alloc_size, self, kind, machine, - )))), + BorrowTrackerMethod::StackedBorrows => AllocState::StackedBorrows(Box::new( + RefCell::new(Stacks::new_allocation(id, alloc_size, self, kind, machine)), + )), + BorrowTrackerMethod::TreeBorrows { .. } => AllocState::TreeBorrows(Box::new( + RefCell::new(Tree::new_allocation(id, alloc_size, self, kind, machine)), + )), } } } @@ -338,8 +336,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.tcx.tcx.dcx().warn("Stacked Borrows does not support named pointers; `miri_pointer_name` is a no-op"); interp_ok(()) } - BorrowTrackerMethod::TreeBorrows { .. } => - this.tb_give_pointer_debug_name(ptr, nth_parent, name), + BorrowTrackerMethod::TreeBorrows { .. } => { + this.tb_give_pointer_debug_name(ptr, nth_parent, name) + } } } @@ -440,16 +439,16 @@ impl AllocState { ) -> InterpResult<'tcx> { let _span = enter_trace_span!(borrow_tracker::before_memory_read, alloc_id = alloc_id.0); match self { - AllocState::StackedBorrows(sb) => - sb.borrow_mut().before_memory_read(alloc_id, prov_extra, range, machine), - AllocState::TreeBorrows(tb) => - tb.borrow_mut().before_memory_access( - AccessKind::Read, - alloc_id, - prov_extra, - range, - machine, - ), + AllocState::StackedBorrows(sb) => { + sb.borrow_mut().before_memory_read(alloc_id, prov_extra, range, machine) + } + AllocState::TreeBorrows(tb) => tb.borrow_mut().before_memory_access( + AccessKind::Read, + alloc_id, + prov_extra, + range, + machine, + ), } } @@ -462,16 +461,16 @@ impl AllocState { ) -> InterpResult<'tcx> { let _span = enter_trace_span!(borrow_tracker::before_memory_write, alloc_id = alloc_id.0); match self { - AllocState::StackedBorrows(sb) => - sb.get_mut().before_memory_write(alloc_id, prov_extra, range, machine), - AllocState::TreeBorrows(tb) => - tb.get_mut().before_memory_access( - AccessKind::Write, - alloc_id, - prov_extra, - range, - machine, - ), + AllocState::StackedBorrows(sb) => { + sb.get_mut().before_memory_write(alloc_id, prov_extra, range, machine) + } + AllocState::TreeBorrows(tb) => tb.get_mut().before_memory_access( + AccessKind::Write, + alloc_id, + prov_extra, + range, + machine, + ), } } @@ -485,10 +484,12 @@ impl AllocState { let _span = enter_trace_span!(borrow_tracker::before_memory_deallocation, alloc_id = alloc_id.0); match self { - AllocState::StackedBorrows(sb) => - sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine), - AllocState::TreeBorrows(tb) => - tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine), + AllocState::StackedBorrows(sb) => { + sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine) + } + AllocState::TreeBorrows(tb) => { + tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine) + } } } @@ -515,8 +516,9 @@ impl AllocState { ); match self { AllocState::StackedBorrows(_sb) => interp_ok(()), - AllocState::TreeBorrows(tb) => - tb.borrow_mut().release_protector(machine, global, tag, alloc_id), + AllocState::TreeBorrows(tb) => { + tb.borrow_mut().release_protector(machine, global, tag, alloc_id) + } } } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 63b18028a5b9d..fed98dfeca7d2 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -96,8 +96,9 @@ 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, info) => - write!(f, "{perm:?} {retag}", retag = info.summary()), + InvalidationCause::Retag(perm, info) => { + write!(f, "{perm:?} {retag}", retag = info.summary()) + } } } } @@ -250,7 +251,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { None => { last_creation.retag.permission = Some(perm); } - Some(previous) => + Some(previous) => { if previous != perm { // 'Split up' the creation event. let previous_range = last_creation.retag.range; @@ -259,7 +260,8 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { new_event.retag.range = alloc_range(self.offset, previous_range.end()); new_event.retag.permission = Some(perm); self.history.creations.push(new_event); - }, + } + } } } @@ -281,8 +283,9 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { } (*range, InvalidationCause::Retag(permission.unwrap(), *info)) } - Operation::Access(AccessOp { kind, range, .. }) => - (*range, InvalidationCause::Access(*kind)), + Operation::Access(AccessOp { kind, range, .. }) => { + (*range, InvalidationCause::Access(*kind)) + } Operation::Dealloc(_) => { // This can be reached, but never be relevant later since the entire allocation is // gone now. @@ -434,17 +437,17 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { ProtectorKind::StrongProtector => "strongly protected", }; match self.operation { - Operation::Dealloc(_) => - err_sb_ub(format!("deallocating while item {item:?} is {protected}",), vec![], None), + Operation::Dealloc(_) => { + err_sb_ub(format!("deallocating while item {item:?} is {protected}",), vec![], None) + } Operation::Retag(RetagOp { orig_tag: tag, .. }) - | Operation::Access(AccessOp { tag, .. }) => - err_sb_ub( - format!( - "not granting access to tag {tag:?} because that would remove {item:?} which is {protected}", - ), - vec![], - tag.and_then(|tag| self.get_logs_relevant_to(tag, Some(item.tag()))), + | Operation::Access(AccessOp { tag, .. }) => err_sb_ub( + format!( + "not granting access to tag {tag:?} because that would remove {item:?} which is {protected}", ), + vec![], + tag.and_then(|tag| self.get_logs_relevant_to(tag, Some(item.tag()))), + ), } } @@ -472,8 +475,9 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { } let cause = match self.operation { Operation::Dealloc(_) => format!(" due to deallocation"), - Operation::Access(AccessOp { kind, tag, .. }) => - format!(" due to {kind:?} access for {tag:?}"), + Operation::Access(AccessOp { kind, tag, .. }) => { + format!(" due to {kind:?} access for {tag:?}") + } Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => { let permission = permission .expect("start_grant should set the current permission before popping a tag"); diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs index dc3370f125104..9dfdcd7fbe243 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs @@ -64,8 +64,9 @@ impl Stack { Permission::Disabled => left.perm() == Permission::SharedReadWrite, // Unique and SharedReadOnly can terminate a SharedReadWrite block, so only remove // them if they are both unreachable and not directly after a SharedReadWrite. - Permission::Unique | Permission::SharedReadOnly => - left.perm() == Permission::SharedReadWrite || tags.contains(&this.tag()), + Permission::Unique | Permission::SharedReadOnly => { + left.perm() == Permission::SharedReadWrite || tags.contains(&this.tag()) + } }; if should_keep { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index 7b4c533cfaed7..537bdfa185899 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -526,11 +526,9 @@ impl DisplayFmt { /// Print extra text if the tag has a protector. fn print_protector(&self, protector: Option<&ProtectorKind>) -> &'static str { protector - .map(|p| { - match *p { - ProtectorKind::WeakProtector => " Weakly protected", - ProtectorKind::StrongProtector => " Strongly protected", - } + .map(|p| match *p { + ProtectorKind::WeakProtector => " Weakly protected", + ProtectorKind::StrongProtector => " Strongly protected", }) .unwrap_or("") } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index ad2a67160f484..eed4908aa4096 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -143,35 +143,30 @@ impl<'tcx> NewPermission { let protector = is_protected.then_some(ProtectorKind::StrongProtector); Some(match mutability { - Mutability::Mut if ty_is_unpin => - NewPermission { - freeze_perm: Permission::new_reserved( - /* ty_is_freeze */ true, - is_protected, - ), - freeze_access: true, - nonfreeze_perm: Permission::new_reserved( - /* ty_is_freeze */ false, - is_protected, - ), - // If we have a mutable reference, then the non-frozen part will - // have state `ReservedIM` or `Reserved`, which can have an initial read access - // performed on it because you cannot have multiple mutable borrows. - nonfreeze_access: true, - protector, - }, - Mutability::Not => - NewPermission { - freeze_perm: Permission::new_frozen(), - freeze_access: true, - nonfreeze_perm: Permission::new_cell(), - // If it is a shared reference, then the non-frozen - // part will have state `Cell`, which should not have an initial access, - // as this can cause data races when using thread-safe data types like - // `Mutex`. - nonfreeze_access: false, - protector, - }, + Mutability::Mut if ty_is_unpin => NewPermission { + freeze_perm: Permission::new_reserved(/* ty_is_freeze */ true, is_protected), + freeze_access: true, + nonfreeze_perm: Permission::new_reserved( + /* ty_is_freeze */ false, + is_protected, + ), + // If we have a mutable reference, then the non-frozen part will + // have state `ReservedIM` or `Reserved`, which can have an initial read access + // performed on it because you cannot have multiple mutable borrows. + nonfreeze_access: true, + protector, + }, + Mutability::Not => NewPermission { + freeze_perm: Permission::new_frozen(), + freeze_access: true, + nonfreeze_perm: Permission::new_cell(), + // If it is a shared reference, then the non-frozen + // part will have state `Cell`, which should not have an initial access, + // as this can cause data races when using thread-safe data types like + // `Mutex`. + nonfreeze_access: false, + protector, + }, _ => return None, }) } @@ -513,8 +508,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, ImmTy<'tcx>> { let this = self.eval_context_mut(); let new_perm = match val.layout.ty.kind() { - &ty::Ref(_, pointee, mutability) => - NewPermission::from_ref_ty(pointee, mutability, kind, this), + &ty::Ref(_, pointee, mutability) => { + NewPermission::from_ref_ty(pointee, mutability, kind, this) + } _ => None, }; if let Some(new_perm) = new_perm { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 38863ca0734a1..b570b91b7aea2 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -167,7 +167,7 @@ mod transition { assert!(!protected); res } - Active => + Active => { if protected { // We wrote, someone else reads -- that's bad. // (Since Active is always initialized, this move-to-protected will mean insta-UB.) @@ -176,7 +176,8 @@ mod transition { // We don't want to disable here to allow read-read reordering: it is crucial // that the foreign read does not invalidate future reads through this tag. Frozen - }, + } + } }) } @@ -470,12 +471,14 @@ pub mod diagnostics { match (self.from, self.to) { (_, Active) => "the first write to a 2-phase borrowed mutable reference", (_, Frozen) => "a loss of write permissions", - (ReservedFrz { conflicted: false }, ReservedFrz { conflicted: true }) => - "a temporary loss of write permissions until function exit", + (ReservedFrz { conflicted: false }, ReservedFrz { conflicted: true }) => { + "a temporary loss of write permissions until function exit" + } (Frozen, Disabled) => "a loss of read permissions", (_, Disabled) => "a loss of read and write permissions", - (old, new) => - unreachable!("Transition from {old:?} to {new:?} should never be possible"), + (old, new) => { + unreachable!("Transition from {old:?} to {new:?} should never be possible") + } } } @@ -532,13 +535,15 @@ pub mod diagnostics { // `Active`, `Reserved`, and `Cell` have all permissions, so a // `ChildAccessForbidden(Reserved | Active)` can never exist. - (_, Active) | (_, ReservedFrz { conflicted: false }) | (_, Cell) => - unreachable!("this permission cannot cause an error"), + (_, Active) | (_, ReservedFrz { conflicted: false }) | (_, Cell) => { + unreachable!("this permission cannot cause an error") + } // No transition has `Reserved { conflicted: false }` or `ReservedIM` // as its `.to` unless it's a noop. `Cell` cannot be in its `.to` // because all child accesses are a noop. - (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => - unreachable!("self is a noop transition"), + (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => { + unreachable!("self is a noop transition") + } // All transitions produced in normal executions (using `apply_access`) // change permissions in the order `Reserved -> Active -> Frozen -> Disabled`. // We assume that the error was triggered on the same location that @@ -546,8 +551,9 @@ pub mod diagnostics { // in the order `self.from < self.to <= insufficient.inner` (Active | Frozen | Disabled, ReservedFrz { .. } | ReservedIM) | (Disabled, Frozen) - | (ReservedFrz { .. }, ReservedIM) => - unreachable!("permissions between self and err must be increasing"), + | (ReservedFrz { .. }, ReservedIM) => { + unreachable!("permissions between self and err must be increasing") + } } } TransitionError::ProtectedDisabled(before_disabled) => { @@ -578,23 +584,24 @@ pub mod diagnostics { (Active, Frozen) => false, (ReservedFrz { conflicted: true }, _) => false, - (_, Disabled) => - unreachable!( - "permission that results in Disabled should not itself be Disabled in the first place" - ), + (_, Disabled) => unreachable!( + "permission that results in Disabled should not itself be Disabled in the first place" + ), // No transition has `Reserved { conflicted: false }` or `ReservedIM` as its `.to` // unless it's a noop. `Cell` cannot be in its `.to` because all child // accesses are a noop. - (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => - unreachable!("self is a noop transition"), + (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => { + unreachable!("self is a noop transition") + } // Permissions only evolve in the order `Reserved -> Active -> Frozen -> Disabled`, // so permissions found must be increasing in the order // `self.from < self.to <= forbidden.from < forbidden.to`. (Disabled, Cell | ReservedFrz { .. } | ReservedIM | Active | Frozen) | (Frozen, Cell | ReservedFrz { .. } | ReservedIM | Active) - | (Active, Cell | ReservedFrz { .. } | ReservedIM) => - unreachable!("permissions between self and err must be increasing"), + | (Active, Cell | ReservedFrz { .. } | ReservedIM) => { + unreachable!("permissions between self and err must be increasing") + } } } // We don't care because protectors evolve independently from diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs index bb3fc2d80b3fa..dede1708e0472 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs @@ -9,12 +9,10 @@ use crate::borrow_tracker::tree_borrows::exhaustive::{Exhaustive, precondition}; impl Exhaustive for LocationState { fn exhaustive() -> Box> { // We keep `latest_foreign_access` at `None` as that's just a cache. - Box::new(<(Permission, bool)>::exhaustive().map(|(permission, accessed)| { - Self { - permission, - accessed, - idempotent_foreign_access: IdempotentForeignAccess::default(), - } + Box::new(<(Permission, bool)>::exhaustive().map(|(permission, accessed)| Self { + permission, + accessed, + idempotent_foreign_access: IdempotentForeignAccess::default(), })) } } @@ -261,18 +259,16 @@ mod spurious_read { fn rel_pair(self, xy_rel: RelPosXY) -> (AccessRelatedness, AccessRelatedness) { use AccessRelatedness::*; match xy_rel { - RelPosXY::MutuallyForeign => - match self { - PtrSelector::X => (This, CousinAccess), - PtrSelector::Y => (CousinAccess, This), - PtrSelector::Other => (CousinAccess, CousinAccess), - }, - RelPosXY::XChildY => - match self { - PtrSelector::X => (This, StrictChildAccess), - PtrSelector::Y => (AncestorAccess, This), - PtrSelector::Other => (CousinAccess, CousinAccess), - }, + RelPosXY::MutuallyForeign => match self { + PtrSelector::X => (This, CousinAccess), + PtrSelector::Y => (CousinAccess, This), + PtrSelector::Other => (CousinAccess, CousinAccess), + }, + RelPosXY::XChildY => match self { + PtrSelector::X => (This, StrictChildAccess), + PtrSelector::Y => (AncestorAccess, This), + PtrSelector::Other => (CousinAccess, CousinAccess), + }, } } } @@ -442,10 +438,9 @@ mod spurious_read { let accessed = match ptr { PtrSelector::X => self.x.state.accessed, PtrSelector::Y => self.y.state.accessed, - PtrSelector::Other => - panic!( - "the `accessed` status of `PtrSelector::Other` is unknown, do not pass it to `read_if_accessed`" - ), + PtrSelector::Other => panic!( + "the `accessed` status of `PtrSelector::Other` is unknown, do not pass it to `read_if_accessed`" + ), }; if accessed { self.perform_test_access(&TestAccess { ptr, kind: AccessKind::Read }) @@ -492,8 +487,11 @@ mod spurious_read { impl Exhaustive for LocStateProtPair { fn exhaustive() -> Box> { Box::new(<[LocStateProt; 2]>::exhaustive().flat_map(|[x, y]| { - RelPosXY::exhaustive() - .map(move |xy_rel| Self { x: x.clone(), y: y.clone(), xy_rel }) + RelPosXY::exhaustive().map(move |xy_rel| Self { + x: x.clone(), + y: y.clone(), + xy_rel, + }) })) } } diff --git a/src/tools/miri/src/clock.rs b/src/tools/miri/src/clock.rs index 34465e9cac60d..4e6f867013079 100644 --- a/src/tools/miri/src/clock.rs +++ b/src/tools/miri/src/clock.rs @@ -39,8 +39,9 @@ impl Instant { pub fn duration_since(&self, earlier: Instant) -> Duration { match (&self.kind, earlier.kind) { - (InstantKind::Host(instant), InstantKind::Host(earlier)) => - instant.duration_since(earlier), + (InstantKind::Host(instant), InstantKind::Host(earlier)) => { + instant.duration_since(earlier) + } ( InstantKind::Virtual { nanoseconds }, InstantKind::Virtual { nanoseconds: earlier }, @@ -122,17 +123,20 @@ impl MonotonicClock { pub fn epoch(&self) -> Instant { match &self.kind { MonotonicClockKind::Host { epoch } => Instant { kind: InstantKind::Host(*epoch) }, - MonotonicClockKind::Virtual { .. } => - Instant { kind: InstantKind::Virtual { nanoseconds: 0 } }, + MonotonicClockKind::Virtual { .. } => { + Instant { kind: InstantKind::Virtual { nanoseconds: 0 } } + } } } pub fn now(&self) -> Instant { match &self.kind { - MonotonicClockKind::Host { .. } => - Instant { kind: InstantKind::Host(StdInstant::now()) }, - MonotonicClockKind::Virtual { nanoseconds } => - Instant { kind: InstantKind::Virtual { nanoseconds: nanoseconds.get() } }, + MonotonicClockKind::Host { .. } => { + Instant { kind: InstantKind::Host(StdInstant::now()) } + } + MonotonicClockKind::Virtual { nanoseconds } => { + Instant { kind: InstantKind::Virtual { nanoseconds: nanoseconds.get() } } + } } } } diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 38d76f5cf73b7..d4c6635dd2e97 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -1041,8 +1041,9 @@ impl VClockAlloc { | MiriMemoryKind::ExternStatic | MiriMemoryKind::Tls, ) - | MemoryKind::CallerLocation => - (VTimestamp::ZERO, global.thread_index(ThreadId::MAIN_THREAD)), + | MemoryKind::CallerLocation => { + (VTimestamp::ZERO, global.thread_index(ThreadId::MAIN_THREAD)) + } }; VClockAlloc { alloc_ranges: RefCell::new(DedupRangeMap::new( diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index fe1ef86ccd31e..86d00e940719c 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -127,8 +127,9 @@ impl<'tcx> std::fmt::Debug for ThreadState<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Enabled => write!(f, "Enabled"), - Self::Blocked { reason, timeout, .. } => - f.debug_struct("Blocked").field("reason", reason).field("timeout", timeout).finish(), + Self::Blocked { reason, timeout, .. } => { + f.debug_struct("Blocked").field("reason", reason).field("timeout", timeout).finish() + } Self::Terminated => write!(f, "Terminated"), } } @@ -354,8 +355,9 @@ impl Timeout { fn get_wait_time(&self, clock: &MonotonicClock) -> Duration { match self { Timeout::Monotonic(instant) => instant.duration_since(clock.now()), - Timeout::RealTime(time) => - time.duration_since(SystemTime::now()).unwrap_or(Duration::ZERO), + Timeout::RealTime(time) => { + time.duration_since(SystemTime::now()).unwrap_or(Duration::ZERO) + } } } @@ -620,12 +622,11 @@ impl<'tcx> ThreadManager<'tcx> { fn next_callback_wait_time(&self, clock: &MonotonicClock) -> Option { self.threads .iter() - .filter_map(|t| { - match &t.state { - ThreadState::Blocked { timeout: Some(timeout), .. } => - Some(timeout.get_wait_time(clock)), - _ => None, + .filter_map(|t| match &t.state { + ThreadState::Blocked { timeout: Some(timeout), .. } => { + Some(timeout.get_wait_time(clock)) } + _ => None, }) .min() } @@ -860,10 +861,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let current_span = this.machine.current_span(); match &mut this.machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Vclocks(data_race) => - data_race.thread_created(&this.machine.threads, new_thread_id, current_span), - GlobalDataRaceHandler::Genmc(genmc_ctx) => - genmc_ctx.handle_thread_create(&this.machine.threads, new_thread_id)?, + GlobalDataRaceHandler::Vclocks(data_race) => { + data_race.thread_created(&this.machine.threads, new_thread_id, current_span) + } + GlobalDataRaceHandler::Genmc(genmc_ctx) => { + genmc_ctx.handle_thread_create(&this.machine.threads, new_thread_id)? + } } // Write the current thread-id, switch to the next thread later // to treat this write operation as occurring on the current thread. @@ -918,10 +921,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { thread.state = ThreadState::Terminated; match &mut this.machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Vclocks(data_race) => - data_race.thread_terminated(&this.machine.threads), - GlobalDataRaceHandler::Genmc(genmc_ctx) => - genmc_ctx.handle_thread_finish(&this.machine.threads)?, + GlobalDataRaceHandler::Vclocks(data_race) => { + data_race.thread_terminated(&this.machine.threads) + } + GlobalDataRaceHandler::Genmc(genmc_ctx) => { + genmc_ctx.handle_thread_finish(&this.machine.threads)? + } } // Deallocate TLS. let gone_thread = this.active_thread(); @@ -940,16 +945,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Now free the TLS statics. for ptr in free_tls_statics { match tls_alloc_action { - TlsAllocAction::Deallocate => - this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?, - TlsAllocAction::Leak => + TlsAllocAction::Deallocate => { + this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())? + } + TlsAllocAction::Leak => { if let Some(alloc) = ptr.provenance.get_alloc_id() { trace!( "Thread-local static leaked and stored as static root: {:?}", alloc ); this.machine.static_roots.push(alloc); - }, + } + } } } } @@ -990,11 +997,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { TimeoutAnchor::Relative => SystemTime::now(), }) } - TimeoutClock::Monotonic => - Timeout::Monotonic(match anchor { - TimeoutAnchor::Absolute => this.machine.monotonic_clock.epoch(), - TimeoutAnchor::Relative => this.machine.monotonic_clock.now(), - }), + TimeoutClock::Monotonic => Timeout::Monotonic(match anchor { + TimeoutAnchor::Absolute => this.machine.monotonic_clock.epoch(), + TimeoutAnchor::Relative => this.machine.monotonic_clock.now(), + }), }; anchor.add_lossy(duration) }); @@ -1059,10 +1065,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let threads = &this.machine.threads; match &mut this.machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Vclocks(data_race) => - data_race.thread_joined(threads, joined_thread_id), - GlobalDataRaceHandler::Genmc(genmc_ctx) => - genmc_ctx.handle_thread_join(threads.active_thread, joined_thread_id)?, + GlobalDataRaceHandler::Vclocks(data_race) => { + data_race.thread_joined(threads, joined_thread_id) + } + GlobalDataRaceHandler::Genmc(genmc_ctx) => { + genmc_ctx.handle_thread_join(threads.active_thread, joined_thread_id)? + } } this.write_scalar(success_retval, return_dest)?; interp_ok(()) @@ -1228,8 +1236,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // See if this thread can do something else. match this.run_on_stack_empty()? { Poll::Pending => {} // keep going - Poll::Ready(()) => - this.terminate_active_thread(TlsAllocAction::Deallocate)?, + Poll::Ready(()) => { + this.terminate_active_thread(TlsAllocAction::Deallocate)? + } } } } diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index 494e7922d2b2b..22807ba996c3f 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -270,14 +270,16 @@ impl PartialOrd for VClock { for (l, r) in iter { match order { Ordering::Equal => order = l.cmp(r), - Ordering::Less => + Ordering::Less => { if l > r { return None; - }, - Ordering::Greater => + } + } + Ordering::Greater => { if l < r { return None; - }, + } + } } } @@ -292,18 +294,16 @@ impl PartialOrd for VClock { Ordering::Equal => Some(order), // Right has at least 1 element > than the implicit 0, // so the only valid values are Ordering::Less or None. - Ordering::Less => - match order { - Ordering::Less | Ordering::Equal => Some(Ordering::Less), - Ordering::Greater => None, - }, + Ordering::Less => match order { + Ordering::Less | Ordering::Equal => Some(Ordering::Less), + Ordering::Greater => None, + }, // Left has at least 1 element > than the implicit 0, // so the only valid values are Ordering::Greater or None. - Ordering::Greater => - match order { - Ordering::Greater | Ordering::Equal => Some(Ordering::Greater), - Ordering::Less => None, - }, + Ordering::Greater => match order { + Ordering::Greater | Ordering::Equal => Some(Ordering::Greater), + Ordering::Less => None, + }, } } diff --git a/src/tools/miri/src/data_structures/range_object_map.rs b/src/tools/miri/src/data_structures/range_object_map.rs index 4c9cf3dc6351b..eab768af13dc3 100644 --- a/src/tools/miri/src/data_structures/range_object_map.rs +++ b/src/tools/miri/src/data_structures/range_object_map.rs @@ -83,14 +83,15 @@ impl RangeObjectMap { // Start of the range doesn't belong to an existing object match self.find_offset(range.end() - Size::from_bytes(1)) { // Neither does the end - Err(end_pos) => + Err(end_pos) => { if pos == end_pos { // There's nothing between the start and the end, so the range thing is empty AccessType::Empty(pos) } else { // Otherwise we have entirely covered an existing object AccessType::ImperfectlyOverlapping(pos..end_pos) - }, + } + } // Otherwise at least part of it overlaps with something else Ok(end_pos) => AccessType::ImperfectlyOverlapping(pos..end_pos + 1), } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 9ecbd31c5b9f9..ec5208f42eb4d 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -69,29 +69,29 @@ impl fmt::Display for TerminationInfo { Abort(msg) => write!(f, "{msg}"), Interrupted => write!(f, "interpretation was interrupted"), UnsupportedInIsolation(msg) => write!(f, "{msg}"), - Int2PtrWithStrictProvenance => - write!( - f, - "integer-to-pointer casts and `ptr::with_exposed_provenance` are not supported with `-Zmiri-strict-provenance`" - ), + Int2PtrWithStrictProvenance => write!( + f, + "integer-to-pointer casts and `ptr::with_exposed_provenance` are not supported with `-Zmiri-strict-provenance`" + ), StackedBorrowsUb { msg, .. } => write!(f, "{msg}"), TreeBorrowsUb { title, .. } => write!(f, "{title}"), Deadlock => write!(f, "the evaluated program deadlocked"), GenmcStuckExecution => write!(f, "GenMC determined that the execution got stuck"), - MultipleSymbolDefinitions { link_name, .. } => - write!(f, "multiple definitions of symbol `{link_name}`"), - SymbolShimClashing { link_name, .. } => - write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",), - DataRace { involves_non_atomic, ptr, op1, op2, .. } => - write!( - f, - "{} detected between (1) {} on {} and (2) {} on {} at {ptr:?}", - if *involves_non_atomic { "Data race" } else { "Race condition" }, - op1.action, - op1.thread_info, - op2.action, - op2.thread_info - ), + MultipleSymbolDefinitions { link_name, .. } => { + write!(f, "multiple definitions of symbol `{link_name}`") + } + SymbolShimClashing { link_name, .. } => { + write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",) + } + DataRace { involves_non_atomic, ptr, op1, op2, .. } => write!( + f, + "{} detected between (1) {} on {} and (2) {} on {} at {ptr:?}", + if *involves_non_atomic { "Data race" } else { "Race condition" }, + op1.action, + op1.thread_info, + op2.action, + op2.thread_info + ), UnsupportedForeignItem(msg) => write!(f, "{msg}"), } } @@ -235,10 +235,12 @@ pub fn report_error<'tcx>( &Exit { code, leak_check } => return Some((code, leak_check)), Abort(_) => Some("abnormal termination"), Interrupted => None, - UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) => - Some("unsupported operation"), - StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } => - Some("Undefined Behavior"), + UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) => { + Some("unsupported operation") + } + StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } => { + Some("Undefined Behavior") + } Deadlock => { labels.push(format!("this thread got stuck here")); None @@ -626,51 +628,59 @@ impl<'tcx> MiriMachine<'tcx> { let (stacktrace, _was_pruned) = prune_stacktrace(stacktrace, self); let (label, diag_level) = match &e { - RejectedIsolatedOp(_) => - ("operation rejected by isolation".to_string(), DiagLevel::Warning), + RejectedIsolatedOp(_) => { + ("operation rejected by isolation".to_string(), DiagLevel::Warning) + } Int2Ptr { .. } => ("integer-to-pointer cast".to_string(), DiagLevel::Warning), - NativeCallSharedMem { .. } => - ("sharing memory with a native function".to_string(), DiagLevel::Warning), - ExternTypeReborrow => - ("reborrow of reference to `extern type`".to_string(), DiagLevel::Warning), + NativeCallSharedMem { .. } => { + ("sharing memory with a native function".to_string(), DiagLevel::Warning) + } + ExternTypeReborrow => { + ("reborrow of reference to `extern type`".to_string(), DiagLevel::Warning) + } CreatedPointerTag(..) | PoppedPointerTag(..) | CreatedAlloc(..) | AccessedAlloc(..) | FreedAlloc(..) | ProgressReport { .. } - | WeakMemoryOutdatedLoad { .. } => - ("tracking was triggered here".to_string(), DiagLevel::Note), + | WeakMemoryOutdatedLoad { .. } => { + ("tracking was triggered here".to_string(), DiagLevel::Note) + } }; let title = match &e { CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"), - CreatedPointerTag(tag, Some(perm), None) => - format!("created {tag:?} with {perm} derived from unknown tag"), - CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) => - format!( - "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}" - ), + CreatedPointerTag(tag, Some(perm), None) => { + format!("created {tag:?} with {perm} derived from unknown tag") + } + CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) => format!( + "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}" + ), PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"), - CreatedAlloc(AllocId(id), size, align, kind) => - format!( - "created {kind} allocation of {size} bytes (alignment {align} bytes) with id {id}", - size = size.bytes(), - align = align.bytes(), - ), - AccessedAlloc(AllocId(id), access_kind) => - format!("{access_kind} to allocation with id {id}"), + CreatedAlloc(AllocId(id), size, align, kind) => format!( + "created {kind} allocation of {size} bytes (alignment {align} bytes) with id {id}", + size = size.bytes(), + align = align.bytes(), + ), + AccessedAlloc(AllocId(id), access_kind) => { + format!("{access_kind} to allocation with id {id}") + } FreedAlloc(AllocId(id)) => format!("freed allocation with id {id}"), RejectedIsolatedOp(op) => format!("{op} was made to return an error due to isolation"), - ProgressReport { .. } => - format!("progress report: current operation being executed is here"), + ProgressReport { .. } => { + format!("progress report: current operation being executed is here") + } Int2Ptr { .. } => format!("integer-to-pointer cast"), - NativeCallSharedMem { .. } => - format!("sharing memory with a native function called via FFI"), - WeakMemoryOutdatedLoad { ptr } => - format!("weak memory emulation: outdated value returned from load at {ptr}"), - ExternTypeReborrow => - format!("reborrow of a reference to `extern type` is not properly supported"), + NativeCallSharedMem { .. } => { + format!("sharing memory with a native function called via FFI") + } + WeakMemoryOutdatedLoad { ptr } => { + format!("weak memory emulation: outdated value returned from load at {ptr}") + } + ExternTypeReborrow => { + format!("reborrow of a reference to `extern type` is not properly supported") + } }; let notes = match &e { @@ -712,7 +722,7 @@ impl<'tcx> MiriMachine<'tcx> { } v } - NativeCallSharedMem { tracing } => + NativeCallSharedMem { tracing } => { if *tracing { vec![ note!( @@ -746,7 +756,8 @@ impl<'tcx> MiriMachine<'tcx> { "what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free" ), ] - }, + } + } ExternTypeReborrow => { assert!(self.borrow_tracker.as_ref().is_some_and(|b| { matches!( diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 4c531a8d1f526..d292bed8457b2 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -257,37 +257,35 @@ impl<'tcx> MainThreadState<'tcx> { Running => { *self = TlsDtors(Default::default()); } - TlsDtors(state) => - match state.on_stack_empty(this)? { - Poll::Pending => {} // just keep going - Poll::Ready(()) => { - if this.machine.data_race.as_genmc_ref().is_some() { - // In GenMC mode, we don't yield at the end of the main thread. - // Instead, the `GenmcCtx` will ensure that unfinished threads get a chance to run at this point. - *self = Done; + TlsDtors(state) => match state.on_stack_empty(this)? { + Poll::Pending => {} // just keep going + Poll::Ready(()) => { + if this.machine.data_race.as_genmc_ref().is_some() { + // In GenMC mode, we don't yield at the end of the main thread. + // Instead, the `GenmcCtx` will ensure that unfinished threads get a chance to run at this point. + *self = Done; + } else { + // Give background threads a chance to finish by yielding the main thread a + // couple of times -- but only if we would also preempt threads randomly. + if this.machine.preemption_rate > 0.0 { + // There is a non-zero chance they will yield back to us often enough to + // make Miri terminate eventually. + *self = Yield { remaining: MAIN_THREAD_YIELDS_AT_SHUTDOWN }; } else { - // Give background threads a chance to finish by yielding the main thread a - // couple of times -- but only if we would also preempt threads randomly. - if this.machine.preemption_rate > 0.0 { - // There is a non-zero chance they will yield back to us often enough to - // make Miri terminate eventually. - *self = Yield { remaining: MAIN_THREAD_YIELDS_AT_SHUTDOWN }; - } else { - // The other threads did not get preempted, so no need to yield back to - // them. - *self = Done; - } + // The other threads did not get preempted, so no need to yield back to + // them. + *self = Done; } } - }, - Yield { remaining } => - match remaining.checked_sub(1) { - None => *self = Done, - Some(new_remaining) => { - *remaining = new_remaining; - this.yield_active_thread(); - } - }, + } + }, + Yield { remaining } => match remaining.checked_sub(1) { + None => *self = Done, + Some(new_remaining) => { + *remaining = new_remaining; + this.yield_active_thread(); + } + }, Done => { // Figure out exit code. let ret_place = this.machine.main_fn_ret_place.clone().unwrap(); diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index ab7e35710d349..e170bdb168b4f 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -582,8 +582,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn visit_value(&mut self, v: &MPlaceTy<'tcx>) -> InterpResult<'tcx> { trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty); let is_unsafe_cell = match v.layout.ty.kind() { - ty::Adt(adt, _) => - Some(adt.did()) == self.ecx.tcx.lang_items().unsafe_cell_type(), + ty::Adt(adt, _) => { + Some(adt.did()) == self.ecx.tcx.lang_items().unsafe_cell_type() + } _ => false, }; if is_unsafe_cell { @@ -990,12 +991,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { (Scalar::from_int(res.value, int_size), res.status) } // Nothing else - _ => - span_bug!( - ecx.cur_span(), - "attempted float-to-int conversion with non-int output type {}", - cast_to.ty, - ), + _ => span_bug!( + ecx.cur_span(), + "attempted float-to-int conversion with non-int output type {}", + cast_to.ty, + ), } } @@ -1004,14 +1004,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; let (val, status) = match fty { - FloatTy::F16 => - float_to_int_inner::(this, src.to_scalar().to_f16()?, cast_to, round), - FloatTy::F32 => - float_to_int_inner::(this, src.to_scalar().to_f32()?, cast_to, round), - FloatTy::F64 => - float_to_int_inner::(this, src.to_scalar().to_f64()?, cast_to, round), - FloatTy::F128 => - float_to_int_inner::(this, src.to_scalar().to_f128()?, cast_to, round), + FloatTy::F16 => { + float_to_int_inner::(this, src.to_scalar().to_f16()?, cast_to, round) + } + FloatTy::F32 => { + float_to_int_inner::(this, src.to_scalar().to_f32()?, cast_to, round) + } + FloatTy::F64 => { + float_to_int_inner::(this, src.to_scalar().to_f64()?, cast_to, round) + } + FloatTy::F128 => { + float_to_int_inner::(this, src.to_scalar().to_f128()?, cast_to, round) + } }; if status.intersects( @@ -1097,10 +1101,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { array.push(this.read_immediate(&elem)?); } } - _ => - throw_unsup_format!( - "only function pointers and arrays of function pointers are supported in well-known linker sections" - ), + _ => throw_unsup_format!( + "only function pointers and arrays of function pointers are supported in well-known linker sections" + ), } } interp_ok(()) diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs index bcc3e9ec885fd..1c518282d130d 100644 --- a/src/tools/miri/src/intrinsics/atomic.rs +++ b/src/tools/miri/src/intrinsics/atomic.rs @@ -242,12 +242,15 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { } let old = match atomic_op { - AtomicOp::Min => - this.atomic_min_max_scalar(&place, rhs, /* min */ true, atomic)?, - AtomicOp::Max => - this.atomic_min_max_scalar(&place, rhs, /* min */ false, atomic)?, - AtomicOp::MirOp(op, not) => - this.atomic_rmw_op_immediate(&place, &rhs, op, not, atomic)?, + AtomicOp::Min => { + this.atomic_min_max_scalar(&place, rhs, /* min */ true, atomic)? + } + AtomicOp::Max => { + this.atomic_min_max_scalar(&place, rhs, /* min */ false, atomic)? + } + AtomicOp::MirOp(op, not) => { + this.atomic_rmw_op_immediate(&place, &rhs, op, not, atomic)? + } }; this.write_immediate(*old, dest)?; // old value is returned interp_ok(()) diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index b5e81460773ba..a163161186fea 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -497,14 +497,18 @@ fn apply_random_float_error_to_imm<'tcx>( ) -> InterpResult<'tcx, ImmTy<'tcx>> { let scalar = val.to_scalar_int()?; let res: ScalarInt = match val.layout.ty.kind() { - ty::Float(FloatTy::F16) => - apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into(), - ty::Float(FloatTy::F32) => - apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into(), - ty::Float(FloatTy::F64) => - apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into(), - ty::Float(FloatTy::F128) => - apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into(), + ty::Float(FloatTy::F16) => { + apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into() + } + ty::Float(FloatTy::F32) => { + apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into() + } + ty::Float(FloatTy::F64) => { + apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into() + } + ty::Float(FloatTy::F128) => { + apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into() + } _ => bug!("intrinsic called with non-float input type"), }; @@ -607,11 +611,13 @@ fn fixed_powi_float_value( fn clamp_float_value(intrinsic_name: &str, val: IeeeFloat) -> IeeeFloat { match intrinsic_name { // sin and cos: [-1, 1] - "sinf32" | "cosf32" | "sinf64" | "cosf64" => - val.clamp(IeeeFloat::::one().neg(), IeeeFloat::::one()), + "sinf32" | "cosf32" | "sinf64" | "cosf64" => { + val.clamp(IeeeFloat::::one().neg(), IeeeFloat::::one()) + } // exp: [0, +INF] - "expf32" | "exp2f32" | "expf64" | "exp2f64" => - IeeeFloat::::maximum(val, IeeeFloat::::ZERO), + "expf32" | "exp2f32" | "expf64" | "exp2f64" => { + IeeeFloat::::maximum(val, IeeeFloat::::ZERO) + } _ => val, } } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 8f0814a070cbf..095ce003574d7 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -837,17 +837,16 @@ impl<'tcx> MiriMachine<'tcx> { let data_race = match &ecx.machine.data_race { GlobalDataRaceHandler::None => AllocDataRaceHandler::None, - GlobalDataRaceHandler::Vclocks(data_race) => - AllocDataRaceHandler::Vclocks( - data_race::AllocState::new_allocation( - data_race, - &ecx.machine.threads, - size, - kind, - ecx.machine.current_span(), - ), - data_race.weak_memory.then(weak_memory::AllocState::new_allocation), + GlobalDataRaceHandler::Vclocks(data_race) => AllocDataRaceHandler::Vclocks( + data_race::AllocState::new_allocation( + data_race, + &ecx.machine.threads, + size, + kind, + ecx.machine.current_span(), ), + data_race.weak_memory.then(weak_memory::AllocState::new_allocation), + ), GlobalDataRaceHandler::Genmc(_genmc_ctx) => { // GenMC learns about new allocations directly from the alloc_addresses module, // since it has to be able to control the address at which they are placed. @@ -1391,8 +1390,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { // The order of checks is deliberate, to prefer reporting a data race over a borrow tracker error. match &machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Genmc(genmc_ctx) => - genmc_ctx.memory_load(machine, ptr.addr(), range.size)?, + GlobalDataRaceHandler::Genmc(genmc_ctx) => { + genmc_ctx.memory_load(machine, ptr.addr(), range.size)? + } GlobalDataRaceHandler::Vclocks(_data_race) => { let AllocDataRaceHandler::Vclocks(data_race, weak_memory) = &alloc_extra.data_race else { @@ -1462,8 +1462,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } match &machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Genmc(genmc_ctx) => - genmc_ctx.handle_dealloc(machine, ptr.addr(), size, align, kind)?, + GlobalDataRaceHandler::Genmc(genmc_ctx) => { + genmc_ctx.handle_dealloc(machine, ptr.addr(), size, align, kind)? + } GlobalDataRaceHandler::Vclocks(_global_state) => { let data_race = alloc_extra.data_race.as_vclocks_mut().unwrap(); data_race.write( diff --git a/src/tools/miri/src/math.rs b/src/tools/miri/src/math.rs index e9e5a1070c9e4..518e213099e2b 100644 --- a/src/tools/miri/src/math.rs +++ b/src/tools/miri/src/math.rs @@ -59,14 +59,18 @@ pub(crate) fn apply_random_float_error_to_imm<'tcx>( ) -> InterpResult<'tcx, ImmTy<'tcx>> { let scalar = val.to_scalar_int()?; let res: ScalarInt = match val.layout.ty.kind() { - ty::Float(FloatTy::F16) => - apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into(), - ty::Float(FloatTy::F32) => - apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into(), - ty::Float(FloatTy::F64) => - apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into(), - ty::Float(FloatTy::F128) => - apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into(), + ty::Float(FloatTy::F16) => { + apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into() + } + ty::Float(FloatTy::F32) => { + apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into() + } + ty::Float(FloatTy::F64) => { + apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into() + } + ty::Float(FloatTy::F128) => { + apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into() + } _ => bug!("intrinsic called with non-float input type"), }; diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index bd3914b652ac9..e20b8780bceb6 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -67,14 +67,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { 0 => { throw_unsup_format!("miri_get_backtrace: v0 is not supported any more"); } - 1 => + 1 => { for (i, ptr) in ptrs.into_iter().enumerate() { let offset = ptr_layout.size.checked_mul(i.to_u64(), this).unwrap(); let op_place = buf_place.offset(offset, ptr_layout, this)?; this.write_pointer(ptr, &op_place)?; - }, + } + } _ => throw_unsup_format!("unknown `miri_get_backtrace` flags {}", flags), }; diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 21545b680299c..1b0d8d063a14a 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -1045,22 +1045,26 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Platform-specific shims - _ => + _ => { return match this.tcx.sess.target.os.as_ref() { - _ if this.target_os_is_unix() => + _ if this.target_os_is_unix() => { shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, - ), - "wasi" => + ) + } + "wasi" => { shims::wasi::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, - ), - "windows" => + ) + } + "windows" => { shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, - ), + ) + } _ => interp_ok(EmulateItemResult::NotSupported), - }, + }; + } }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. diff --git a/src/tools/miri/src/shims/global_ctor.rs b/src/tools/miri/src/shims/global_ctor.rs index c56251bbe63ae..18e9752be577a 100644 --- a/src/tools/miri/src/shims/global_ctor.rs +++ b/src/tools/miri/src/shims/global_ctor.rs @@ -33,17 +33,17 @@ impl<'tcx> GlobalCtorState<'tcx> { // Lookup constructors from the relevant magic link section. let ctors = match this.tcx.sess.target.binary_format { // Read the CRT library section on Windows. - BinaryFormat::Coff => - this.lookup_link_section(|section| section == ".CRT$XCU")?, + BinaryFormat::Coff => { + this.lookup_link_section(|section| section == ".CRT$XCU")? + } // Read the `__mod_init_func` section on macOS. - BinaryFormat::MachO => - this.lookup_link_section(|section| { - let mut parts = section.splitn(3, ','); - let (segment_name, section_name, section_type) = - (parts.next(), parts.next(), parts.next()); + BinaryFormat::MachO => this.lookup_link_section(|section| { + let mut parts = section.splitn(3, ','); + let (segment_name, section_name, section_type) = + (parts.next(), parts.next(), parts.next()); - segment_name == Some("__DATA") + segment_name == Some("__DATA") && section_name == Some("__mod_init_func") // The `mod_init_funcs` directive ensures that the // `S_MOD_INIT_FUNC_POINTERS` flag is set on the section. LLVM @@ -52,13 +52,14 @@ impl<'tcx> GlobalCtorState<'tcx> { // implicitly add it here. Also see // . && matches!(section_type, None | Some("mod_init_funcs")) - })?, + })?, // Read the standard `.init_array` section on platforms that use ELF, or WASM, // which supports the same linker directive. // FIXME: Add support for `.init_array.N` and `.ctors`? - BinaryFormat::Elf | BinaryFormat::Wasm => - this.lookup_link_section(|section| section == ".init_array")?, + BinaryFormat::Elf | BinaryFormat::Wasm => { + this.lookup_link_section(|section| section == ".init_array")? + } // Other platforms have no global ctor support. _ => break 'new_state Done, diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs index e597b527cb7a8..231e98daf1367 100644 --- a/src/tools/miri/src/shims/io_error.rs +++ b/src/tools/miri/src/shims/io_error.rs @@ -17,19 +17,18 @@ pub use self::IoError::*; impl IoError { pub(crate) fn into_ntstatus(self) -> i32 { let raw = match self { - HostError(e) => - match e.kind() { - // STATUS_MEDIA_WRITE_PROTECTED - ErrorKind::ReadOnlyFilesystem => 0xC00000A2u32, - // STATUS_FILE_INVALID - ErrorKind::InvalidInput => 0xC0000098, - // STATUS_DISK_FULL - ErrorKind::QuotaExceeded => 0xC000007F, - // STATUS_ACCESS_DENIED - ErrorKind::PermissionDenied => 0xC0000022, - // For the default error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. - _ => 0xC0000185, - }, + HostError(e) => match e.kind() { + // STATUS_MEDIA_WRITE_PROTECTED + ErrorKind::ReadOnlyFilesystem => 0xC00000A2u32, + // STATUS_FILE_INVALID + ErrorKind::InvalidInput => 0xC0000098, + // STATUS_DISK_FULL + ErrorKind::QuotaExceeded => 0xC000007F, + // STATUS_ACCESS_DENIED + ErrorKind::PermissionDenied => 0xC0000022, + // For the default error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. + _ => 0xC0000185, + }, // For the default error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. _ => 0xC0000185, }; diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs index 2827ed997a7c6..1b7c4e3696cb8 100644 --- a/src/tools/miri/src/shims/native_lib/mod.rs +++ b/src/tools/miri/src/shims/native_lib/mod.rs @@ -144,12 +144,13 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let ptr = Pointer::new(Provenance::Wildcard, Size::from_bytes(x.addr())); Scalar::from_pointer(ptr, this) } - _ => + _ => { return Err(err_unsup_format!( "unsupported return type for native call: {:?}", link_name )) - .into(), + .into(); + } }; interp_ok(ImmTy::from_scalar(scalar, dest.layout)) }) @@ -443,15 +444,17 @@ fn imm_to_carg<'tcx>(v: &ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<' ty::Int(IntTy::I16) => CArg::Int16(v.to_scalar().to_i16()?), ty::Int(IntTy::I32) => CArg::Int32(v.to_scalar().to_i32()?), ty::Int(IntTy::I64) => CArg::Int64(v.to_scalar().to_i64()?), - ty::Int(IntTy::Isize) => - CArg::ISize(v.to_scalar().to_target_isize(cx)?.try_into().unwrap()), + ty::Int(IntTy::Isize) => { + CArg::ISize(v.to_scalar().to_target_isize(cx)?.try_into().unwrap()) + } // the uints ty::Uint(UintTy::U8) => CArg::UInt8(v.to_scalar().to_u8()?), ty::Uint(UintTy::U16) => CArg::UInt16(v.to_scalar().to_u16()?), ty::Uint(UintTy::U32) => CArg::UInt32(v.to_scalar().to_u32()?), ty::Uint(UintTy::U64) => CArg::UInt64(v.to_scalar().to_u64()?), - ty::Uint(UintTy::Usize) => - CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()), + ty::Uint(UintTy::Usize) => { + CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()) + } ty::RawPtr(..) => { let s = v.to_scalar().to_pointer(cx)?.addr(); // This relies on the `expose_provenance` in the `visit_reachable_allocs` callback diff --git a/src/tools/miri/src/shims/native_lib/trace/child.rs b/src/tools/miri/src/shims/native_lib/trace/child.rs index b998ba822dde4..70f62fdfa0fdb 100644 --- a/src/tools/miri/src/shims/native_lib/trace/child.rs +++ b/src/tools/miri/src/shims/native_lib/trace/child.rs @@ -142,11 +142,10 @@ impl Supervisor { let events = sv .event_rx .try_recv_timeout(std::time::Duration::from_secs(5)) - .map_err(|e| { - match e { - ipc::TryRecvError::IpcError(_) => (), - ipc::TryRecvError::Empty => - panic!("Waiting for accesses from supervisor timed out!"), + .map_err(|e| match e { + ipc::TryRecvError::IpcError(_) => (), + ipc::TryRecvError::Empty => { + panic!("Waiting for accesses from supervisor timed out!") } }) .ok(); diff --git a/src/tools/miri/src/shims/native_lib/trace/parent.rs b/src/tools/miri/src/shims/native_lib/trace/parent.rs index 83f6c7a13fcfe..9640fccdd762e 100644 --- a/src/tools/miri/src/shims/native_lib/trace/parent.rs +++ b/src/tools/miri/src/shims/native_lib/trace/parent.rs @@ -120,49 +120,51 @@ impl Iterator for ChildListener { // defensive programming since Linux sometimes assigns threads of // the same process different PIDs with unpredictable rules... match wait::waitid(wait::Id::All, opts) { - Ok(stat) => - match stat { - // Child exited normally with a specific code set. - wait::WaitStatus::Exited(_, code) => self.last_code = Some(code), - // Child was killed by a signal, without giving a code. - wait::WaitStatus::Signaled(_, _, _) => self.last_code = None, - // Child entered or exited a syscall. - wait::WaitStatus::PtraceSyscall(pid) => - if self.attached { - return Some(ExecEvent::Syscall(pid)); - }, - // Child with the given pid was stopped by the given signal. - // It's somewhat dubious when this is returned instead of - // WaitStatus::Stopped, but for our purposes they are the - // same thing. - wait::WaitStatus::PtraceEvent(pid, signal, _) => - if self.attached { - // This is our end-of-FFI signal! - if signal == signal::SIGUSR1 { - self.attached = false; - return Some(ExecEvent::End); - } else { - return Some(ExecEvent::Status(pid, signal)); - } + Ok(stat) => match stat { + // Child exited normally with a specific code set. + wait::WaitStatus::Exited(_, code) => self.last_code = Some(code), + // Child was killed by a signal, without giving a code. + wait::WaitStatus::Signaled(_, _, _) => self.last_code = None, + // Child entered or exited a syscall. + wait::WaitStatus::PtraceSyscall(pid) => { + if self.attached { + return Some(ExecEvent::Syscall(pid)); + } + } + // Child with the given pid was stopped by the given signal. + // It's somewhat dubious when this is returned instead of + // WaitStatus::Stopped, but for our purposes they are the + // same thing. + wait::WaitStatus::PtraceEvent(pid, signal, _) => { + if self.attached { + // This is our end-of-FFI signal! + if signal == signal::SIGUSR1 { + self.attached = false; + return Some(ExecEvent::End); } else { - // Just pass along the signal. - ptrace::cont(pid, signal).unwrap(); - }, - // Child was stopped at the given signal. Same logic as for - // WaitStatus::PtraceEvent. - wait::WaitStatus::Stopped(pid, signal) => - if self.attached { - if signal == signal::SIGUSR1 { - self.attached = false; - return Some(ExecEvent::End); - } else { - return Some(ExecEvent::Status(pid, signal)); - } + return Some(ExecEvent::Status(pid, signal)); + } + } else { + // Just pass along the signal. + ptrace::cont(pid, signal).unwrap(); + } + } + // Child was stopped at the given signal. Same logic as for + // WaitStatus::PtraceEvent. + wait::WaitStatus::Stopped(pid, signal) => { + if self.attached { + if signal == signal::SIGUSR1 { + self.attached = false; + return Some(ExecEvent::End); } else { - ptrace::cont(pid, signal).unwrap(); - }, - _ => (), - }, + return Some(ExecEvent::Status(pid, signal)); + } + } else { + ptrace::cont(pid, signal).unwrap(); + } + } + _ => (), + }, // This case should only trigger when all children died. Err(_) => return Some(ExecEvent::Died(self.override_retcode.or(self.last_code))), } @@ -172,12 +174,14 @@ impl Iterator for ChildListener { match req { TraceRequest::StartFfi(info) => // Should never trigger - but better to panic explicitly than deadlock! + { if self.attached { panic!("Attempting to begin FFI multiple times!"); } else { self.attached = true; return Some(ExecEvent::Start(info)); - }, + } + } TraceRequest::OverrideRetcode(code) => { self.override_retcode = Some(code); self.confirm_tx.send(Confirmation).unwrap(); @@ -265,30 +269,28 @@ pub fn sv_loop( ptrace::cont(curr_pid, None).unwrap(); } // Child process was stopped by a signal - ExecEvent::Status(pid, signal) => - match signal { - // If it was a segfault, check if it was an artificial one - // caused by it trying to access the MiriMachine memory. - signal::SIGSEGV => - handle_segfault( - pid, - &ch_pages, - ch_stack.unwrap(), - page_size, - &cs, - &mut acc_events, - )?, - // Something weird happened. - _ => { - eprintln!("Process unexpectedly got {signal}; continuing..."); - // In case we're not tracing - if ptrace::syscall(pid, None).is_err() { - // If *this* fails too, something really weird happened - // and it's probably best to just panic. - signal::kill(pid, signal::SIGCONT).unwrap(); - } + ExecEvent::Status(pid, signal) => match signal { + // If it was a segfault, check if it was an artificial one + // caused by it trying to access the MiriMachine memory. + signal::SIGSEGV => handle_segfault( + pid, + &ch_pages, + ch_stack.unwrap(), + page_size, + &cs, + &mut acc_events, + )?, + // Something weird happened. + _ => { + eprintln!("Process unexpectedly got {signal}; continuing..."); + // In case we're not tracing + if ptrace::syscall(pid, None).is_err() { + // If *this* fails too, something really weird happened + // and it's probably best to just panic. + signal::kill(pid, signal::SIGCONT).unwrap(); } - }, + } + }, // Child entered a syscall; we wait for exits inside of this, so it // should never trigger on return from a syscall we care about. ExecEvent::Syscall(pid) => { diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index b5b35797fec2f..7855ac776ffe1 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -74,11 +74,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?; system_time_to_duration(&SystemTime::now())? } - Some(TimeoutClock::Monotonic) => - this.machine - .monotonic_clock - .now() - .duration_since(this.machine.monotonic_clock.epoch()), + Some(TimeoutClock::Monotonic) => this + .machine + .monotonic_clock + .now() + .duration_since(this.machine.monotonic_clock.epoch()), None => { return this.set_last_error_and_return(LibcError("EINVAL"), dest); } diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 55906f4eb9548..4365a18f298d9 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -26,15 +26,14 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool { // needed at least on macOS to avoid file-based fallback in getrandom "getentropy" | "getrandom" => true, // Give specific OSes a chance to allow their symbols. - _ => - match target_os { - "android" => android::is_dyn_sym(name), - "freebsd" => freebsd::is_dyn_sym(name), - "linux" => linux::is_dyn_sym(name), - "macos" => macos::is_dyn_sym(name), - "solaris" | "illumos" => solarish::is_dyn_sym(name), - _ => false, - }, + _ => match target_os { + "android" => android::is_dyn_sym(name), + "freebsd" => freebsd::is_dyn_sym(name), + "linux" => linux::is_dyn_sym(name), + "macos" => macos::is_dyn_sym(name), + "solaris" | "illumos" => solarish::is_dyn_sym(name), + _ => false, + }, } } @@ -879,10 +878,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // TODO: when https://github.com/rust-lang/miri/issues/3730 is fixed this should use its notion of tid/pid let thread_id = match pid { 0 => this.active_thread(), - _ => - throw_unsup_format!( - "`sched_getaffinity` is only supported with a pid of 0 (indicating the current thread)" - ), + _ => throw_unsup_format!( + "`sched_getaffinity` is only supported with a pid of 0 (indicating the current thread)" + ), }; // The mask is stored in chunks, and the size must be a whole number of chunks. @@ -917,10 +915,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // TODO: when https://github.com/rust-lang/miri/issues/3730 is fixed this should use its notion of tid/pid let thread_id = match pid { 0 => this.active_thread(), - _ => - throw_unsup_format!( - "`sched_setaffinity` is only supported with a pid of 0 (indicating the current thread)" - ), + _ => throw_unsup_format!( + "`sched_setaffinity` is only supported with a pid of 0 (indicating the current thread)" + ), }; if this.ptr_is_null(mask)? { @@ -1146,26 +1143,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { _ => { let target_os = &*this.tcx.sess.target.os; return match target_os { - "android" => - android::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), - "freebsd" => - freebsd::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), - "linux" => - linux::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), - "macos" => - macos::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), - "solaris" | "illumos" => - solarish::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), + "android" => android::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), + "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), + "linux" => linux::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), + "macos" => macos::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), + "solaris" | "illumos" => solarish::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), _ => interp_ok(EmulateItemResult::NotSupported), }; } diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 9e247053fbcdb..aa4b3b84e2c8c 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -89,10 +89,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // TODO: Use gettid? I'm (LorrensP-2158466) not that familiar with this api . let id = match id { -1 => this.active_thread(), - _ => - throw_unsup_format!( - "`cpuset_getaffinity` is only supported with a pid of -1 (indicating the current thread)" - ), + _ => throw_unsup_format!( + "`cpuset_getaffinity` is only supported with a pid of -1 (indicating the current thread)" + ), }; if this.ptr_is_null(mask)? { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index f9bcacf64c412..27488fa03d212 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -105,12 +105,13 @@ impl UnixFileDescription for FileHandle { match res { Ok(()) => interp_ok(Ok(())), Err(TryLockError::Error(err)) => interp_ok(Err(err)), - Err(TryLockError::WouldBlock) => + Err(TryLockError::WouldBlock) => { if nonblocking { interp_ok(Err(ErrorKind::WouldBlock.into())) } else { throw_unsup_format!("blocking `flock` is not currently supported"); - }, + } + } } } } @@ -186,21 +187,26 @@ trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> { match () { _ if file_type.is_dir() => interp_ok(this.eval_libc("DT_DIR").to_u8()?.into()), _ if file_type.is_file() => interp_ok(this.eval_libc("DT_REG").to_u8()?.into()), - _ if file_type.is_symlink() => - interp_ok(this.eval_libc("DT_LNK").to_u8()?.into()), + _ if file_type.is_symlink() => { + interp_ok(this.eval_libc("DT_LNK").to_u8()?.into()) + } // Certain file types are only supported when the host is a Unix system. #[cfg(unix)] - _ if file_type.is_block_device() => - interp_ok(this.eval_libc("DT_BLK").to_u8()?.into()), + _ if file_type.is_block_device() => { + interp_ok(this.eval_libc("DT_BLK").to_u8()?.into()) + } #[cfg(unix)] - _ if file_type.is_char_device() => - interp_ok(this.eval_libc("DT_CHR").to_u8()?.into()), + _ if file_type.is_char_device() => { + interp_ok(this.eval_libc("DT_CHR").to_u8()?.into()) + } #[cfg(unix)] - _ if file_type.is_fifo() => - interp_ok(this.eval_libc("DT_FIFO").to_u8()?.into()), + _ if file_type.is_fifo() => { + interp_ok(this.eval_libc("DT_FIFO").to_u8()?.into()) + } #[cfg(unix)] - _ if file_type.is_socket() => - interp_ok(this.eval_libc("DT_SOCK").to_u8()?.into()), + _ if file_type.is_socket() => { + interp_ok(this.eval_libc("DT_SOCK").to_u8()?.into()) + } // Fallback _ => interp_ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into()), } @@ -1502,17 +1508,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let fd = this.machine.fds.insert_new(FileHandle { file: f, writable: true }); return interp_ok(Scalar::from_i32(fd)); } - Err(e) => - match e.kind() { - // If the random file already exists, keep trying. - ErrorKind::AlreadyExists => continue, - // Any other errors are returned to the caller. - _ => { - // "On error, -1 is returned, and errno is set to - // indicate the error" - return this.set_last_error_and_return_i32(e); - } - }, + Err(e) => match e.kind() { + // If the random file already exists, keep trying. + ErrorKind::AlreadyExists => continue, + // Any other errors are returned to the caller. + _ => { + // "On error, -1 is returned, and errno is set to + // indicate the error" + return this.set_last_error_and_return_i32(e); + } + }, } } diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 05616dd5a4287..be2d27981ea0b 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -145,12 +145,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { .to_bits(Size::from_bytes(size))?; let futex = this - .get_sync_or_init(ptr, |_| { - MacOsFutex { - futex: Default::default(), - size: Cell::new(size), - shared: Cell::new(is_shared), - } + .get_sync_or_init(ptr, |_| MacOsFutex { + futex: Default::default(), + size: Cell::new(size), + shared: Cell::new(is_shared), }) .unwrap(); @@ -230,12 +228,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let is_shared = flags == shared; - let Some(futex) = this.get_sync_or_init(ptr, |_| { - MacOsFutex { - futex: Default::default(), - size: Cell::new(size), - shared: Cell::new(is_shared), - } + let Some(futex) = this.get_sync_or_init(ptr, |_| MacOsFutex { + futex: Default::default(), + size: Cell::new(size), + shared: Cell::new(is_shared), }) else { // No AllocId, or no live allocation at that AllocId. Return an // error code. (That seems nicer than silently doing something diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 5ad4fd501a607..6b361e680a59f 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -212,12 +212,13 @@ fn mutex_kind_from_static_initializer<'tcx>( } // Support additional platform-specific initializers. match &*ecx.tcx.sess.target.os { - "linux" => + "linux" => { if is_initializer("PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP")? { return interp_ok(MutexKind::Recursive); } else if is_initializer("PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP")? { return interp_ok(MutexKind::ErrorCheck); - }, + } + } _ => {} } throw_unsup_format!("unsupported static initializer used for `pthread_mutex_t`"); @@ -491,10 +492,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { // Trying to acquire the same mutex again. match mutex.kind { - MutexKind::Default => - throw_ub_format!( - "trying to acquire default mutex already locked by the current thread" - ), + MutexKind::Default => throw_ub_format!( + "trying to acquire default mutex already locked by the current thread" + ), MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock), MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"), MutexKind::Recursive => { @@ -522,8 +522,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.eval_libc_i32("EBUSY") } else { match mutex.kind { - MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck => - this.eval_libc_i32("EBUSY"), + MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck => { + this.eval_libc_i32("EBUSY") + } MutexKind::Recursive => { this.mutex_lock(&mutex.mutex_ref); 0 @@ -550,16 +551,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the “Unlock When Not Owner” column in // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html. match mutex.kind { - MutexKind::Default => - throw_ub_format!( - "unlocked a default mutex that was not locked by the current thread" - ), - MutexKind::Normal => - throw_ub_format!( - "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" - ), - MutexKind::ErrorCheck | MutexKind::Recursive => - interp_ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))), + MutexKind::Default => throw_ub_format!( + "unlocked a default mutex that was not locked by the current thread" + ), + MutexKind::Normal => throw_ub_format!( + "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" + ), + MutexKind::ErrorCheck | MutexKind::Recursive => { + interp_ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))) + } } } } diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs index 8a965ea316d72..2b8768fe7823f 100644 --- a/src/tools/miri/src/shims/windows/handle.rs +++ b/src/tools/miri/src/shims/windows/handle.rs @@ -209,16 +209,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let handle = this.read_scalar(handle)?; match Handle::try_from_scalar(handle, this)? { Ok(handle) => interp_ok(handle), - Err(HandleError::InvalidHandle) => + Err(HandleError::InvalidHandle) => { throw_machine_stop!(TerminationInfo::Abort(format!( "invalid handle {} passed to {function_name}", handle.to_target_isize(this)?, - ))), - Err(HandleError::ThreadNotFound(_)) => + ))) + } + Err(HandleError::ThreadNotFound(_)) => { throw_machine_stop!(TerminationInfo::Abort(format!( "invalid thread ID {} passed to {function_name}", handle.to_target_isize(this)?, - ))), + ))) + } } } @@ -331,7 +333,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.detach_thread(thread, /*allow_terminated_joined*/ true)?; this.eval_windows("c", "TRUE") } - Handle::File(fd_num) => + Handle::File(fd_num) => { if let Some(fd) = this.machine.fds.remove(fd_num) { let err = fd.close_ref(this.machine.communicate(), this)?; if let Err(e) = err { @@ -342,7 +344,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } else { this.invalid_handle("CloseHandle")? - }, + } + } _ => this.invalid_handle("CloseHandle")?, }; diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index 269ce3b51b93f..1a2f66a293fe7 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -329,8 +329,9 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let res = match unprefixed_name { "vtestz.pd.256" | "vtestz.pd" | "vtestz.ps.256" | "vtestz.ps" => direct, "vtestc.pd.256" | "vtestc.pd" | "vtestc.ps.256" | "vtestc.ps" => negated, - "vtestnzc.pd.256" | "vtestnzc.pd" | "vtestnzc.ps.256" | "vtestnzc.ps" => - !direct && !negated, + "vtestnzc.pd.256" | "vtestnzc.pd" | "vtestnzc.ps.256" | "vtestnzc.ps" => { + !direct && !negated + } _ => unreachable!(), }; From d412336dbab605eeb56887763200d7e5c79fa61a Mon Sep 17 00:00:00 2001 From: OneProg Date: Thu, 31 Jul 2025 13:39:14 +0300 Subject: [PATCH 2/5] Revert "The text of the error that occurs when the order of formatting arguments is incorrect is clearer" This reverts commit b75ba509f54add50b1af8b73de59e73aca7d2767. --- compiler/rustc_parse_format/src/lib.rs | 7 +- .../clippy_lints/src/disallowed_macros.rs | 1 + .../src/needless_pass_by_value.rs | 4 +- src/tools/miri/cargo-miri/src/arg.rs | 28 ++-- src/tools/miri/cargo-miri/src/phases.rs | 7 +- src/tools/miri/cargo-miri/src/setup.rs | 9 +- src/tools/miri/src/alloc/alloc_bytes.rs | 5 +- src/tools/miri/src/bin/log/tracing_chrome.rs | 55 ++++++-- src/tools/miri/src/bin/miri.rs | 19 +-- src/tools/miri/src/borrow_tracker/mod.rs | 74 +++++----- .../stacked_borrows/diagnostics.rs | 38 +++-- .../borrow_tracker/stacked_borrows/stack.rs | 5 +- .../tree_borrows/diagnostics.rs | 8 +- .../src/borrow_tracker/tree_borrows/mod.rs | 58 ++++---- .../src/borrow_tracker/tree_borrows/perms.rs | 47 +++---- .../borrow_tracker/tree_borrows/tree/tests.rs | 46 +++--- src/tools/miri/src/clock.rs | 20 ++- src/tools/miri/src/concurrency/data_race.rs | 5 +- src/tools/miri/src/concurrency/thread.rs | 73 +++++----- .../miri/src/concurrency/vector_clock.rs | 28 ++-- .../src/data_structures/range_object_map.rs | 5 +- src/tools/miri/src/diagnostics.rs | 121 ++++++++-------- src/tools/miri/src/eval.rs | 54 +++---- src/tools/miri/src/helpers.rs | 43 +++--- src/tools/miri/src/intrinsics/atomic.rs | 15 +- src/tools/miri/src/intrinsics/mod.rs | 30 ++-- src/tools/miri/src/machine.rs | 29 ++-- src/tools/miri/src/math.rs | 20 ++- src/tools/miri/src/shims/backtrace.rs | 5 +- src/tools/miri/src/shims/foreign_items.rs | 20 ++- src/tools/miri/src/shims/global_ctor.rs | 23 ++- src/tools/miri/src/shims/io_error.rs | 25 ++-- src/tools/miri/src/shims/native_lib/mod.rs | 15 +- .../miri/src/shims/native_lib/trace/child.rs | 9 +- .../miri/src/shims/native_lib/trace/parent.rs | 132 +++++++++--------- src/tools/miri/src/shims/time.rs | 10 +- .../miri/src/shims/unix/foreign_items.rs | 66 +++++---- .../src/shims/unix/freebsd/foreign_items.rs | 7 +- src/tools/miri/src/shims/unix/fs.rs | 51 +++---- src/tools/miri/src/shims/unix/macos/sync.rs | 20 +-- src/tools/miri/src/shims/unix/sync.rs | 36 ++--- src/tools/miri/src/shims/windows/handle.rs | 15 +- src/tools/miri/src/shims/x86/avx.rs | 5 +- 43 files changed, 633 insertions(+), 660 deletions(-) diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 40055b6f4272f..8e4da7923fcb5 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -859,11 +859,8 @@ impl<'input> Parser<'input> { 0, ParseError { description: "expected format parameter to occur after `:`".to_owned(), - note: Some( - "See https://doc.rust-lang.org/std/fmt/index.html#syntax for more details" - .to_string(), - ), - label: format!("expected `{}` to occur in its correct place", alignment), + note: None, + label: format!("expected `{}` to occur after `:`", alignment), span: range, secondary_label: None, suggestion: Suggestion::None, diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs index 044903ce57537..23e7c7251cf15 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs @@ -1,3 +1,4 @@ + use clippy_config::Conf; use clippy_config::types::{DisallowedPath, create_disallowed_map}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index a28e9a279d708..7b057998063f9 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -311,7 +311,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { /// Functions marked with these attributes must have the exact signature. pub(crate) fn requires_exact_signature(attrs: &[Attribute]) -> bool { - attrs.iter().any(|attr| attr.is_proc_macro_attr()) + attrs.iter().any(|attr| { + attr.is_proc_macro_attr() + }) } #[derive(Default)] diff --git a/src/tools/miri/cargo-miri/src/arg.rs b/src/tools/miri/cargo-miri/src/arg.rs index 2f9723e87c9f5..d7216060358cb 100644 --- a/src/tools/miri/cargo-miri/src/arg.rs +++ b/src/tools/miri/cargo-miri/src/arg.rs @@ -45,7 +45,7 @@ impl<'s, I: Iterator>> Iterator for ArgSplitFlagValue<'_, I> } // These branches cannot be merged if we want to avoid the allocation in the `Borrowed` branch. match &arg { - Cow::Borrowed(arg) => { + Cow::Borrowed(arg) => if let Some(suffix) = arg.strip_prefix(self.name) { // Strip leading `name`. if suffix.is_empty() { @@ -55,9 +55,8 @@ impl<'s, I: Iterator>> Iterator for ArgSplitFlagValue<'_, I> // This argument is `name=value`; get the value. return Some(Ok(Cow::Borrowed(suffix))); } - } - } - Cow::Owned(arg) => { + }, + Cow::Owned(arg) => if let Some(suffix) = arg.strip_prefix(self.name) { // Strip leading `name`. if suffix.is_empty() { @@ -68,8 +67,7 @@ impl<'s, I: Iterator>> Iterator for ArgSplitFlagValue<'_, I> // here as a `String` cannot be subsliced (what would the lifetime be?). return Some(Ok(Cow::Owned(suffix.to_owned()))); } - } - } + }, } Some(Err(arg)) } @@ -80,9 +78,11 @@ impl<'a, I: Iterator + 'a> ArgSplitFlagValue<'a, I> { args: I, name: &'a str, ) -> impl Iterator> + 'a { - ArgSplitFlagValue::new(args.map(Cow::Owned), name).map(|x| match x { - Ok(s) => Ok(s.into_owned()), - Err(s) => Err(s.into_owned()), + ArgSplitFlagValue::new(args.map(Cow::Owned), name).map(|x| { + match x { + Ok(s) => Ok(s.into_owned()), + Err(s) => Err(s.into_owned()), + } }) } } @@ -92,10 +92,12 @@ impl<'x: 'a, 'a, I: Iterator + 'a> ArgSplitFlagValue<'a, I> { args: I, name: &'a str, ) -> impl Iterator> + 'a { - ArgSplitFlagValue::new(args.map(Cow::Borrowed), name).map(|x| match x { - Ok(Cow::Borrowed(s)) => Ok(s), - Err(Cow::Borrowed(s)) => Err(s), - _ => panic!("iterator converted borrowed to owned"), + ArgSplitFlagValue::new(args.map(Cow::Borrowed), name).map(|x| { + match x { + Ok(Cow::Borrowed(s)) => Ok(s), + Err(Cow::Borrowed(s)) => Err(s), + _ => panic!("iterator converted borrowed to owned"), + } }) } } diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 2f413d5eb7b49..efb9053f69a5a 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -85,9 +85,10 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { "setup" => MiriCommand::Setup, "test" | "t" | "run" | "r" | "nextest" => MiriCommand::Forward(subcommand), "clean" => MiriCommand::Clean, - _ => show_error!( - "`cargo miri` supports the following subcommands: `run`, `test`, `nextest`, `clean`, and `setup`." - ), + _ => + show_error!( + "`cargo miri` supports the following subcommands: `run`, `test`, `nextest`, `clean`, and `setup`." + ), }; let verbose = num_arg_flag("-v") + num_arg_flag("--verbose"); let quiet = has_arg_flag("-q") || has_arg_flag("--quiet"); diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index 7bcb80f9b671c..e399f66fbc9cd 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -73,12 +73,10 @@ pub fn setup( None => // No-std heuristic taken from rust/src/bootstrap/config.rs // (https://github.com/rust-lang/rust/blob/25b5af1b3a0b9e2c0c57b223b2d0e3e203869b2c/src/bootstrap/config.rs#L549-L555). - { target.contains("-none") || target.contains("nvptx") || target.contains("switch") - || target.contains("-uefi") - } + || target.contains("-uefi"), Some(val) => val != "0", }; let sysroot_config = if no_std { @@ -170,14 +168,13 @@ pub fn setup( .when_build_required(notify) .build_from_source(&rust_src); match status { - Ok(SysrootStatus::AlreadyCached) => { + Ok(SysrootStatus::AlreadyCached) => if !quiet && show_setup { eprintln!( "A sysroot for Miri is already available in `{}`.", sysroot_dir.display() ); - } - } + }, Ok(SysrootStatus::SysrootBuilt) => { // Print what `notify` prepared. eprint!("{after_build_output}"); diff --git a/src/tools/miri/src/alloc/alloc_bytes.rs b/src/tools/miri/src/alloc/alloc_bytes.rs index edb4b07f8952e..5d00d3eafcb5d 100644 --- a/src/tools/miri/src/alloc/alloc_bytes.rs +++ b/src/tools/miri/src/alloc/alloc_bytes.rs @@ -54,9 +54,8 @@ impl Drop for MiriAllocBytes { unsafe { match self.params.clone() { MiriAllocParams::Global => alloc::dealloc(self.ptr, alloc_layout), - MiriAllocParams::Isolated(alloc) => { - alloc.borrow_mut().dealloc(self.ptr, alloc_layout) - } + MiriAllocParams::Isolated(alloc) => + alloc.borrow_mut().dealloc(self.ptr, alloc_layout), } } } diff --git a/src/tools/miri/src/bin/log/tracing_chrome.rs b/src/tools/miri/src/bin/log/tracing_chrome.rs index 5840a33b997a5..3379816550cfe 100644 --- a/src/tools/miri/src/bin/log/tracing_chrome.rs +++ b/src/tools/miri/src/bin/log/tracing_chrome.rs @@ -25,20 +25,20 @@ // should not be included if the "tracing" feature is disabled. extern crate tracing_core; -use tracing_core::{Event, Subscriber, field::Field, span}; +use tracing_core::{field::Field, span, Event, Subscriber}; use tracing_subscriber::{ - Layer, layer::Context, registry::{LookupSpan, SpanRef}, + Layer, }; -use serde_json::{Value as JsonValue, json}; +use serde_json::{json, Value as JsonValue}; use std::{ marker::PhantomData, path::Path, sync::{ - Arc, Mutex, atomic::{AtomicUsize, Ordering}, + Arc, Mutex, }, }; @@ -308,7 +308,10 @@ fn create_default_writer() -> Box { Box::new( std::fs::File::create(format!( "./trace-{}.json", - std::time::SystemTime::UNIX_EPOCH.elapsed().unwrap().as_micros() + std::time::SystemTime::UNIX_EPOCH + .elapsed() + .unwrap() + .as_micros() )) .expect("Failed to create trace file."), ) @@ -322,7 +325,9 @@ where let (tx, rx) = mpsc::channel(); OUT.with(|val| val.replace(Some(tx.clone()))); - let out_writer = builder.out_writer.unwrap_or_else(|| create_default_writer()); + let out_writer = builder + .out_writer + .unwrap_or_else(|| create_default_writer()); let handle = std::thread::spawn(move || { let mut write = BufWriter::new(out_writer); @@ -432,7 +437,10 @@ where write.flush().unwrap(); }); - let guard = FlushGuard { sender: tx.clone(), handle: Cell::new(Some(handle)) }; + let guard = FlushGuard { + sender: tx.clone(), + handle: Cell::new(Some(handle)), + }; let layer = ChromeLayer { out: Arc::new(Mutex::new(tx)), start: std::time::Instant::now(), @@ -480,12 +488,19 @@ where None } } - EventOrSpan::Span(s) => s.extensions().get::().map(|e| &e.args).cloned(), + EventOrSpan::Span(s) => s + .extensions() + .get::() + .map(|e| &e.args) + .cloned(), }; let name = name.unwrap_or_else(|| meta.name().into()); let target = target.unwrap_or_else(|| meta.target().into()); - let (file, line) = - if self.include_locations { (meta.file(), meta.line()) } else { (None, None) }; + let (file, line) = if self.include_locations { + (meta.file(), meta.line()) + } else { + (None, None) + }; if new_thread { let name = match std::thread::current().name() { @@ -495,7 +510,14 @@ where self.send_message(Message::NewThread(tid, name)); } - Callsite { tid, name, target, file, line, args } + Callsite { + tid, + name, + target, + file, + line, + args, + } } fn get_root_id(&self, span: SpanRef) -> Option { @@ -512,7 +534,7 @@ where } else { None } - } + }, TraceStyle::Async => Some( span.scope() .from_root() @@ -521,7 +543,7 @@ where .unwrap_or(span) .id() .into_u64() - .cast_signed(), // the comment above explains the cast + .cast_signed() // the comment above explains the cast ), } } @@ -600,7 +622,9 @@ where if self.include_args { let mut args = Object::new(); attrs.record(&mut JsonVisitor { object: &mut args }); - ctx.span(id).unwrap().extensions_mut().insert(ArgsWrapper { args: Arc::new(args) }); + ctx.span(id).unwrap().extensions_mut().insert(ArgsWrapper { + args: Arc::new(args), + }); } if let TraceStyle::Threaded = self.trace_style { return; @@ -626,7 +650,8 @@ struct JsonVisitor<'a> { impl<'a> tracing_subscriber::field::Visit for JsonVisitor<'a> { fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) { - self.object.insert(field.name().to_owned(), format!("{value:?}").into()); + self.object + .insert(field.name().to_owned(), format!("{value:?}").into()); } } diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 0e670a1feadd9..ae1b25f8857a0 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -516,9 +516,10 @@ fn main() { Some(BorrowTrackerMethod::TreeBorrows(params)) => { params.precise_interior_mut = false; } - _ => fatal_error!( - "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-no-precise-interior-mut`" - ), + _ => + fatal_error!( + "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-no-precise-interior-mut`" + ), }; } else if arg == "-Zmiri-disable-data-race-detector" { miri_config.data_race_detector = false; @@ -540,12 +541,12 @@ fn main() { "abort" => miri::IsolatedOp::Reject(miri::RejectOpWith::Abort), "hide" => miri::IsolatedOp::Reject(miri::RejectOpWith::NoWarning), "warn" => miri::IsolatedOp::Reject(miri::RejectOpWith::Warning), - "warn-nobacktrace" => { - miri::IsolatedOp::Reject(miri::RejectOpWith::WarningWithoutBacktrace) - } - _ => fatal_error!( - "-Zmiri-isolation-error must be `abort`, `hide`, `warn`, or `warn-nobacktrace`" - ), + "warn-nobacktrace" => + miri::IsolatedOp::Reject(miri::RejectOpWith::WarningWithoutBacktrace), + _ => + fatal_error!( + "-Zmiri-isolation-error must be `abort`, `hide`, `warn`, or `warn-nobacktrace`" + ), }; } else if arg == "-Zmiri-ignore-leaks" { miri_config.ignore_leaks = true; diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index abb21c8200dda..ec6c2c60ca9c6 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -262,12 +262,14 @@ impl GlobalStateInner { ) -> AllocState { let _span = enter_trace_span!(borrow_tracker::new_allocation, ?id, ?alloc_size, ?kind); match self.borrow_tracker_method { - BorrowTrackerMethod::StackedBorrows => AllocState::StackedBorrows(Box::new( - RefCell::new(Stacks::new_allocation(id, alloc_size, self, kind, machine)), - )), - BorrowTrackerMethod::TreeBorrows { .. } => AllocState::TreeBorrows(Box::new( - RefCell::new(Tree::new_allocation(id, alloc_size, self, kind, machine)), - )), + BorrowTrackerMethod::StackedBorrows => + AllocState::StackedBorrows(Box::new(RefCell::new(Stacks::new_allocation( + id, alloc_size, self, kind, machine, + )))), + BorrowTrackerMethod::TreeBorrows { .. } => + AllocState::TreeBorrows(Box::new(RefCell::new(Tree::new_allocation( + id, alloc_size, self, kind, machine, + )))), } } } @@ -336,9 +338,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.tcx.tcx.dcx().warn("Stacked Borrows does not support named pointers; `miri_pointer_name` is a no-op"); interp_ok(()) } - BorrowTrackerMethod::TreeBorrows { .. } => { - this.tb_give_pointer_debug_name(ptr, nth_parent, name) - } + BorrowTrackerMethod::TreeBorrows { .. } => + this.tb_give_pointer_debug_name(ptr, nth_parent, name), } } @@ -439,16 +440,16 @@ impl AllocState { ) -> InterpResult<'tcx> { let _span = enter_trace_span!(borrow_tracker::before_memory_read, alloc_id = alloc_id.0); match self { - AllocState::StackedBorrows(sb) => { - sb.borrow_mut().before_memory_read(alloc_id, prov_extra, range, machine) - } - AllocState::TreeBorrows(tb) => tb.borrow_mut().before_memory_access( - AccessKind::Read, - alloc_id, - prov_extra, - range, - machine, - ), + AllocState::StackedBorrows(sb) => + sb.borrow_mut().before_memory_read(alloc_id, prov_extra, range, machine), + AllocState::TreeBorrows(tb) => + tb.borrow_mut().before_memory_access( + AccessKind::Read, + alloc_id, + prov_extra, + range, + machine, + ), } } @@ -461,16 +462,16 @@ impl AllocState { ) -> InterpResult<'tcx> { let _span = enter_trace_span!(borrow_tracker::before_memory_write, alloc_id = alloc_id.0); match self { - AllocState::StackedBorrows(sb) => { - sb.get_mut().before_memory_write(alloc_id, prov_extra, range, machine) - } - AllocState::TreeBorrows(tb) => tb.get_mut().before_memory_access( - AccessKind::Write, - alloc_id, - prov_extra, - range, - machine, - ), + AllocState::StackedBorrows(sb) => + sb.get_mut().before_memory_write(alloc_id, prov_extra, range, machine), + AllocState::TreeBorrows(tb) => + tb.get_mut().before_memory_access( + AccessKind::Write, + alloc_id, + prov_extra, + range, + machine, + ), } } @@ -484,12 +485,10 @@ impl AllocState { let _span = enter_trace_span!(borrow_tracker::before_memory_deallocation, alloc_id = alloc_id.0); match self { - AllocState::StackedBorrows(sb) => { - sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine) - } - AllocState::TreeBorrows(tb) => { - tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine) - } + AllocState::StackedBorrows(sb) => + sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine), + AllocState::TreeBorrows(tb) => + tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine), } } @@ -516,9 +515,8 @@ impl AllocState { ); match self { AllocState::StackedBorrows(_sb) => interp_ok(()), - AllocState::TreeBorrows(tb) => { - tb.borrow_mut().release_protector(machine, global, tag, alloc_id) - } + AllocState::TreeBorrows(tb) => + tb.borrow_mut().release_protector(machine, global, tag, alloc_id), } } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index fed98dfeca7d2..63b18028a5b9d 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -96,9 +96,8 @@ 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, info) => { - write!(f, "{perm:?} {retag}", retag = info.summary()) - } + InvalidationCause::Retag(perm, info) => + write!(f, "{perm:?} {retag}", retag = info.summary()), } } } @@ -251,7 +250,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { None => { last_creation.retag.permission = Some(perm); } - Some(previous) => { + Some(previous) => if previous != perm { // 'Split up' the creation event. let previous_range = last_creation.retag.range; @@ -260,8 +259,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { new_event.retag.range = alloc_range(self.offset, previous_range.end()); new_event.retag.permission = Some(perm); self.history.creations.push(new_event); - } - } + }, } } @@ -283,9 +281,8 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { } (*range, InvalidationCause::Retag(permission.unwrap(), *info)) } - Operation::Access(AccessOp { kind, range, .. }) => { - (*range, InvalidationCause::Access(*kind)) - } + Operation::Access(AccessOp { kind, range, .. }) => + (*range, InvalidationCause::Access(*kind)), Operation::Dealloc(_) => { // This can be reached, but never be relevant later since the entire allocation is // gone now. @@ -437,17 +434,17 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { ProtectorKind::StrongProtector => "strongly protected", }; match self.operation { - Operation::Dealloc(_) => { - err_sb_ub(format!("deallocating while item {item:?} is {protected}",), vec![], None) - } + Operation::Dealloc(_) => + err_sb_ub(format!("deallocating while item {item:?} is {protected}",), vec![], None), Operation::Retag(RetagOp { orig_tag: tag, .. }) - | Operation::Access(AccessOp { tag, .. }) => err_sb_ub( - format!( - "not granting access to tag {tag:?} because that would remove {item:?} which is {protected}", + | Operation::Access(AccessOp { tag, .. }) => + err_sb_ub( + format!( + "not granting access to tag {tag:?} because that would remove {item:?} which is {protected}", + ), + vec![], + tag.and_then(|tag| self.get_logs_relevant_to(tag, Some(item.tag()))), ), - vec![], - tag.and_then(|tag| self.get_logs_relevant_to(tag, Some(item.tag()))), - ), } } @@ -475,9 +472,8 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { } let cause = match self.operation { Operation::Dealloc(_) => format!(" due to deallocation"), - Operation::Access(AccessOp { kind, tag, .. }) => { - format!(" due to {kind:?} access for {tag:?}") - } + Operation::Access(AccessOp { kind, tag, .. }) => + format!(" due to {kind:?} access for {tag:?}"), Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => { let permission = permission .expect("start_grant should set the current permission before popping a tag"); diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs index 9dfdcd7fbe243..dc3370f125104 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs @@ -64,9 +64,8 @@ impl Stack { Permission::Disabled => left.perm() == Permission::SharedReadWrite, // Unique and SharedReadOnly can terminate a SharedReadWrite block, so only remove // them if they are both unreachable and not directly after a SharedReadWrite. - Permission::Unique | Permission::SharedReadOnly => { - left.perm() == Permission::SharedReadWrite || tags.contains(&this.tag()) - } + Permission::Unique | Permission::SharedReadOnly => + left.perm() == Permission::SharedReadWrite || tags.contains(&this.tag()), }; if should_keep { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index 537bdfa185899..7b4c533cfaed7 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -526,9 +526,11 @@ impl DisplayFmt { /// Print extra text if the tag has a protector. fn print_protector(&self, protector: Option<&ProtectorKind>) -> &'static str { protector - .map(|p| match *p { - ProtectorKind::WeakProtector => " Weakly protected", - ProtectorKind::StrongProtector => " Strongly protected", + .map(|p| { + match *p { + ProtectorKind::WeakProtector => " Weakly protected", + ProtectorKind::StrongProtector => " Strongly protected", + } }) .unwrap_or("") } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index eed4908aa4096..ad2a67160f484 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -143,30 +143,35 @@ impl<'tcx> NewPermission { let protector = is_protected.then_some(ProtectorKind::StrongProtector); Some(match mutability { - Mutability::Mut if ty_is_unpin => NewPermission { - freeze_perm: Permission::new_reserved(/* ty_is_freeze */ true, is_protected), - freeze_access: true, - nonfreeze_perm: Permission::new_reserved( - /* ty_is_freeze */ false, - is_protected, - ), - // If we have a mutable reference, then the non-frozen part will - // have state `ReservedIM` or `Reserved`, which can have an initial read access - // performed on it because you cannot have multiple mutable borrows. - nonfreeze_access: true, - protector, - }, - Mutability::Not => NewPermission { - freeze_perm: Permission::new_frozen(), - freeze_access: true, - nonfreeze_perm: Permission::new_cell(), - // If it is a shared reference, then the non-frozen - // part will have state `Cell`, which should not have an initial access, - // as this can cause data races when using thread-safe data types like - // `Mutex`. - nonfreeze_access: false, - protector, - }, + Mutability::Mut if ty_is_unpin => + NewPermission { + freeze_perm: Permission::new_reserved( + /* ty_is_freeze */ true, + is_protected, + ), + freeze_access: true, + nonfreeze_perm: Permission::new_reserved( + /* ty_is_freeze */ false, + is_protected, + ), + // If we have a mutable reference, then the non-frozen part will + // have state `ReservedIM` or `Reserved`, which can have an initial read access + // performed on it because you cannot have multiple mutable borrows. + nonfreeze_access: true, + protector, + }, + Mutability::Not => + NewPermission { + freeze_perm: Permission::new_frozen(), + freeze_access: true, + nonfreeze_perm: Permission::new_cell(), + // If it is a shared reference, then the non-frozen + // part will have state `Cell`, which should not have an initial access, + // as this can cause data races when using thread-safe data types like + // `Mutex`. + nonfreeze_access: false, + protector, + }, _ => return None, }) } @@ -508,9 +513,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, ImmTy<'tcx>> { let this = self.eval_context_mut(); let new_perm = match val.layout.ty.kind() { - &ty::Ref(_, pointee, mutability) => { - NewPermission::from_ref_ty(pointee, mutability, kind, this) - } + &ty::Ref(_, pointee, mutability) => + NewPermission::from_ref_ty(pointee, mutability, kind, this), _ => None, }; if let Some(new_perm) = new_perm { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index b570b91b7aea2..38863ca0734a1 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -167,7 +167,7 @@ mod transition { assert!(!protected); res } - Active => { + Active => if protected { // We wrote, someone else reads -- that's bad. // (Since Active is always initialized, this move-to-protected will mean insta-UB.) @@ -176,8 +176,7 @@ mod transition { // We don't want to disable here to allow read-read reordering: it is crucial // that the foreign read does not invalidate future reads through this tag. Frozen - } - } + }, }) } @@ -471,14 +470,12 @@ pub mod diagnostics { match (self.from, self.to) { (_, Active) => "the first write to a 2-phase borrowed mutable reference", (_, Frozen) => "a loss of write permissions", - (ReservedFrz { conflicted: false }, ReservedFrz { conflicted: true }) => { - "a temporary loss of write permissions until function exit" - } + (ReservedFrz { conflicted: false }, ReservedFrz { conflicted: true }) => + "a temporary loss of write permissions until function exit", (Frozen, Disabled) => "a loss of read permissions", (_, Disabled) => "a loss of read and write permissions", - (old, new) => { - unreachable!("Transition from {old:?} to {new:?} should never be possible") - } + (old, new) => + unreachable!("Transition from {old:?} to {new:?} should never be possible"), } } @@ -535,15 +532,13 @@ pub mod diagnostics { // `Active`, `Reserved`, and `Cell` have all permissions, so a // `ChildAccessForbidden(Reserved | Active)` can never exist. - (_, Active) | (_, ReservedFrz { conflicted: false }) | (_, Cell) => { - unreachable!("this permission cannot cause an error") - } + (_, Active) | (_, ReservedFrz { conflicted: false }) | (_, Cell) => + unreachable!("this permission cannot cause an error"), // No transition has `Reserved { conflicted: false }` or `ReservedIM` // as its `.to` unless it's a noop. `Cell` cannot be in its `.to` // because all child accesses are a noop. - (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => { - unreachable!("self is a noop transition") - } + (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => + unreachable!("self is a noop transition"), // All transitions produced in normal executions (using `apply_access`) // change permissions in the order `Reserved -> Active -> Frozen -> Disabled`. // We assume that the error was triggered on the same location that @@ -551,9 +546,8 @@ pub mod diagnostics { // in the order `self.from < self.to <= insufficient.inner` (Active | Frozen | Disabled, ReservedFrz { .. } | ReservedIM) | (Disabled, Frozen) - | (ReservedFrz { .. }, ReservedIM) => { - unreachable!("permissions between self and err must be increasing") - } + | (ReservedFrz { .. }, ReservedIM) => + unreachable!("permissions between self and err must be increasing"), } } TransitionError::ProtectedDisabled(before_disabled) => { @@ -584,24 +578,23 @@ pub mod diagnostics { (Active, Frozen) => false, (ReservedFrz { conflicted: true }, _) => false, - (_, Disabled) => unreachable!( - "permission that results in Disabled should not itself be Disabled in the first place" - ), + (_, Disabled) => + unreachable!( + "permission that results in Disabled should not itself be Disabled in the first place" + ), // No transition has `Reserved { conflicted: false }` or `ReservedIM` as its `.to` // unless it's a noop. `Cell` cannot be in its `.to` because all child // accesses are a noop. - (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => { - unreachable!("self is a noop transition") - } + (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => + unreachable!("self is a noop transition"), // Permissions only evolve in the order `Reserved -> Active -> Frozen -> Disabled`, // so permissions found must be increasing in the order // `self.from < self.to <= forbidden.from < forbidden.to`. (Disabled, Cell | ReservedFrz { .. } | ReservedIM | Active | Frozen) | (Frozen, Cell | ReservedFrz { .. } | ReservedIM | Active) - | (Active, Cell | ReservedFrz { .. } | ReservedIM) => { - unreachable!("permissions between self and err must be increasing") - } + | (Active, Cell | ReservedFrz { .. } | ReservedIM) => + unreachable!("permissions between self and err must be increasing"), } } // We don't care because protectors evolve independently from diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs index dede1708e0472..bb3fc2d80b3fa 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs @@ -9,10 +9,12 @@ use crate::borrow_tracker::tree_borrows::exhaustive::{Exhaustive, precondition}; impl Exhaustive for LocationState { fn exhaustive() -> Box> { // We keep `latest_foreign_access` at `None` as that's just a cache. - Box::new(<(Permission, bool)>::exhaustive().map(|(permission, accessed)| Self { - permission, - accessed, - idempotent_foreign_access: IdempotentForeignAccess::default(), + Box::new(<(Permission, bool)>::exhaustive().map(|(permission, accessed)| { + Self { + permission, + accessed, + idempotent_foreign_access: IdempotentForeignAccess::default(), + } })) } } @@ -259,16 +261,18 @@ mod spurious_read { fn rel_pair(self, xy_rel: RelPosXY) -> (AccessRelatedness, AccessRelatedness) { use AccessRelatedness::*; match xy_rel { - RelPosXY::MutuallyForeign => match self { - PtrSelector::X => (This, CousinAccess), - PtrSelector::Y => (CousinAccess, This), - PtrSelector::Other => (CousinAccess, CousinAccess), - }, - RelPosXY::XChildY => match self { - PtrSelector::X => (This, StrictChildAccess), - PtrSelector::Y => (AncestorAccess, This), - PtrSelector::Other => (CousinAccess, CousinAccess), - }, + RelPosXY::MutuallyForeign => + match self { + PtrSelector::X => (This, CousinAccess), + PtrSelector::Y => (CousinAccess, This), + PtrSelector::Other => (CousinAccess, CousinAccess), + }, + RelPosXY::XChildY => + match self { + PtrSelector::X => (This, StrictChildAccess), + PtrSelector::Y => (AncestorAccess, This), + PtrSelector::Other => (CousinAccess, CousinAccess), + }, } } } @@ -438,9 +442,10 @@ mod spurious_read { let accessed = match ptr { PtrSelector::X => self.x.state.accessed, PtrSelector::Y => self.y.state.accessed, - PtrSelector::Other => panic!( - "the `accessed` status of `PtrSelector::Other` is unknown, do not pass it to `read_if_accessed`" - ), + PtrSelector::Other => + panic!( + "the `accessed` status of `PtrSelector::Other` is unknown, do not pass it to `read_if_accessed`" + ), }; if accessed { self.perform_test_access(&TestAccess { ptr, kind: AccessKind::Read }) @@ -487,11 +492,8 @@ mod spurious_read { impl Exhaustive for LocStateProtPair { fn exhaustive() -> Box> { Box::new(<[LocStateProt; 2]>::exhaustive().flat_map(|[x, y]| { - RelPosXY::exhaustive().map(move |xy_rel| Self { - x: x.clone(), - y: y.clone(), - xy_rel, - }) + RelPosXY::exhaustive() + .map(move |xy_rel| Self { x: x.clone(), y: y.clone(), xy_rel }) })) } } diff --git a/src/tools/miri/src/clock.rs b/src/tools/miri/src/clock.rs index 4e6f867013079..34465e9cac60d 100644 --- a/src/tools/miri/src/clock.rs +++ b/src/tools/miri/src/clock.rs @@ -39,9 +39,8 @@ impl Instant { pub fn duration_since(&self, earlier: Instant) -> Duration { match (&self.kind, earlier.kind) { - (InstantKind::Host(instant), InstantKind::Host(earlier)) => { - instant.duration_since(earlier) - } + (InstantKind::Host(instant), InstantKind::Host(earlier)) => + instant.duration_since(earlier), ( InstantKind::Virtual { nanoseconds }, InstantKind::Virtual { nanoseconds: earlier }, @@ -123,20 +122,17 @@ impl MonotonicClock { pub fn epoch(&self) -> Instant { match &self.kind { MonotonicClockKind::Host { epoch } => Instant { kind: InstantKind::Host(*epoch) }, - MonotonicClockKind::Virtual { .. } => { - Instant { kind: InstantKind::Virtual { nanoseconds: 0 } } - } + MonotonicClockKind::Virtual { .. } => + Instant { kind: InstantKind::Virtual { nanoseconds: 0 } }, } } pub fn now(&self) -> Instant { match &self.kind { - MonotonicClockKind::Host { .. } => { - Instant { kind: InstantKind::Host(StdInstant::now()) } - } - MonotonicClockKind::Virtual { nanoseconds } => { - Instant { kind: InstantKind::Virtual { nanoseconds: nanoseconds.get() } } - } + MonotonicClockKind::Host { .. } => + Instant { kind: InstantKind::Host(StdInstant::now()) }, + MonotonicClockKind::Virtual { nanoseconds } => + Instant { kind: InstantKind::Virtual { nanoseconds: nanoseconds.get() } }, } } } diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index d4c6635dd2e97..38d76f5cf73b7 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -1041,9 +1041,8 @@ impl VClockAlloc { | MiriMemoryKind::ExternStatic | MiriMemoryKind::Tls, ) - | MemoryKind::CallerLocation => { - (VTimestamp::ZERO, global.thread_index(ThreadId::MAIN_THREAD)) - } + | MemoryKind::CallerLocation => + (VTimestamp::ZERO, global.thread_index(ThreadId::MAIN_THREAD)), }; VClockAlloc { alloc_ranges: RefCell::new(DedupRangeMap::new( diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 86d00e940719c..fe1ef86ccd31e 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -127,9 +127,8 @@ impl<'tcx> std::fmt::Debug for ThreadState<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Enabled => write!(f, "Enabled"), - Self::Blocked { reason, timeout, .. } => { - f.debug_struct("Blocked").field("reason", reason).field("timeout", timeout).finish() - } + Self::Blocked { reason, timeout, .. } => + f.debug_struct("Blocked").field("reason", reason).field("timeout", timeout).finish(), Self::Terminated => write!(f, "Terminated"), } } @@ -355,9 +354,8 @@ impl Timeout { fn get_wait_time(&self, clock: &MonotonicClock) -> Duration { match self { Timeout::Monotonic(instant) => instant.duration_since(clock.now()), - Timeout::RealTime(time) => { - time.duration_since(SystemTime::now()).unwrap_or(Duration::ZERO) - } + Timeout::RealTime(time) => + time.duration_since(SystemTime::now()).unwrap_or(Duration::ZERO), } } @@ -622,11 +620,12 @@ impl<'tcx> ThreadManager<'tcx> { fn next_callback_wait_time(&self, clock: &MonotonicClock) -> Option { self.threads .iter() - .filter_map(|t| match &t.state { - ThreadState::Blocked { timeout: Some(timeout), .. } => { - Some(timeout.get_wait_time(clock)) + .filter_map(|t| { + match &t.state { + ThreadState::Blocked { timeout: Some(timeout), .. } => + Some(timeout.get_wait_time(clock)), + _ => None, } - _ => None, }) .min() } @@ -861,12 +860,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let current_span = this.machine.current_span(); match &mut this.machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Vclocks(data_race) => { - data_race.thread_created(&this.machine.threads, new_thread_id, current_span) - } - GlobalDataRaceHandler::Genmc(genmc_ctx) => { - genmc_ctx.handle_thread_create(&this.machine.threads, new_thread_id)? - } + GlobalDataRaceHandler::Vclocks(data_race) => + data_race.thread_created(&this.machine.threads, new_thread_id, current_span), + GlobalDataRaceHandler::Genmc(genmc_ctx) => + genmc_ctx.handle_thread_create(&this.machine.threads, new_thread_id)?, } // Write the current thread-id, switch to the next thread later // to treat this write operation as occurring on the current thread. @@ -921,12 +918,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { thread.state = ThreadState::Terminated; match &mut this.machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Vclocks(data_race) => { - data_race.thread_terminated(&this.machine.threads) - } - GlobalDataRaceHandler::Genmc(genmc_ctx) => { - genmc_ctx.handle_thread_finish(&this.machine.threads)? - } + GlobalDataRaceHandler::Vclocks(data_race) => + data_race.thread_terminated(&this.machine.threads), + GlobalDataRaceHandler::Genmc(genmc_ctx) => + genmc_ctx.handle_thread_finish(&this.machine.threads)?, } // Deallocate TLS. let gone_thread = this.active_thread(); @@ -945,18 +940,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Now free the TLS statics. for ptr in free_tls_statics { match tls_alloc_action { - TlsAllocAction::Deallocate => { - this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())? - } - TlsAllocAction::Leak => { + TlsAllocAction::Deallocate => + this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?, + TlsAllocAction::Leak => if let Some(alloc) = ptr.provenance.get_alloc_id() { trace!( "Thread-local static leaked and stored as static root: {:?}", alloc ); this.machine.static_roots.push(alloc); - } - } + }, } } } @@ -997,10 +990,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { TimeoutAnchor::Relative => SystemTime::now(), }) } - TimeoutClock::Monotonic => Timeout::Monotonic(match anchor { - TimeoutAnchor::Absolute => this.machine.monotonic_clock.epoch(), - TimeoutAnchor::Relative => this.machine.monotonic_clock.now(), - }), + TimeoutClock::Monotonic => + Timeout::Monotonic(match anchor { + TimeoutAnchor::Absolute => this.machine.monotonic_clock.epoch(), + TimeoutAnchor::Relative => this.machine.monotonic_clock.now(), + }), }; anchor.add_lossy(duration) }); @@ -1065,12 +1059,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let threads = &this.machine.threads; match &mut this.machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Vclocks(data_race) => { - data_race.thread_joined(threads, joined_thread_id) - } - GlobalDataRaceHandler::Genmc(genmc_ctx) => { - genmc_ctx.handle_thread_join(threads.active_thread, joined_thread_id)? - } + GlobalDataRaceHandler::Vclocks(data_race) => + data_race.thread_joined(threads, joined_thread_id), + GlobalDataRaceHandler::Genmc(genmc_ctx) => + genmc_ctx.handle_thread_join(threads.active_thread, joined_thread_id)?, } this.write_scalar(success_retval, return_dest)?; interp_ok(()) @@ -1236,9 +1228,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // See if this thread can do something else. match this.run_on_stack_empty()? { Poll::Pending => {} // keep going - Poll::Ready(()) => { - this.terminate_active_thread(TlsAllocAction::Deallocate)? - } + Poll::Ready(()) => + this.terminate_active_thread(TlsAllocAction::Deallocate)?, } } } diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index 22807ba996c3f..494e7922d2b2b 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -270,16 +270,14 @@ impl PartialOrd for VClock { for (l, r) in iter { match order { Ordering::Equal => order = l.cmp(r), - Ordering::Less => { + Ordering::Less => if l > r { return None; - } - } - Ordering::Greater => { + }, + Ordering::Greater => if l < r { return None; - } - } + }, } } @@ -294,16 +292,18 @@ impl PartialOrd for VClock { Ordering::Equal => Some(order), // Right has at least 1 element > than the implicit 0, // so the only valid values are Ordering::Less or None. - Ordering::Less => match order { - Ordering::Less | Ordering::Equal => Some(Ordering::Less), - Ordering::Greater => None, - }, + Ordering::Less => + match order { + Ordering::Less | Ordering::Equal => Some(Ordering::Less), + Ordering::Greater => None, + }, // Left has at least 1 element > than the implicit 0, // so the only valid values are Ordering::Greater or None. - Ordering::Greater => match order { - Ordering::Greater | Ordering::Equal => Some(Ordering::Greater), - Ordering::Less => None, - }, + Ordering::Greater => + match order { + Ordering::Greater | Ordering::Equal => Some(Ordering::Greater), + Ordering::Less => None, + }, } } diff --git a/src/tools/miri/src/data_structures/range_object_map.rs b/src/tools/miri/src/data_structures/range_object_map.rs index eab768af13dc3..4c9cf3dc6351b 100644 --- a/src/tools/miri/src/data_structures/range_object_map.rs +++ b/src/tools/miri/src/data_structures/range_object_map.rs @@ -83,15 +83,14 @@ impl RangeObjectMap { // Start of the range doesn't belong to an existing object match self.find_offset(range.end() - Size::from_bytes(1)) { // Neither does the end - Err(end_pos) => { + Err(end_pos) => if pos == end_pos { // There's nothing between the start and the end, so the range thing is empty AccessType::Empty(pos) } else { // Otherwise we have entirely covered an existing object AccessType::ImperfectlyOverlapping(pos..end_pos) - } - } + }, // Otherwise at least part of it overlaps with something else Ok(end_pos) => AccessType::ImperfectlyOverlapping(pos..end_pos + 1), } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index ec5208f42eb4d..9ecbd31c5b9f9 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -69,29 +69,29 @@ impl fmt::Display for TerminationInfo { Abort(msg) => write!(f, "{msg}"), Interrupted => write!(f, "interpretation was interrupted"), UnsupportedInIsolation(msg) => write!(f, "{msg}"), - Int2PtrWithStrictProvenance => write!( - f, - "integer-to-pointer casts and `ptr::with_exposed_provenance` are not supported with `-Zmiri-strict-provenance`" - ), + Int2PtrWithStrictProvenance => + write!( + f, + "integer-to-pointer casts and `ptr::with_exposed_provenance` are not supported with `-Zmiri-strict-provenance`" + ), StackedBorrowsUb { msg, .. } => write!(f, "{msg}"), TreeBorrowsUb { title, .. } => write!(f, "{title}"), Deadlock => write!(f, "the evaluated program deadlocked"), GenmcStuckExecution => write!(f, "GenMC determined that the execution got stuck"), - MultipleSymbolDefinitions { link_name, .. } => { - write!(f, "multiple definitions of symbol `{link_name}`") - } - SymbolShimClashing { link_name, .. } => { - write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",) - } - DataRace { involves_non_atomic, ptr, op1, op2, .. } => write!( - f, - "{} detected between (1) {} on {} and (2) {} on {} at {ptr:?}", - if *involves_non_atomic { "Data race" } else { "Race condition" }, - op1.action, - op1.thread_info, - op2.action, - op2.thread_info - ), + MultipleSymbolDefinitions { link_name, .. } => + write!(f, "multiple definitions of symbol `{link_name}`"), + SymbolShimClashing { link_name, .. } => + write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",), + DataRace { involves_non_atomic, ptr, op1, op2, .. } => + write!( + f, + "{} detected between (1) {} on {} and (2) {} on {} at {ptr:?}", + if *involves_non_atomic { "Data race" } else { "Race condition" }, + op1.action, + op1.thread_info, + op2.action, + op2.thread_info + ), UnsupportedForeignItem(msg) => write!(f, "{msg}"), } } @@ -235,12 +235,10 @@ pub fn report_error<'tcx>( &Exit { code, leak_check } => return Some((code, leak_check)), Abort(_) => Some("abnormal termination"), Interrupted => None, - UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) => { - Some("unsupported operation") - } - StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } => { - Some("Undefined Behavior") - } + UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) => + Some("unsupported operation"), + StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } => + Some("Undefined Behavior"), Deadlock => { labels.push(format!("this thread got stuck here")); None @@ -628,59 +626,51 @@ impl<'tcx> MiriMachine<'tcx> { let (stacktrace, _was_pruned) = prune_stacktrace(stacktrace, self); let (label, diag_level) = match &e { - RejectedIsolatedOp(_) => { - ("operation rejected by isolation".to_string(), DiagLevel::Warning) - } + RejectedIsolatedOp(_) => + ("operation rejected by isolation".to_string(), DiagLevel::Warning), Int2Ptr { .. } => ("integer-to-pointer cast".to_string(), DiagLevel::Warning), - NativeCallSharedMem { .. } => { - ("sharing memory with a native function".to_string(), DiagLevel::Warning) - } - ExternTypeReborrow => { - ("reborrow of reference to `extern type`".to_string(), DiagLevel::Warning) - } + NativeCallSharedMem { .. } => + ("sharing memory with a native function".to_string(), DiagLevel::Warning), + ExternTypeReborrow => + ("reborrow of reference to `extern type`".to_string(), DiagLevel::Warning), CreatedPointerTag(..) | PoppedPointerTag(..) | CreatedAlloc(..) | AccessedAlloc(..) | FreedAlloc(..) | ProgressReport { .. } - | WeakMemoryOutdatedLoad { .. } => { - ("tracking was triggered here".to_string(), DiagLevel::Note) - } + | WeakMemoryOutdatedLoad { .. } => + ("tracking was triggered here".to_string(), DiagLevel::Note), }; let title = match &e { CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"), - CreatedPointerTag(tag, Some(perm), None) => { - format!("created {tag:?} with {perm} derived from unknown tag") - } - CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) => format!( - "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}" - ), + CreatedPointerTag(tag, Some(perm), None) => + format!("created {tag:?} with {perm} derived from unknown tag"), + CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) => + format!( + "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}" + ), PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"), - CreatedAlloc(AllocId(id), size, align, kind) => format!( - "created {kind} allocation of {size} bytes (alignment {align} bytes) with id {id}", - size = size.bytes(), - align = align.bytes(), - ), - AccessedAlloc(AllocId(id), access_kind) => { - format!("{access_kind} to allocation with id {id}") - } + CreatedAlloc(AllocId(id), size, align, kind) => + format!( + "created {kind} allocation of {size} bytes (alignment {align} bytes) with id {id}", + size = size.bytes(), + align = align.bytes(), + ), + AccessedAlloc(AllocId(id), access_kind) => + format!("{access_kind} to allocation with id {id}"), FreedAlloc(AllocId(id)) => format!("freed allocation with id {id}"), RejectedIsolatedOp(op) => format!("{op} was made to return an error due to isolation"), - ProgressReport { .. } => { - format!("progress report: current operation being executed is here") - } + ProgressReport { .. } => + format!("progress report: current operation being executed is here"), Int2Ptr { .. } => format!("integer-to-pointer cast"), - NativeCallSharedMem { .. } => { - format!("sharing memory with a native function called via FFI") - } - WeakMemoryOutdatedLoad { ptr } => { - format!("weak memory emulation: outdated value returned from load at {ptr}") - } - ExternTypeReborrow => { - format!("reborrow of a reference to `extern type` is not properly supported") - } + NativeCallSharedMem { .. } => + format!("sharing memory with a native function called via FFI"), + WeakMemoryOutdatedLoad { ptr } => + format!("weak memory emulation: outdated value returned from load at {ptr}"), + ExternTypeReborrow => + format!("reborrow of a reference to `extern type` is not properly supported"), }; let notes = match &e { @@ -722,7 +712,7 @@ impl<'tcx> MiriMachine<'tcx> { } v } - NativeCallSharedMem { tracing } => { + NativeCallSharedMem { tracing } => if *tracing { vec![ note!( @@ -756,8 +746,7 @@ impl<'tcx> MiriMachine<'tcx> { "what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free" ), ] - } - } + }, ExternTypeReborrow => { assert!(self.borrow_tracker.as_ref().is_some_and(|b| { matches!( diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index d292bed8457b2..4c531a8d1f526 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -257,35 +257,37 @@ impl<'tcx> MainThreadState<'tcx> { Running => { *self = TlsDtors(Default::default()); } - TlsDtors(state) => match state.on_stack_empty(this)? { - Poll::Pending => {} // just keep going - Poll::Ready(()) => { - if this.machine.data_race.as_genmc_ref().is_some() { - // In GenMC mode, we don't yield at the end of the main thread. - // Instead, the `GenmcCtx` will ensure that unfinished threads get a chance to run at this point. - *self = Done; - } else { - // Give background threads a chance to finish by yielding the main thread a - // couple of times -- but only if we would also preempt threads randomly. - if this.machine.preemption_rate > 0.0 { - // There is a non-zero chance they will yield back to us often enough to - // make Miri terminate eventually. - *self = Yield { remaining: MAIN_THREAD_YIELDS_AT_SHUTDOWN }; - } else { - // The other threads did not get preempted, so no need to yield back to - // them. + TlsDtors(state) => + match state.on_stack_empty(this)? { + Poll::Pending => {} // just keep going + Poll::Ready(()) => { + if this.machine.data_race.as_genmc_ref().is_some() { + // In GenMC mode, we don't yield at the end of the main thread. + // Instead, the `GenmcCtx` will ensure that unfinished threads get a chance to run at this point. *self = Done; + } else { + // Give background threads a chance to finish by yielding the main thread a + // couple of times -- but only if we would also preempt threads randomly. + if this.machine.preemption_rate > 0.0 { + // There is a non-zero chance they will yield back to us often enough to + // make Miri terminate eventually. + *self = Yield { remaining: MAIN_THREAD_YIELDS_AT_SHUTDOWN }; + } else { + // The other threads did not get preempted, so no need to yield back to + // them. + *self = Done; + } } } - } - }, - Yield { remaining } => match remaining.checked_sub(1) { - None => *self = Done, - Some(new_remaining) => { - *remaining = new_remaining; - this.yield_active_thread(); - } - }, + }, + Yield { remaining } => + match remaining.checked_sub(1) { + None => *self = Done, + Some(new_remaining) => { + *remaining = new_remaining; + this.yield_active_thread(); + } + }, Done => { // Figure out exit code. let ret_place = this.machine.main_fn_ret_place.clone().unwrap(); diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index e170bdb168b4f..ab7e35710d349 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -582,9 +582,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn visit_value(&mut self, v: &MPlaceTy<'tcx>) -> InterpResult<'tcx> { trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty); let is_unsafe_cell = match v.layout.ty.kind() { - ty::Adt(adt, _) => { - Some(adt.did()) == self.ecx.tcx.lang_items().unsafe_cell_type() - } + ty::Adt(adt, _) => + Some(adt.did()) == self.ecx.tcx.lang_items().unsafe_cell_type(), _ => false, }; if is_unsafe_cell { @@ -991,11 +990,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { (Scalar::from_int(res.value, int_size), res.status) } // Nothing else - _ => span_bug!( - ecx.cur_span(), - "attempted float-to-int conversion with non-int output type {}", - cast_to.ty, - ), + _ => + span_bug!( + ecx.cur_span(), + "attempted float-to-int conversion with non-int output type {}", + cast_to.ty, + ), } } @@ -1004,18 +1004,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; let (val, status) = match fty { - FloatTy::F16 => { - float_to_int_inner::(this, src.to_scalar().to_f16()?, cast_to, round) - } - FloatTy::F32 => { - float_to_int_inner::(this, src.to_scalar().to_f32()?, cast_to, round) - } - FloatTy::F64 => { - float_to_int_inner::(this, src.to_scalar().to_f64()?, cast_to, round) - } - FloatTy::F128 => { - float_to_int_inner::(this, src.to_scalar().to_f128()?, cast_to, round) - } + FloatTy::F16 => + float_to_int_inner::(this, src.to_scalar().to_f16()?, cast_to, round), + FloatTy::F32 => + float_to_int_inner::(this, src.to_scalar().to_f32()?, cast_to, round), + FloatTy::F64 => + float_to_int_inner::(this, src.to_scalar().to_f64()?, cast_to, round), + FloatTy::F128 => + float_to_int_inner::(this, src.to_scalar().to_f128()?, cast_to, round), }; if status.intersects( @@ -1101,9 +1097,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { array.push(this.read_immediate(&elem)?); } } - _ => throw_unsup_format!( - "only function pointers and arrays of function pointers are supported in well-known linker sections" - ), + _ => + throw_unsup_format!( + "only function pointers and arrays of function pointers are supported in well-known linker sections" + ), } } interp_ok(()) diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs index 1c518282d130d..bcc3e9ec885fd 100644 --- a/src/tools/miri/src/intrinsics/atomic.rs +++ b/src/tools/miri/src/intrinsics/atomic.rs @@ -242,15 +242,12 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { } let old = match atomic_op { - AtomicOp::Min => { - this.atomic_min_max_scalar(&place, rhs, /* min */ true, atomic)? - } - AtomicOp::Max => { - this.atomic_min_max_scalar(&place, rhs, /* min */ false, atomic)? - } - AtomicOp::MirOp(op, not) => { - this.atomic_rmw_op_immediate(&place, &rhs, op, not, atomic)? - } + AtomicOp::Min => + this.atomic_min_max_scalar(&place, rhs, /* min */ true, atomic)?, + AtomicOp::Max => + this.atomic_min_max_scalar(&place, rhs, /* min */ false, atomic)?, + AtomicOp::MirOp(op, not) => + this.atomic_rmw_op_immediate(&place, &rhs, op, not, atomic)?, }; this.write_immediate(*old, dest)?; // old value is returned interp_ok(()) diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index a163161186fea..b5e81460773ba 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -497,18 +497,14 @@ fn apply_random_float_error_to_imm<'tcx>( ) -> InterpResult<'tcx, ImmTy<'tcx>> { let scalar = val.to_scalar_int()?; let res: ScalarInt = match val.layout.ty.kind() { - ty::Float(FloatTy::F16) => { - apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into() - } - ty::Float(FloatTy::F32) => { - apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into() - } - ty::Float(FloatTy::F64) => { - apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into() - } - ty::Float(FloatTy::F128) => { - apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into() - } + ty::Float(FloatTy::F16) => + apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into(), + ty::Float(FloatTy::F32) => + apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into(), + ty::Float(FloatTy::F64) => + apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into(), + ty::Float(FloatTy::F128) => + apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into(), _ => bug!("intrinsic called with non-float input type"), }; @@ -611,13 +607,11 @@ fn fixed_powi_float_value( fn clamp_float_value(intrinsic_name: &str, val: IeeeFloat) -> IeeeFloat { match intrinsic_name { // sin and cos: [-1, 1] - "sinf32" | "cosf32" | "sinf64" | "cosf64" => { - val.clamp(IeeeFloat::::one().neg(), IeeeFloat::::one()) - } + "sinf32" | "cosf32" | "sinf64" | "cosf64" => + val.clamp(IeeeFloat::::one().neg(), IeeeFloat::::one()), // exp: [0, +INF] - "expf32" | "exp2f32" | "expf64" | "exp2f64" => { - IeeeFloat::::maximum(val, IeeeFloat::::ZERO) - } + "expf32" | "exp2f32" | "expf64" | "exp2f64" => + IeeeFloat::::maximum(val, IeeeFloat::::ZERO), _ => val, } } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 095ce003574d7..8f0814a070cbf 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -837,16 +837,17 @@ impl<'tcx> MiriMachine<'tcx> { let data_race = match &ecx.machine.data_race { GlobalDataRaceHandler::None => AllocDataRaceHandler::None, - GlobalDataRaceHandler::Vclocks(data_race) => AllocDataRaceHandler::Vclocks( - data_race::AllocState::new_allocation( - data_race, - &ecx.machine.threads, - size, - kind, - ecx.machine.current_span(), + GlobalDataRaceHandler::Vclocks(data_race) => + AllocDataRaceHandler::Vclocks( + data_race::AllocState::new_allocation( + data_race, + &ecx.machine.threads, + size, + kind, + ecx.machine.current_span(), + ), + data_race.weak_memory.then(weak_memory::AllocState::new_allocation), ), - data_race.weak_memory.then(weak_memory::AllocState::new_allocation), - ), GlobalDataRaceHandler::Genmc(_genmc_ctx) => { // GenMC learns about new allocations directly from the alloc_addresses module, // since it has to be able to control the address at which they are placed. @@ -1390,9 +1391,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { // The order of checks is deliberate, to prefer reporting a data race over a borrow tracker error. match &machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Genmc(genmc_ctx) => { - genmc_ctx.memory_load(machine, ptr.addr(), range.size)? - } + GlobalDataRaceHandler::Genmc(genmc_ctx) => + genmc_ctx.memory_load(machine, ptr.addr(), range.size)?, GlobalDataRaceHandler::Vclocks(_data_race) => { let AllocDataRaceHandler::Vclocks(data_race, weak_memory) = &alloc_extra.data_race else { @@ -1462,9 +1462,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } match &machine.data_race { GlobalDataRaceHandler::None => {} - GlobalDataRaceHandler::Genmc(genmc_ctx) => { - genmc_ctx.handle_dealloc(machine, ptr.addr(), size, align, kind)? - } + GlobalDataRaceHandler::Genmc(genmc_ctx) => + genmc_ctx.handle_dealloc(machine, ptr.addr(), size, align, kind)?, GlobalDataRaceHandler::Vclocks(_global_state) => { let data_race = alloc_extra.data_race.as_vclocks_mut().unwrap(); data_race.write( diff --git a/src/tools/miri/src/math.rs b/src/tools/miri/src/math.rs index 518e213099e2b..e9e5a1070c9e4 100644 --- a/src/tools/miri/src/math.rs +++ b/src/tools/miri/src/math.rs @@ -59,18 +59,14 @@ pub(crate) fn apply_random_float_error_to_imm<'tcx>( ) -> InterpResult<'tcx, ImmTy<'tcx>> { let scalar = val.to_scalar_int()?; let res: ScalarInt = match val.layout.ty.kind() { - ty::Float(FloatTy::F16) => { - apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into() - } - ty::Float(FloatTy::F32) => { - apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into() - } - ty::Float(FloatTy::F64) => { - apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into() - } - ty::Float(FloatTy::F128) => { - apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into() - } + ty::Float(FloatTy::F16) => + apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into(), + ty::Float(FloatTy::F32) => + apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into(), + ty::Float(FloatTy::F64) => + apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into(), + ty::Float(FloatTy::F128) => + apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into(), _ => bug!("intrinsic called with non-float input type"), }; diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index e20b8780bceb6..bd3914b652ac9 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -67,15 +67,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { 0 => { throw_unsup_format!("miri_get_backtrace: v0 is not supported any more"); } - 1 => { + 1 => for (i, ptr) in ptrs.into_iter().enumerate() { let offset = ptr_layout.size.checked_mul(i.to_u64(), this).unwrap(); let op_place = buf_place.offset(offset, ptr_layout, this)?; this.write_pointer(ptr, &op_place)?; - } - } + }, _ => throw_unsup_format!("unknown `miri_get_backtrace` flags {}", flags), }; diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 1b0d8d063a14a..21545b680299c 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -1045,26 +1045,22 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Platform-specific shims - _ => { + _ => return match this.tcx.sess.target.os.as_ref() { - _ if this.target_os_is_unix() => { + _ if this.target_os_is_unix() => shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, - ) - } - "wasi" => { + ), + "wasi" => shims::wasi::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, - ) - } - "windows" => { + ), + "windows" => shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, - ) - } + ), _ => interp_ok(EmulateItemResult::NotSupported), - }; - } + }, }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. diff --git a/src/tools/miri/src/shims/global_ctor.rs b/src/tools/miri/src/shims/global_ctor.rs index 18e9752be577a..c56251bbe63ae 100644 --- a/src/tools/miri/src/shims/global_ctor.rs +++ b/src/tools/miri/src/shims/global_ctor.rs @@ -33,17 +33,17 @@ impl<'tcx> GlobalCtorState<'tcx> { // Lookup constructors from the relevant magic link section. let ctors = match this.tcx.sess.target.binary_format { // Read the CRT library section on Windows. - BinaryFormat::Coff => { - this.lookup_link_section(|section| section == ".CRT$XCU")? - } + BinaryFormat::Coff => + this.lookup_link_section(|section| section == ".CRT$XCU")?, // Read the `__mod_init_func` section on macOS. - BinaryFormat::MachO => this.lookup_link_section(|section| { - let mut parts = section.splitn(3, ','); - let (segment_name, section_name, section_type) = - (parts.next(), parts.next(), parts.next()); + BinaryFormat::MachO => + this.lookup_link_section(|section| { + let mut parts = section.splitn(3, ','); + let (segment_name, section_name, section_type) = + (parts.next(), parts.next(), parts.next()); - segment_name == Some("__DATA") + segment_name == Some("__DATA") && section_name == Some("__mod_init_func") // The `mod_init_funcs` directive ensures that the // `S_MOD_INIT_FUNC_POINTERS` flag is set on the section. LLVM @@ -52,14 +52,13 @@ impl<'tcx> GlobalCtorState<'tcx> { // implicitly add it here. Also see // . && matches!(section_type, None | Some("mod_init_funcs")) - })?, + })?, // Read the standard `.init_array` section on platforms that use ELF, or WASM, // which supports the same linker directive. // FIXME: Add support for `.init_array.N` and `.ctors`? - BinaryFormat::Elf | BinaryFormat::Wasm => { - this.lookup_link_section(|section| section == ".init_array")? - } + BinaryFormat::Elf | BinaryFormat::Wasm => + this.lookup_link_section(|section| section == ".init_array")?, // Other platforms have no global ctor support. _ => break 'new_state Done, diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs index 231e98daf1367..e597b527cb7a8 100644 --- a/src/tools/miri/src/shims/io_error.rs +++ b/src/tools/miri/src/shims/io_error.rs @@ -17,18 +17,19 @@ pub use self::IoError::*; impl IoError { pub(crate) fn into_ntstatus(self) -> i32 { let raw = match self { - HostError(e) => match e.kind() { - // STATUS_MEDIA_WRITE_PROTECTED - ErrorKind::ReadOnlyFilesystem => 0xC00000A2u32, - // STATUS_FILE_INVALID - ErrorKind::InvalidInput => 0xC0000098, - // STATUS_DISK_FULL - ErrorKind::QuotaExceeded => 0xC000007F, - // STATUS_ACCESS_DENIED - ErrorKind::PermissionDenied => 0xC0000022, - // For the default error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. - _ => 0xC0000185, - }, + HostError(e) => + match e.kind() { + // STATUS_MEDIA_WRITE_PROTECTED + ErrorKind::ReadOnlyFilesystem => 0xC00000A2u32, + // STATUS_FILE_INVALID + ErrorKind::InvalidInput => 0xC0000098, + // STATUS_DISK_FULL + ErrorKind::QuotaExceeded => 0xC000007F, + // STATUS_ACCESS_DENIED + ErrorKind::PermissionDenied => 0xC0000022, + // For the default error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. + _ => 0xC0000185, + }, // For the default error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR. _ => 0xC0000185, }; diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs index 1b7c4e3696cb8..2827ed997a7c6 100644 --- a/src/tools/miri/src/shims/native_lib/mod.rs +++ b/src/tools/miri/src/shims/native_lib/mod.rs @@ -144,13 +144,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let ptr = Pointer::new(Provenance::Wildcard, Size::from_bytes(x.addr())); Scalar::from_pointer(ptr, this) } - _ => { + _ => return Err(err_unsup_format!( "unsupported return type for native call: {:?}", link_name )) - .into(); - } + .into(), }; interp_ok(ImmTy::from_scalar(scalar, dest.layout)) }) @@ -444,17 +443,15 @@ fn imm_to_carg<'tcx>(v: &ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<' ty::Int(IntTy::I16) => CArg::Int16(v.to_scalar().to_i16()?), ty::Int(IntTy::I32) => CArg::Int32(v.to_scalar().to_i32()?), ty::Int(IntTy::I64) => CArg::Int64(v.to_scalar().to_i64()?), - ty::Int(IntTy::Isize) => { - CArg::ISize(v.to_scalar().to_target_isize(cx)?.try_into().unwrap()) - } + ty::Int(IntTy::Isize) => + CArg::ISize(v.to_scalar().to_target_isize(cx)?.try_into().unwrap()), // the uints ty::Uint(UintTy::U8) => CArg::UInt8(v.to_scalar().to_u8()?), ty::Uint(UintTy::U16) => CArg::UInt16(v.to_scalar().to_u16()?), ty::Uint(UintTy::U32) => CArg::UInt32(v.to_scalar().to_u32()?), ty::Uint(UintTy::U64) => CArg::UInt64(v.to_scalar().to_u64()?), - ty::Uint(UintTy::Usize) => { - CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()) - } + ty::Uint(UintTy::Usize) => + CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()), ty::RawPtr(..) => { let s = v.to_scalar().to_pointer(cx)?.addr(); // This relies on the `expose_provenance` in the `visit_reachable_allocs` callback diff --git a/src/tools/miri/src/shims/native_lib/trace/child.rs b/src/tools/miri/src/shims/native_lib/trace/child.rs index 70f62fdfa0fdb..b998ba822dde4 100644 --- a/src/tools/miri/src/shims/native_lib/trace/child.rs +++ b/src/tools/miri/src/shims/native_lib/trace/child.rs @@ -142,10 +142,11 @@ impl Supervisor { let events = sv .event_rx .try_recv_timeout(std::time::Duration::from_secs(5)) - .map_err(|e| match e { - ipc::TryRecvError::IpcError(_) => (), - ipc::TryRecvError::Empty => { - panic!("Waiting for accesses from supervisor timed out!") + .map_err(|e| { + match e { + ipc::TryRecvError::IpcError(_) => (), + ipc::TryRecvError::Empty => + panic!("Waiting for accesses from supervisor timed out!"), } }) .ok(); diff --git a/src/tools/miri/src/shims/native_lib/trace/parent.rs b/src/tools/miri/src/shims/native_lib/trace/parent.rs index 9640fccdd762e..83f6c7a13fcfe 100644 --- a/src/tools/miri/src/shims/native_lib/trace/parent.rs +++ b/src/tools/miri/src/shims/native_lib/trace/parent.rs @@ -120,51 +120,49 @@ impl Iterator for ChildListener { // defensive programming since Linux sometimes assigns threads of // the same process different PIDs with unpredictable rules... match wait::waitid(wait::Id::All, opts) { - Ok(stat) => match stat { - // Child exited normally with a specific code set. - wait::WaitStatus::Exited(_, code) => self.last_code = Some(code), - // Child was killed by a signal, without giving a code. - wait::WaitStatus::Signaled(_, _, _) => self.last_code = None, - // Child entered or exited a syscall. - wait::WaitStatus::PtraceSyscall(pid) => { - if self.attached { - return Some(ExecEvent::Syscall(pid)); - } - } - // Child with the given pid was stopped by the given signal. - // It's somewhat dubious when this is returned instead of - // WaitStatus::Stopped, but for our purposes they are the - // same thing. - wait::WaitStatus::PtraceEvent(pid, signal, _) => { - if self.attached { - // This is our end-of-FFI signal! - if signal == signal::SIGUSR1 { - self.attached = false; - return Some(ExecEvent::End); + Ok(stat) => + match stat { + // Child exited normally with a specific code set. + wait::WaitStatus::Exited(_, code) => self.last_code = Some(code), + // Child was killed by a signal, without giving a code. + wait::WaitStatus::Signaled(_, _, _) => self.last_code = None, + // Child entered or exited a syscall. + wait::WaitStatus::PtraceSyscall(pid) => + if self.attached { + return Some(ExecEvent::Syscall(pid)); + }, + // Child with the given pid was stopped by the given signal. + // It's somewhat dubious when this is returned instead of + // WaitStatus::Stopped, but for our purposes they are the + // same thing. + wait::WaitStatus::PtraceEvent(pid, signal, _) => + if self.attached { + // This is our end-of-FFI signal! + if signal == signal::SIGUSR1 { + self.attached = false; + return Some(ExecEvent::End); + } else { + return Some(ExecEvent::Status(pid, signal)); + } } else { - return Some(ExecEvent::Status(pid, signal)); - } - } else { - // Just pass along the signal. - ptrace::cont(pid, signal).unwrap(); - } - } - // Child was stopped at the given signal. Same logic as for - // WaitStatus::PtraceEvent. - wait::WaitStatus::Stopped(pid, signal) => { - if self.attached { - if signal == signal::SIGUSR1 { - self.attached = false; - return Some(ExecEvent::End); + // Just pass along the signal. + ptrace::cont(pid, signal).unwrap(); + }, + // Child was stopped at the given signal. Same logic as for + // WaitStatus::PtraceEvent. + wait::WaitStatus::Stopped(pid, signal) => + if self.attached { + if signal == signal::SIGUSR1 { + self.attached = false; + return Some(ExecEvent::End); + } else { + return Some(ExecEvent::Status(pid, signal)); + } } else { - return Some(ExecEvent::Status(pid, signal)); - } - } else { - ptrace::cont(pid, signal).unwrap(); - } - } - _ => (), - }, + ptrace::cont(pid, signal).unwrap(); + }, + _ => (), + }, // This case should only trigger when all children died. Err(_) => return Some(ExecEvent::Died(self.override_retcode.or(self.last_code))), } @@ -174,14 +172,12 @@ impl Iterator for ChildListener { match req { TraceRequest::StartFfi(info) => // Should never trigger - but better to panic explicitly than deadlock! - { if self.attached { panic!("Attempting to begin FFI multiple times!"); } else { self.attached = true; return Some(ExecEvent::Start(info)); - } - } + }, TraceRequest::OverrideRetcode(code) => { self.override_retcode = Some(code); self.confirm_tx.send(Confirmation).unwrap(); @@ -269,28 +265,30 @@ pub fn sv_loop( ptrace::cont(curr_pid, None).unwrap(); } // Child process was stopped by a signal - ExecEvent::Status(pid, signal) => match signal { - // If it was a segfault, check if it was an artificial one - // caused by it trying to access the MiriMachine memory. - signal::SIGSEGV => handle_segfault( - pid, - &ch_pages, - ch_stack.unwrap(), - page_size, - &cs, - &mut acc_events, - )?, - // Something weird happened. - _ => { - eprintln!("Process unexpectedly got {signal}; continuing..."); - // In case we're not tracing - if ptrace::syscall(pid, None).is_err() { - // If *this* fails too, something really weird happened - // and it's probably best to just panic. - signal::kill(pid, signal::SIGCONT).unwrap(); + ExecEvent::Status(pid, signal) => + match signal { + // If it was a segfault, check if it was an artificial one + // caused by it trying to access the MiriMachine memory. + signal::SIGSEGV => + handle_segfault( + pid, + &ch_pages, + ch_stack.unwrap(), + page_size, + &cs, + &mut acc_events, + )?, + // Something weird happened. + _ => { + eprintln!("Process unexpectedly got {signal}; continuing..."); + // In case we're not tracing + if ptrace::syscall(pid, None).is_err() { + // If *this* fails too, something really weird happened + // and it's probably best to just panic. + signal::kill(pid, signal::SIGCONT).unwrap(); + } } - } - }, + }, // Child entered a syscall; we wait for exits inside of this, so it // should never trigger on return from a syscall we care about. ExecEvent::Syscall(pid) => { diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 7855ac776ffe1..b5b35797fec2f 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -74,11 +74,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?; system_time_to_duration(&SystemTime::now())? } - Some(TimeoutClock::Monotonic) => this - .machine - .monotonic_clock - .now() - .duration_since(this.machine.monotonic_clock.epoch()), + Some(TimeoutClock::Monotonic) => + this.machine + .monotonic_clock + .now() + .duration_since(this.machine.monotonic_clock.epoch()), None => { return this.set_last_error_and_return(LibcError("EINVAL"), dest); } diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 4365a18f298d9..55906f4eb9548 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -26,14 +26,15 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool { // needed at least on macOS to avoid file-based fallback in getrandom "getentropy" | "getrandom" => true, // Give specific OSes a chance to allow their symbols. - _ => match target_os { - "android" => android::is_dyn_sym(name), - "freebsd" => freebsd::is_dyn_sym(name), - "linux" => linux::is_dyn_sym(name), - "macos" => macos::is_dyn_sym(name), - "solaris" | "illumos" => solarish::is_dyn_sym(name), - _ => false, - }, + _ => + match target_os { + "android" => android::is_dyn_sym(name), + "freebsd" => freebsd::is_dyn_sym(name), + "linux" => linux::is_dyn_sym(name), + "macos" => macos::is_dyn_sym(name), + "solaris" | "illumos" => solarish::is_dyn_sym(name), + _ => false, + }, } } @@ -878,9 +879,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // TODO: when https://github.com/rust-lang/miri/issues/3730 is fixed this should use its notion of tid/pid let thread_id = match pid { 0 => this.active_thread(), - _ => throw_unsup_format!( - "`sched_getaffinity` is only supported with a pid of 0 (indicating the current thread)" - ), + _ => + throw_unsup_format!( + "`sched_getaffinity` is only supported with a pid of 0 (indicating the current thread)" + ), }; // The mask is stored in chunks, and the size must be a whole number of chunks. @@ -915,9 +917,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // TODO: when https://github.com/rust-lang/miri/issues/3730 is fixed this should use its notion of tid/pid let thread_id = match pid { 0 => this.active_thread(), - _ => throw_unsup_format!( - "`sched_setaffinity` is only supported with a pid of 0 (indicating the current thread)" - ), + _ => + throw_unsup_format!( + "`sched_setaffinity` is only supported with a pid of 0 (indicating the current thread)" + ), }; if this.ptr_is_null(mask)? { @@ -1143,21 +1146,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { _ => { let target_os = &*this.tcx.sess.target.os; return match target_os { - "android" => android::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), - "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), - "linux" => linux::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), - "macos" => macos::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), - "solaris" | "illumos" => solarish::EvalContextExt::emulate_foreign_item_inner( - this, link_name, abi, args, dest, - ), + "android" => + android::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), + "freebsd" => + freebsd::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), + "linux" => + linux::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), + "macos" => + macos::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), + "solaris" | "illumos" => + solarish::EvalContextExt::emulate_foreign_item_inner( + this, link_name, abi, args, dest, + ), _ => interp_ok(EmulateItemResult::NotSupported), }; } diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index aa4b3b84e2c8c..9e247053fbcdb 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -89,9 +89,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // TODO: Use gettid? I'm (LorrensP-2158466) not that familiar with this api . let id = match id { -1 => this.active_thread(), - _ => throw_unsup_format!( - "`cpuset_getaffinity` is only supported with a pid of -1 (indicating the current thread)" - ), + _ => + throw_unsup_format!( + "`cpuset_getaffinity` is only supported with a pid of -1 (indicating the current thread)" + ), }; if this.ptr_is_null(mask)? { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 27488fa03d212..f9bcacf64c412 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -105,13 +105,12 @@ impl UnixFileDescription for FileHandle { match res { Ok(()) => interp_ok(Ok(())), Err(TryLockError::Error(err)) => interp_ok(Err(err)), - Err(TryLockError::WouldBlock) => { + Err(TryLockError::WouldBlock) => if nonblocking { interp_ok(Err(ErrorKind::WouldBlock.into())) } else { throw_unsup_format!("blocking `flock` is not currently supported"); - } - } + }, } } } @@ -187,26 +186,21 @@ trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> { match () { _ if file_type.is_dir() => interp_ok(this.eval_libc("DT_DIR").to_u8()?.into()), _ if file_type.is_file() => interp_ok(this.eval_libc("DT_REG").to_u8()?.into()), - _ if file_type.is_symlink() => { - interp_ok(this.eval_libc("DT_LNK").to_u8()?.into()) - } + _ if file_type.is_symlink() => + interp_ok(this.eval_libc("DT_LNK").to_u8()?.into()), // Certain file types are only supported when the host is a Unix system. #[cfg(unix)] - _ if file_type.is_block_device() => { - interp_ok(this.eval_libc("DT_BLK").to_u8()?.into()) - } + _ if file_type.is_block_device() => + interp_ok(this.eval_libc("DT_BLK").to_u8()?.into()), #[cfg(unix)] - _ if file_type.is_char_device() => { - interp_ok(this.eval_libc("DT_CHR").to_u8()?.into()) - } + _ if file_type.is_char_device() => + interp_ok(this.eval_libc("DT_CHR").to_u8()?.into()), #[cfg(unix)] - _ if file_type.is_fifo() => { - interp_ok(this.eval_libc("DT_FIFO").to_u8()?.into()) - } + _ if file_type.is_fifo() => + interp_ok(this.eval_libc("DT_FIFO").to_u8()?.into()), #[cfg(unix)] - _ if file_type.is_socket() => { - interp_ok(this.eval_libc("DT_SOCK").to_u8()?.into()) - } + _ if file_type.is_socket() => + interp_ok(this.eval_libc("DT_SOCK").to_u8()?.into()), // Fallback _ => interp_ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into()), } @@ -1508,16 +1502,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let fd = this.machine.fds.insert_new(FileHandle { file: f, writable: true }); return interp_ok(Scalar::from_i32(fd)); } - Err(e) => match e.kind() { - // If the random file already exists, keep trying. - ErrorKind::AlreadyExists => continue, - // Any other errors are returned to the caller. - _ => { - // "On error, -1 is returned, and errno is set to - // indicate the error" - return this.set_last_error_and_return_i32(e); - } - }, + Err(e) => + match e.kind() { + // If the random file already exists, keep trying. + ErrorKind::AlreadyExists => continue, + // Any other errors are returned to the caller. + _ => { + // "On error, -1 is returned, and errno is set to + // indicate the error" + return this.set_last_error_and_return_i32(e); + } + }, } } diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index be2d27981ea0b..05616dd5a4287 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -145,10 +145,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { .to_bits(Size::from_bytes(size))?; let futex = this - .get_sync_or_init(ptr, |_| MacOsFutex { - futex: Default::default(), - size: Cell::new(size), - shared: Cell::new(is_shared), + .get_sync_or_init(ptr, |_| { + MacOsFutex { + futex: Default::default(), + size: Cell::new(size), + shared: Cell::new(is_shared), + } }) .unwrap(); @@ -228,10 +230,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let is_shared = flags == shared; - let Some(futex) = this.get_sync_or_init(ptr, |_| MacOsFutex { - futex: Default::default(), - size: Cell::new(size), - shared: Cell::new(is_shared), + let Some(futex) = this.get_sync_or_init(ptr, |_| { + MacOsFutex { + futex: Default::default(), + size: Cell::new(size), + shared: Cell::new(is_shared), + } }) else { // No AllocId, or no live allocation at that AllocId. Return an // error code. (That seems nicer than silently doing something diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 6b361e680a59f..5ad4fd501a607 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -212,13 +212,12 @@ fn mutex_kind_from_static_initializer<'tcx>( } // Support additional platform-specific initializers. match &*ecx.tcx.sess.target.os { - "linux" => { + "linux" => if is_initializer("PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP")? { return interp_ok(MutexKind::Recursive); } else if is_initializer("PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP")? { return interp_ok(MutexKind::ErrorCheck); - } - } + }, _ => {} } throw_unsup_format!("unsupported static initializer used for `pthread_mutex_t`"); @@ -492,9 +491,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { // Trying to acquire the same mutex again. match mutex.kind { - MutexKind::Default => throw_ub_format!( - "trying to acquire default mutex already locked by the current thread" - ), + MutexKind::Default => + throw_ub_format!( + "trying to acquire default mutex already locked by the current thread" + ), MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock), MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"), MutexKind::Recursive => { @@ -522,9 +522,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.eval_libc_i32("EBUSY") } else { match mutex.kind { - MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck => { - this.eval_libc_i32("EBUSY") - } + MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck => + this.eval_libc_i32("EBUSY"), MutexKind::Recursive => { this.mutex_lock(&mutex.mutex_ref); 0 @@ -551,15 +550,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the “Unlock When Not Owner” column in // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html. match mutex.kind { - MutexKind::Default => throw_ub_format!( - "unlocked a default mutex that was not locked by the current thread" - ), - MutexKind::Normal => throw_ub_format!( - "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" - ), - MutexKind::ErrorCheck | MutexKind::Recursive => { - interp_ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))) - } + MutexKind::Default => + throw_ub_format!( + "unlocked a default mutex that was not locked by the current thread" + ), + MutexKind::Normal => + throw_ub_format!( + "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" + ), + MutexKind::ErrorCheck | MutexKind::Recursive => + interp_ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))), } } } diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs index 2b8768fe7823f..8a965ea316d72 100644 --- a/src/tools/miri/src/shims/windows/handle.rs +++ b/src/tools/miri/src/shims/windows/handle.rs @@ -209,18 +209,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let handle = this.read_scalar(handle)?; match Handle::try_from_scalar(handle, this)? { Ok(handle) => interp_ok(handle), - Err(HandleError::InvalidHandle) => { + Err(HandleError::InvalidHandle) => throw_machine_stop!(TerminationInfo::Abort(format!( "invalid handle {} passed to {function_name}", handle.to_target_isize(this)?, - ))) - } - Err(HandleError::ThreadNotFound(_)) => { + ))), + Err(HandleError::ThreadNotFound(_)) => throw_machine_stop!(TerminationInfo::Abort(format!( "invalid thread ID {} passed to {function_name}", handle.to_target_isize(this)?, - ))) - } + ))), } } @@ -333,7 +331,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.detach_thread(thread, /*allow_terminated_joined*/ true)?; this.eval_windows("c", "TRUE") } - Handle::File(fd_num) => { + Handle::File(fd_num) => if let Some(fd) = this.machine.fds.remove(fd_num) { let err = fd.close_ref(this.machine.communicate(), this)?; if let Err(e) = err { @@ -344,8 +342,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } else { this.invalid_handle("CloseHandle")? - } - } + }, _ => this.invalid_handle("CloseHandle")?, }; diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index 1a2f66a293fe7..269ce3b51b93f 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -329,9 +329,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let res = match unprefixed_name { "vtestz.pd.256" | "vtestz.pd" | "vtestz.ps.256" | "vtestz.ps" => direct, "vtestc.pd.256" | "vtestc.pd" | "vtestc.ps.256" | "vtestc.ps" => negated, - "vtestnzc.pd.256" | "vtestnzc.pd" | "vtestnzc.ps.256" | "vtestnzc.ps" => { - !direct && !negated - } + "vtestnzc.pd.256" | "vtestnzc.pd" | "vtestnzc.ps.256" | "vtestnzc.ps" => + !direct && !negated, _ => unreachable!(), }; From 171077cfcdffd56e93fa764bad6692becd93a4b2 Mon Sep 17 00:00:00 2001 From: OneProg Date: Thu, 31 Jul 2025 13:44:44 +0300 Subject: [PATCH 3/5] Now, the text of the error that occurs when the order of formatting arguments is incorrect is clearer --- compiler/rustc_parse_format/src/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 8e4da7923fcb5..c279e8160ba1b 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -858,9 +858,12 @@ impl<'input> Parser<'input> { self.errors.insert( 0, ParseError { - description: "expected format parameter to occur after `:`".to_owned(), - note: None, - label: format!("expected `{}` to occur after `:`", alignment), + description: "expected format parameter to occur in its right place".to_owned(), + note: Some( + "See https://doc.rust-lang.org/std/fmt/index.html#syntax for more details" + .to_string(), + ), + label: format!("expected `{}` to occur in its right place", alignment), span: range, secondary_label: None, suggestion: Suggestion::None, From fdd084373aec85f431533a1186fa021e8bd5f1dc Mon Sep 17 00:00:00 2001 From: OneProg Date: Thu, 31 Jul 2025 13:58:28 +0300 Subject: [PATCH 4/5] Now, the text of the error that occurs when the order of formatting arguments is incorrect is clearer --- compiler/rustc_parse_format/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index c279e8160ba1b..daec4faa0c1c1 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -858,7 +858,8 @@ impl<'input> Parser<'input> { self.errors.insert( 0, ParseError { - description: "expected format parameter to occur in its right place".to_owned(), + description: "expected format parameter to occur in its right place" + .to_string(), note: Some( "See https://doc.rust-lang.org/std/fmt/index.html#syntax for more details" .to_string(), From f459d76f34e9cb227babeb3fd6706b23f905f318 Mon Sep 17 00:00:00 2001 From: OneProg Date: Thu, 31 Jul 2025 14:00:47 +0300 Subject: [PATCH 5/5] Now, the text of the error that occurs when the order of formatting arguments is incorrect is clearer --- compiler/rustc_parse_format/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index daec4faa0c1c1..c938f073a8e94 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -858,11 +858,10 @@ impl<'input> Parser<'input> { self.errors.insert( 0, ParseError { - description: "expected format parameter to occur in its right place" - .to_string(), + description: "expected format parameter to occur in its right place".to_owned(), note: Some( "See https://doc.rust-lang.org/std/fmt/index.html#syntax for more details" - .to_string(), + .to_owned(), ), label: format!("expected `{}` to occur in its right place", alignment), span: range,