Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
daf5929
Prepare for merging from rust-lang/rust
Nov 30, 2025
ce49398
Merge ref '3ff30e7eafc1' from rust-lang/rust
Nov 30, 2025
ad7ba50
bless genmc tests
RalfJung Nov 30, 2025
8eb411b
use fully deterministic concurrency for while-queued tests
RalfJung Nov 30, 2025
e8f57f8
Merge pull request #4736 from rust-lang/rustup-2025-11-30
RalfJung Nov 30, 2025
8d01e72
Call rustc_driver::main() for MIRI_BE_RUSTC=host
bjorn3 Nov 4, 2025
f9d8a18
Merge pull request #4731 from bjorn3/simplify_driver
RalfJung Dec 2, 2025
ccde7d4
Support retagging of wildcard references in tree borrows
royAmmerschuber Nov 10, 2025
fb5eb59
Merge pull request #4707 from royAmmerschuber/feature/wildcard-root
RalfJung Dec 3, 2025
f04ad99
rust-analyzer settings: use --compile-time-deps
RalfJung Dec 3, 2025
12b9ce2
Merge pull request #4738 from RalfJung/ra
RalfJung Dec 3, 2025
88c2c81
factor out tree_visitor into own file
royAmmerschuber Dec 3, 2025
9622840
make tree_visitor generic
royAmmerschuber Dec 3, 2025
66e9c33
Prepare for merging from rust-lang/rust
Dec 5, 2025
6661762
Merge ref '864339abf952' from rust-lang/rust
Dec 5, 2025
6cf7bd5
Merge pull request #4742 from rust-lang/rustup-2025-12-05
oli-obk Dec 5, 2025
de3100e
Prepare for merging from rust-lang/rust
Dec 6, 2025
741862c
Merge ref '36b2369c91d3' from rust-lang/rust
Dec 6, 2025
77825a2
ubuntu riscv64 is broken even with extensive retries
RalfJung Dec 6, 2025
c9d097d
Merge pull request #4743 from rust-lang/rustup-2025-12-06
RalfJung Dec 6, 2025
1647f44
feat: Support fstat in linux
hulxv Nov 21, 2025
8b9d1d7
use correct stat type and fix some redundancy
RalfJung Dec 6, 2025
e7650fd
Merge pull request #4714 from hulxv/feat/support-fstat-in-linux
RalfJung Dec 6, 2025
44aaae3
remove readdir_r on FreeBSD: it is deprecated, unused, and untested
RalfJung Dec 6, 2025
a26b26a
cleanup: the *64 functions are Linux-specific
RalfJung Dec 6, 2025
ccefb74
Merge pull request #4745 from RalfJung/fs-shim-cleanup
RalfJung Dec 6, 2025
73f124e
Merge pull request #4739 from royAmmerschuber/feature/refactor-tree-v…
RalfJung Dec 6, 2025
7ad3301
show span when there is an error invoking a global ctor/dtor or the t…
RalfJung Dec 6, 2025
5339794
Merge pull request #4747 from RalfJung/empty-stack-error
RalfJung Dec 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/tools/miri/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ jobs:
os: ubuntu-24.04-arm
multiarch: armhf
gcc_cross: arm-linux-gnueabihf
- host_target: riscv64gc-unknown-linux-gnu
os: ubuntu-latest
multiarch: riscv64
gcc_cross: riscv64-linux-gnu
qemu: true
# Ubuntu mirrors are not reliable enough for these architectures
# (see <https://bugs.launchpad.net/ubuntu/+bug/2130309>).
# - host_target: riscv64gc-unknown-linux-gnu
# os: ubuntu-latest
# multiarch: riscv64
# gcc_cross: riscv64-linux-gnu
# qemu: true
# - host_target: s390x-unknown-linux-gnu
# os: ubuntu-latest
# multiarch: s390x
Expand Down
1 change: 1 addition & 0 deletions src/tools/miri/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ Definite bugs found:
* [Mockall reading uninitialized memory when mocking `std::io::Read::read`, even if all expectations are satisfied](https://github.com/asomers/mockall/issues/647) (caught by Miri running Tokio's test suite)
* [`ReentrantLock` not correctly dealing with reuse of addresses for TLS storage of different threads](https://github.com/rust-lang/rust/pull/141248)
* [Rare Deadlock in the thread (un)parking example code](https://github.com/rust-lang/rust/issues/145816)
* [`winit` registering a global constructor with the wrong ABI on Windows](https://github.com/rust-windowing/winit/issues/4435)

Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment):

Expand Down
2 changes: 2 additions & 0 deletions src/tools/miri/etc/rust_analyzer_helix.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@ overrideCommand = [
"./miri",
"check",
"--no-default-features",
"-Zunstable-options",
"--compile-time-deps",
"--message-format=json",
]
2 changes: 2 additions & 0 deletions src/tools/miri/etc/rust_analyzer_vscode.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"./miri",
"check",
"--no-default-features",
"-Zunstable-options",
"--compile-time-deps",
"--message-format=json",
],
}
2 changes: 2 additions & 0 deletions src/tools/miri/etc/rust_analyzer_zed.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
"./miri",
"check",
"--no-default-features",
"-Zunstable-options",
"--compile-time-deps",
"--message-format=json"
]
}
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1eb0657f78777f0b4d6bcc49c126d5d35212cae5
36b2369c91d32c2659887ed6fe3d570640f44fd2
63 changes: 25 additions & 38 deletions src/tools/miri/src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,18 +272,13 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
}
}

