Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-06-09 05:04:11 +00:00
commit 4835a9da54
212 changed files with 2091 additions and 2941 deletions

View file

@ -50,26 +50,39 @@ use crate::utils::channel;
use crate::utils::helpers::exe;
use crate::{Command, GitInfo, OnceLock, TargetSelection, check_ci_llvm, helpers, output, t};
/// Each path in this list is considered "allowed" in the `download-rustc="if-unchanged"` logic.
/// Each path from this function is considered "allowed" in the `download-rustc="if-unchanged"` logic.
/// This means they can be modified and changes to these paths should never trigger a compiler build
/// when "if-unchanged" is set.
///
/// NOTE: Paths must have the ":!" prefix to tell git to ignore changes in those paths during
/// the diff check.
///
/// WARNING: Be cautious when adding paths to this list. If a path that influences the compiler build
/// is added here, it will cause bootstrap to skip necessary rebuilds, which may lead to risky results.
/// For example, "src/bootstrap" should never be included in this list as it plays a crucial role in the
/// final output/compiler, which can be significantly affected by changes made to the bootstrap sources.
#[rustfmt::skip] // We don't want rustfmt to oneline this list
pub const RUSTC_IF_UNCHANGED_ALLOWED_PATHS: &[&str] = &[
":!library",
":!src/tools",
":!src/librustdoc",
":!src/rustdoc-json-types",
":!tests",
":!triagebot.toml",
];
pub fn rustc_if_unchanged_allowed_paths() -> Vec<&'static str> {
// NOTE: Paths must have the ":!" prefix to tell git to ignore changes in those paths during
// the diff check.
//
// WARNING: Be cautious when adding paths to this list. If a path that influences the compiler build
// is added here, it will cause bootstrap to skip necessary rebuilds, which may lead to risky results.
// For example, "src/bootstrap" should never be included in this list as it plays a crucial role in the
// final output/compiler, which can be significantly affected by changes made to the bootstrap sources.
let mut paths = vec![
":!library",
":!src/tools",
":!src/librustdoc",
":!src/rustdoc-json-types",
":!tests",
":!triagebot.toml",
];
if !CiEnv::is_ci() {
// When a dependency is added/updated/removed in the library tree (or in some tools),
// `Cargo.lock` will be updated by `cargo`. This update will incorrectly invalidate the
// `download-rustc=if-unchanged` cache.
//
// To prevent this, add `Cargo.lock` to the list of allowed paths when not running on CI.
// This is generally safe because changes to dependencies typically involve modifying
// `Cargo.toml`, which would already invalidate the CI-rustc cache on non-allowed paths.
paths.push(":!Cargo.lock");
}
paths
}
/// Global configuration for the entire build and/or bootstrap.
///
@ -1503,7 +1516,7 @@ impl Config {
let commit = if self.rust_info.is_managed_git_subrepository() {
// Look for a version to compare to based on the current commit.
// Only commits merged by bors will have CI artifacts.
let freshness = self.check_path_modifications(RUSTC_IF_UNCHANGED_ALLOWED_PATHS);
let freshness = self.check_path_modifications(&rustc_if_unchanged_allowed_paths());
self.verbose(|| {
eprintln!("rustc freshness: {freshness:?}");
});

View file

@ -11,7 +11,7 @@ use serde::Deserialize;
use super::flags::Flags;
use super::toml::change_id::ChangeIdWrapper;
use super::{Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS};
use super::{Config, rustc_if_unchanged_allowed_paths};
use crate::ChangeId;
use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
use crate::core::build_steps::llvm;
@ -459,7 +459,7 @@ fn jobs_precedence() {
#[test]
fn check_rustc_if_unchanged_paths() {
let config = parse("");
let normalised_allowed_paths: Vec<_> = RUSTC_IF_UNCHANGED_ALLOWED_PATHS
let normalised_allowed_paths: Vec<_> = rustc_if_unchanged_allowed_paths()
.iter()
.map(|t| {
t.strip_prefix(":!").expect(&format!("{t} doesn't have ':!' prefix, but it should."))

View file

@ -26,108 +26,131 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
) -> InterpResult<'tcx, EmulateItemResult> {
let this = self.eval_context_mut();
let intrinsic_structure: Vec<_> = intrinsic_name.split('_').collect();
let get_ord_at = |i: usize| {
let ordering = generic_args.const_at(i).to_value();
ordering.valtree.unwrap_branch()[0].unwrap_leaf().to_atomic_ordering()
};
fn read_ord(ord: &str) -> AtomicReadOrd {
fn read_ord(ord: AtomicOrdering) -> AtomicReadOrd {
match ord {
"seqcst" => AtomicReadOrd::SeqCst,
"acquire" => AtomicReadOrd::Acquire,
"relaxed" => AtomicReadOrd::Relaxed,
_ => panic!("invalid read ordering `{ord}`"),
}
}
fn read_ord_const_generic(o: AtomicOrdering) -> AtomicReadOrd {
match o {
AtomicOrdering::SeqCst => AtomicReadOrd::SeqCst,
AtomicOrdering::Acquire => AtomicReadOrd::Acquire,
AtomicOrdering::Relaxed => AtomicReadOrd::Relaxed,
_ => panic!("invalid read ordering `{o:?}`"),
_ => panic!("invalid read ordering `{ord:?}`"),
}
}
fn write_ord(ord: &str) -> AtomicWriteOrd {
fn write_ord(ord: AtomicOrdering) -> AtomicWriteOrd {
match ord {
"seqcst" => AtomicWriteOrd::SeqCst,
"release" => AtomicWriteOrd::Release,
"relaxed" => AtomicWriteOrd::Relaxed,
_ => panic!("invalid write ordering `{ord}`"),
AtomicOrdering::SeqCst => AtomicWriteOrd::SeqCst,
AtomicOrdering::Release => AtomicWriteOrd::Release,
AtomicOrdering::Relaxed => AtomicWriteOrd::Relaxed,
_ => panic!("invalid write ordering `{ord:?}`"),
}
}
fn rw_ord(ord: &str) -> AtomicRwOrd {
fn rw_ord(ord: AtomicOrdering) -> AtomicRwOrd {
match ord {
"seqcst" => AtomicRwOrd::SeqCst,
"acqrel" => AtomicRwOrd::AcqRel,
"acquire" => AtomicRwOrd::Acquire,
"release" => AtomicRwOrd::Release,
"relaxed" => AtomicRwOrd::Relaxed,
_ => panic!("invalid read-write ordering `{ord}`"),
AtomicOrdering::SeqCst => AtomicRwOrd::SeqCst,
AtomicOrdering::AcqRel => AtomicRwOrd::AcqRel,
AtomicOrdering::Acquire => AtomicRwOrd::Acquire,
AtomicOrdering::Release => AtomicRwOrd::Release,
AtomicOrdering::Relaxed => AtomicRwOrd::Relaxed,
}
}
fn fence_ord(ord: &str) -> AtomicFenceOrd {
fn fence_ord(ord: AtomicOrdering) -> AtomicFenceOrd {
match ord {
"seqcst" => AtomicFenceOrd::SeqCst,
"acqrel" => AtomicFenceOrd::AcqRel,
"acquire" => AtomicFenceOrd::Acquire,
"release" => AtomicFenceOrd::Release,
_ => panic!("invalid fence ordering `{ord}`"),
AtomicOrdering::SeqCst => AtomicFenceOrd::SeqCst,
AtomicOrdering::AcqRel => AtomicFenceOrd::AcqRel,
AtomicOrdering::Acquire => AtomicFenceOrd::Acquire,
AtomicOrdering::Release => AtomicFenceOrd::Release,
_ => panic!("invalid fence ordering `{ord:?}`"),
}
}
match &*intrinsic_structure {
// New-style intrinsics that use const generics
["load"] => {
let ordering = generic_args.const_at(1).to_value();
let ordering =
ordering.valtree.unwrap_branch()[0].unwrap_leaf().to_atomic_ordering();
this.atomic_load(args, dest, read_ord_const_generic(ordering))?;
match intrinsic_name {
"load" => {
let ord = get_ord_at(1);
this.atomic_load(args, dest, read_ord(ord))?;
}
// Old-style intrinsics that have the ordering in the intrinsic name
["store", ord] => this.atomic_store(args, write_ord(ord))?,
"store" => {
let ord = get_ord_at(1);
this.atomic_store(args, write_ord(ord))?
}
["fence", ord] => this.atomic_fence_intrinsic(args, fence_ord(ord))?,
["singlethreadfence", ord] => this.compiler_fence_intrinsic(args, fence_ord(ord))?,
"fence" => {
let ord = get_ord_at(0);
this.atomic_fence_intrinsic(args, fence_ord(ord))?
}
"singlethreadfence" => {
let ord = get_ord_at(0);
this.compiler_fence_intrinsic(args, fence_ord(ord))?;
}
["xchg", ord] => this.atomic_exchange(args, dest, rw_ord(ord))?,
["cxchg", ord1, ord2] =>
this.atomic_compare_exchange(args, dest, rw_ord(ord1), read_ord(ord2))?,
["cxchgweak", ord1, ord2] =>
this.atomic_compare_exchange_weak(args, dest, rw_ord(ord1), read_ord(ord2))?,
"xchg" => {
let ord = get_ord_at(1);
this.atomic_exchange(args, dest, rw_ord(ord))?;
}
"cxchg" => {
let ord1 = get_ord_at(1);
let ord2 = get_ord_at(2);
this.atomic_compare_exchange(args, dest, rw_ord(ord1), read_ord(ord2))?;
}
"cxchgweak" => {
let ord1 = get_ord_at(1);
let ord2 = get_ord_at(2);
this.atomic_compare_exchange_weak(args, dest, rw_ord(ord1), read_ord(ord2))?;
}
["or", ord] =>
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord))?,
["xor", ord] =>
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord))?,
["and", ord] =>
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord))?,
["nand", ord] =>
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord))?,
["xadd", ord] =>
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord))?,
["xsub", ord] =>
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord))?,
["min", ord] => {
"or" => {
let ord = get_ord_at(1);
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord))?;
}
"xor" => {
let ord = get_ord_at(1);
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord))?;
}
"and" => {
let ord = get_ord_at(1);
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord))?;
}
"nand" => {
let ord = get_ord_at(1);
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord))?;
}
"xadd" => {
let ord = get_ord_at(1);
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord))?;
}
"xsub" => {
let ord = get_ord_at(1);
this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord))?;
}
"min" => {
let ord = get_ord_at(1);
// Later we will use the type to indicate signed vs unsigned,
// so make sure it matches the intrinsic name.
assert!(matches!(args[1].layout.ty.kind(), ty::Int(_)));
this.atomic_rmw_op(args, dest, AtomicOp::Min, rw_ord(ord))?;
}
["umin", ord] => {
"umin" => {
let ord = get_ord_at(1);
// Later we will use the type to indicate signed vs unsigned,
// so make sure it matches the intrinsic name.
assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_)));
this.atomic_rmw_op(args, dest, AtomicOp::Min, rw_ord(ord))?;
}
["max", ord] => {
"max" => {
let ord = get_ord_at(1);
// Later we will use the type to indicate signed vs unsigned,
// so make sure it matches the intrinsic name.
assert!(matches!(args[1].layout.ty.kind(), ty::Int(_)));
this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord))?;
}
["umax", ord] => {
"umax" => {
let ord = get_ord_at(1);
// Later we will use the type to indicate signed vs unsigned,
// so make sure it matches the intrinsic name.
assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_)));

View file

@ -2,7 +2,7 @@ error[E0080]: accessing memory based on pointer with alignment ALIGN, but alignm
--> tests/fail/const-ub-checks.rs:LL:CC
|
LL | ptr.read();
| ^^^^^^^^^^ evaluation of constant value failed here
| ^^^^^^^^^^ evaluation of `UNALIGNED_READ` failed here
note: erroneous constant encountered
--> tests/fail/const-ub-checks.rs:LL:CC

View file

@ -2,7 +2,7 @@ error[E0080]: attempt to compute `5_u32 - 6_u32`, which would overflow
--> tests/fail/erroneous_const2.rs:LL:CC
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ^^^^^ evaluation of constant value failed here
| ^^^^^ evaluation of `FOO` failed here
note: erroneous constant encountered
--> tests/fail/erroneous_const2.rs:LL:CC