Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 14 additions & 7 deletions src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use rustc_target::spec::Os;
use crate::concurrency::GenmcCtx;
use crate::concurrency::thread::TlsAllocAction;
use crate::diagnostics::report_leaks;
use crate::helpers::is_no_core;
use crate::shims::{global_ctor, tls};
use crate::*;

Expand Down Expand Up @@ -289,14 +290,20 @@ pub fn create_ecx<'tcx>(
MiriMachine::new(config, layout_cx, genmc_ctx),
);

// Make sure we have MIR. We check MIR for some stable monomorphic function in libcore.
let sentinel =
helpers::try_resolve_path(tcx, &["core", "ascii", "escape_default"], Namespace::ValueNS);
if !matches!(sentinel, Some(s) if tcx.is_mir_available(s.def.def_id())) {
tcx.dcx().fatal(
"the current sysroot was built without `-Zalways-encode-mir`, or libcore seems missing.\n\
Note that directly invoking the `miri` binary is not supported; please use `cargo miri` instead."
// Make sure we have MIR. We check MIR for some stable monomorphic function in libcore, except
// if the current crate is #![no_core] it's fine to be missing the usual items from libcore.
if !is_no_core(tcx) {
let sentinel = helpers::try_resolve_path(
tcx,
&["core", "ascii", "escape_default"],
Namespace::ValueNS,
);
if !matches!(sentinel, Some(s) if tcx.is_mir_available(s.def.def_id())) {
tcx.dcx().fatal(
"the current sysroot was built without `-Zalways-encode-mir`, or libcore seems missing.\n\
Note that directly invoking the `miri` binary is not supported; please use `cargo miri` instead."
);
}
}

// Compute argc and argv from `config.args`.
Expand Down
5 changes: 5 additions & 0 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,11 @@ pub(crate) fn windows_check_buffer_size((success, len): (bool, u64)) -> u32 {
}
}

/// Check whether the local crate has the `#![no_core]` attribute.
pub fn is_no_core(tcx: TyCtxt<'_>) -> bool {
rustc_hir::find_attr!(tcx, crate, NoCore(..))
}

/// We don't support 16-bit systems, so let's have ergonomic conversion from `u32` to `usize`.
pub trait ToUsize {
fn to_usize(self) -> usize;
Expand Down
4 changes: 3 additions & 1 deletion src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use crate::concurrency::sync::SyncObj;
use crate::concurrency::{
AllocDataRaceHandler, GenmcCtx, GenmcEvalContextExt as _, GlobalDataRaceHandler, weak_memory,
};
use crate::helpers::is_no_core;
use crate::*;

/// First real-time signal.
Expand Down Expand Up @@ -731,7 +732,8 @@ impl<'tcx> MiriMachine<'tcx> {
);
let threads = ThreadManager::new(config);
let mut thread_cpu_affinity = FxHashMap::default();
if matches!(&tcx.sess.target.os, Os::Linux | Os::FreeBsd | Os::Android) {
if matches!(&tcx.sess.target.os, Os::Linux | Os::FreeBsd | Os::Android) && !is_no_core(tcx)
{
thread_cpu_affinity
.insert(threads.active_thread(), CpuAffinityMask::new(&layout_cx, config.num_cpus));
Copy link
Copy Markdown
Member

@RalfJung RalfJung Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that if the program later calls sched_getaffinity it may get nonsensical errors about threads not existing.

Might be better to turn this into an Option<FxHashMap> so that we can leave it uninitialized and give proper errors in the shims that need it?

View changes since the review

}
Expand Down
22 changes: 22 additions & 0 deletions tests/pass/no_core.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! Test that Miri is able to run no_core programs.
//! This ensures that we don't depend on any paths from core when no_core is set.

#![no_std]
#![no_core]
#![no_main]
#![feature(rustc_attrs, no_core, lang_items, intrinsics)]
#![allow(internal_features)]

#[lang = "pointee_sized"]
pub trait PointeeSized {}

#[lang = "meta_sized"]
pub trait MetaSized: PointeeSized {}

#[lang = "sized"]
pub trait Sized: MetaSized {}

#[no_mangle]
fn miri_start(_argc: isize, _argv: *const *const u8) -> isize {
0
}