struct MiriBeRustCompilerCalls {
target_crate: bool,
}
/// This compiler produces rlibs that are meant for later consumption by Miri.
struct MiriDepCompilerCalls;

impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
impl rustc_driver::Callbacks for MiriDepCompilerCalls {
#[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint
fn config(&mut self, config: &mut Config) {
if !self.target_crate {
// For a host crate, we fully behave like rustc.
return;
}
// For a target crate, we emit an rlib that Miri can later consume.
// We don't need actual codegen, we just emit an rlib that Miri can later consume.
config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend));

// Avoid warnings about unsupported crate types. However, only do that we we are *not* being
Expand Down Expand Up @@ -367,16 +362,12 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
_: &rustc_interface::interface::Compiler,
tcx: TyCtxt<'tcx>,
) -> Compilation {
if self.target_crate {
// cargo-miri has patched the compiler flags to make these into check-only builds,
// but we are still emulating regular rustc builds, which would perform post-mono
// const-eval during collection. So let's also do that here, even if we might be
// running with `--emit=metadata`. In particular this is needed to make
// `compile_fail` doc tests trigger post-mono errors.
// In general `collect_and_partition_mono_items` is not safe to call in check-only
// builds, but we are setting `-Zalways-encode-mir` which avoids those issues.
let _ = tcx.collect_and_partition_mono_items(());
}
// While the dummy codegen backend doesn't do any codegen, we are still emulating
// regular rustc builds, which would perform post-mono const-eval during collection.
// So let's also do that here. In particular this is needed to make `compile_fail`
// doc tests trigger post-mono errors.
let _ = tcx.collect_and_partition_mono_items(());

Compilation::Continue
}
}
Expand Down Expand Up @@ -457,32 +448,28 @@ fn main() {

// If the environment asks us to actually be rustc, then do that.
if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
if crate_kind == "host" {
// For host crates like proc macros and build scripts, we are an entirely normal rustc.
// These eventually produce actual binaries and never run in Miri.
match rustc_driver::main() {
// Empty match proves this function will never return.
}
} else if crate_kind != "target" {
panic!("invalid `MIRI_BE_RUSTC` value: {crate_kind:?}")
};

// Earliest rustc setup.
rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ());
rustc_driver::init_rustc_env_logger(&early_dcx);

let target_crate = if crate_kind == "target" {
true
} else if crate_kind == "host" {
false
} else {
panic!("invalid `MIRI_BE_RUSTC` value: {crate_kind:?}")
};

let mut args = args;
// Don't insert `MIRI_DEFAULT_ARGS`, in particular, `--cfg=miri`, if we are building
// a "host" crate. That may cause procedural macros (and probably build scripts) to
// depend on Miri-only symbols, such as `miri_resolve_frame`:
// https://github.com/rust-lang/miri/issues/1760
if target_crate {
// Splice in the default arguments after the program name.
// Some options have different defaults in Miri than in plain rustc; apply those by making
// them the first arguments after the binary name (but later arguments can overwrite them).
args.splice(1..1, miri::MIRI_DEFAULT_ARGS.iter().map(ToString::to_string));
}
// Splice in the default arguments after the program name.
// Some options have different defaults in Miri than in plain rustc; apply those by making
// them the first arguments after the binary name (but later arguments can overwrite them).
args.splice(1..1, miri::MIRI_DEFAULT_ARGS.iter().map(ToString::to_string));

// We cannot use `rustc_driver::main` as we want it to use `args` as the CLI arguments.
run_compiler_and_exit(&args, &mut MiriBeRustCompilerCalls { target_crate })
run_compiler_and_exit(&args, &mut MiriDepCompilerCalls)
}

// Add an ICE bug report hook.
Expand Down
109 changes: 84 additions & 25 deletions src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ struct DisplayFmtPadding {
indent_middle: S,
/// Indentation for the last child.
indent_last: S,
/// Replaces `join_last` for a wildcard root.
wildcard_root: S,
}
/// How to show whether a location has been accessed
///
Expand Down Expand Up @@ -561,6 +563,11 @@ impl DisplayFmt {
})
.unwrap_or("")
}

/// Print extra text if the tag is exposed.
fn print_exposed(&self, exposed: bool) -> S {
if exposed { " (exposed)" } else { "" }
}
}

/// Track the indentation of the tree.
Expand Down Expand Up @@ -607,23 +614,21 @@ fn char_repeat(c: char, n: usize) -> String {
struct DisplayRepr {
tag: BorTag,
name: Option<String>,
exposed: bool,
rperm: Vec<Option<LocationState>>,
children: Vec<DisplayRepr>,
}

impl DisplayRepr {
fn from(tree: &Tree, show_unnamed: bool) -> Option<Self> {
fn from(tree: &Tree, root: UniIndex, show_unnamed: bool) -> Option<Self> {
let mut v = Vec::new();
extraction_aux(tree, tree.root, show_unnamed, &mut v);
extraction_aux(tree, root, show_unnamed, &mut v);
let Some(root) = v.pop() else {
if show_unnamed {
unreachable!(
"This allocation contains no tags, not even a root. This should not happen."
);
}
eprintln!(
"This allocation does not contain named tags. Use `miri_print_borrow_state(_, true)` to also print unnamed tags."
);
return None;
};
assert!(v.is_empty());
Expand All @@ -637,6 +642,7 @@ impl DisplayRepr {
) {
let node = tree.nodes.get(idx).unwrap();
let name = node.debug_info.name.clone();
let exposed = node.is_exposed;
let children_sorted = {
let mut children = node.children.iter().cloned().collect::<Vec<_>>();
children.sort_by_key(|idx| tree.nodes.get(*idx).unwrap().tag);
Expand All @@ -661,12 +667,13 @@ impl DisplayRepr {
for child_idx in children_sorted {
extraction_aux(tree, child_idx, show_unnamed, &mut children);
}
acc.push(DisplayRepr { tag: node.tag, name, rperm, children });
acc.push(DisplayRepr { tag: node.tag, name, rperm, children, exposed });
}
}
}
fn print(
&self,
main_root: &Option<DisplayRepr>,
wildcard_subtrees: &[DisplayRepr],
fmt: &DisplayFmt,
indenter: &mut DisplayIndent,
protected_tags: &FxHashMap<BorTag, ProtectorKind>,
Expand Down Expand Up @@ -703,15 +710,41 @@ impl DisplayRepr {
block.push(s);
}
// This is the actual work
print_aux(
self,
&range_padding,
fmt,
indenter,
protected_tags,
true, /* root _is_ the last child */
&mut block,
);
if let Some(root) = main_root {
print_aux(
root,
&range_padding,
fmt,
indenter,
protected_tags,
true, /* root _is_ the last child */
false, /* not a wildcard_root*/
&mut block,
);
}
for tree in wildcard_subtrees.iter() {
let mut gap_line = String::new();
gap_line.push_str(fmt.perm.open);
for (i, &pad) in range_padding.iter().enumerate() {
if i > 0 {
gap_line.push_str(fmt.perm.sep);
}
gap_line.push_str(&format!("{}{}", char_repeat(' ', pad), " "));
}
gap_line.push_str(fmt.perm.close);
block.push(gap_line);

print_aux(
tree,
&range_padding,
fmt,
indenter,
protected_tags,
true, /* root _is_ the last child */
true, /* wildcard_root*/
&mut block,
);
}
// Then it's just prettifying it with a border of dashes.
{
let wr = &fmt.wrapper;
Expand Down Expand Up @@ -741,6 +774,7 @@ impl DisplayRepr {
indent: &mut DisplayIndent,
protected_tags: &FxHashMap<BorTag, ProtectorKind>,
is_last_child: bool,
is_wildcard_root: bool,
acc: &mut Vec<String>,
) {
let mut line = String::new();
Expand All @@ -760,7 +794,9 @@ impl DisplayRepr {
indent.write(&mut line);
{
// padding
line.push_str(if is_last_child {
line.push_str(if is_wildcard_root {
fmt.padding.wildcard_root
} else if is_last_child {
fmt.padding.join_last
} else {
fmt.padding.join_middle
Expand All @@ -777,12 +813,22 @@ impl DisplayRepr {
line.push_str(&fmt.print_tag(tree.tag, &tree.name));
let protector = protected_tags.get(&tree.tag);
line.push_str(fmt.print_protector(protector));
line.push_str(fmt.print_exposed(tree.exposed));
// Push the line to the accumulator then recurse.
acc.push(line);
let nb_children = tree.children.len();
for (i, child) in tree.children.iter().enumerate() {
indent.increment(fmt, is_last_child);
print_aux(child, padding, fmt, indent, protected_tags, i + 1 == nb_children, acc);
print_aux(
child,
padding,
fmt,
indent,
protected_tags,
/* is_last_child */ i + 1 == nb_children,
/* is_wildcard_root */ false,
acc,
);
indent.decrement(fmt);
}
}
Expand All @@ -803,6 +849,7 @@ const DEFAULT_FORMATTER: DisplayFmt = DisplayFmt {
indent_last: " ",
join_haschild: "┬",
join_default: "─",
wildcard_root: "*",
},
accessed: DisplayFmtAccess { yes: " ", no: "?", meh: "-" },
};
Expand All @@ -816,15 +863,27 @@ impl<'tcx> Tree {
) -> InterpResult<'tcx> {
let mut indenter = DisplayIndent::new();
let ranges = self.locations.iter_all().map(|(range, _loc)| range).collect::<Vec<_>>();
if let Some(repr) = DisplayRepr::from(self, show_unnamed) {
repr.print(
&DEFAULT_FORMATTER,
&mut indenter,
protected_tags,
ranges,
/* print warning message about tags not shown */ !show_unnamed,
let main_tree = DisplayRepr::from(self, self.roots[0], show_unnamed);
let wildcard_subtrees = self.roots[1..]
.iter()
.filter_map(|root| DisplayRepr::from(self, *root, show_unnamed))
.collect::<Vec<_>>();

if main_tree.is_none() && wildcard_subtrees.is_empty() {
eprintln!(
"This allocation does not contain named tags. Use `miri_print_borrow_state(_, true)` to also print unnamed tags."
);
}

DisplayRepr::print(
&main_tree,
wildcard_subtrees.as_slice(),
&DEFAULT_FORMATTER,
&mut indenter,
protected_tags,
ranges,
/* print warning message about tags not shown */ !show_unnamed,
);
interp_ok(())
}
}
Loading
Loading