Auto merge of #122331 - jhpratt:rollup-cbl8xsy, r=jhpratt

Rollup of 9 pull requests

Successful merges:

 - #121148 (Add slice::try_range)
 - #121633 (Win10: Use `GetSystemTimePreciseAsFileTime` directly)
 - #121840 (Expose the Freeze trait again (unstably) and forbid implementing it manually)
 - #121907 (skip sanity check for non-host targets in `check` builds)
 - #122002 (std::threads: revisit stack address calculation on netbsd.)
 - #122108 (Add `target.*.runner` configuration for targets)
 - #122298 (RawVec::into_box: avoid unnecessary intermediate reference)
 - #122315 (Allow multiple `impl Into<{D,Subd}iagMessage>` parameters in a function.)
 - #122326 (Optimize `process_heap_alloc`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-03-11 10:22:10 +00:00
commit e919669d42
40 changed files with 276 additions and 80 deletions

View File

@ -8,6 +8,7 @@
rustc_attrs,
transparent_unions,
auto_traits,
freeze_impls,
thread_local
)]
#![no_core]

View File

@ -1,6 +1,6 @@
#![feature(
no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
decl_macro, rustc_attrs, transparent_unions, auto_traits,
decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls,
thread_local
)]
#![no_core]

View File

@ -471,6 +471,8 @@ declare_features! (
(unstable, fn_align, "1.53.0", Some(82232)),
/// Support delegating implementation of functions to other already implemented functions.
(incomplete, fn_delegation, "1.76.0", Some(118212)),
/// Allows impls for the Freeze trait.
(internal, freeze_impls, "CURRENT_RUSTC_VERSION", Some(121675)),
/// Allows defining gen blocks and `gen fn`.
(unstable, gen_blocks, "1.75.0", Some(117078)),
/// Infer generic args for both consts and types.

View File

@ -10,6 +10,7 @@ use rustc_errors::{codes::*, struct_span_code_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_session::parse::feature_err;
use rustc_span::{sym, ErrorGuaranteed};
use rustc_trait_selection::traits;
@ -49,6 +50,19 @@ fn enforce_trait_manually_implementable(
) -> Result<(), ErrorGuaranteed> {
let impl_header_span = tcx.def_span(impl_def_id);
if tcx.lang_items().freeze_trait() == Some(trait_def_id) {
if !tcx.features().freeze_impls {
feature_err(
&tcx.sess,
sym::freeze_impls,
impl_header_span,
"explicit impls for the `Freeze` trait are not permitted",
)
.with_span_label(impl_header_span, format!("impl of `Freeze` not allowed"))
.emit();
}
}
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
if trait_def.deny_explicit_impl {
let trait_name = tcx.item_name(trait_def_id);

View File

@ -409,9 +409,8 @@ impl LateLintPass<'_> for Diagnostics {
}
};
// Does the callee have a `impl Into<{D,Subd}iagMessage>` parameter? (There should be at
// most one.)
let mut impl_into_diagnostic_message_param = None;
// Does the callee have one or more `impl Into<{D,Subd}iagMessage>` parameters?
let mut impl_into_diagnostic_message_params = vec![];
let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates;
for (i, &param_ty) in fn_sig.inputs().iter().enumerate() {
@ -425,20 +424,14 @@ impl LateLintPass<'_> for Diagnostics {
&& let ty1 = trait_ref.args.type_at(1)
&& is_diag_message(ty1)
{
if impl_into_diagnostic_message_param.is_some() {
cx.tcx.dcx().span_bug(
span,
"can't handle multiple `impl Into<{D,Sub}iagMessage>` params",
);
}
impl_into_diagnostic_message_param = Some((i, p.name));
impl_into_diagnostic_message_params.push((i, p.name));
}
}
}
}
// Is the callee interesting?
if !has_attr && impl_into_diagnostic_message_param.is_none() {
if !has_attr && impl_into_diagnostic_message_params.is_empty() {
return;
}
@ -481,7 +474,7 @@ impl LateLintPass<'_> for Diagnostics {
// Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg
// with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an
// `UNTRANSLATABLE_DIAGNOSTIC` lint.
if let Some((param_i, param_i_p_name)) = impl_into_diagnostic_message_param {
for (param_i, param_i_p_name) in impl_into_diagnostic_message_params {
// Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`?
let arg_ty = call_tys[param_i];
let is_translatable = is_diag_message(arg_ty)

View File

@ -864,6 +864,7 @@ symbols! {
format_placeholder,
format_unsafe_arg,
freeze,
freeze_impls,
freg,
frem_algebraic,
frem_fast,

View File

@ -842,6 +842,17 @@
# See that option for more info.
#codegen-backends = rust.codegen-backends (array)
# This is a "runner" to pass to `compiletest` when executing tests. Tests will
# execute this tool where the binary-to-test is passed as an argument. Can
# be useful for situations such as when WebAssembly is being tested and a
# runtime needs to be configured. This value is similar to
# Cargo's `CARGO_$target_RUNNER` configuration.
#
# This configuration is a space-separated list of arguments so `foo bar` would
# execute the program `foo` with the first argument as `bar` and the second
# argument as the test binary.
#runner = <none> (string)
# =============================================================================
# Distribution options
#

View File

@ -5,7 +5,6 @@ use core::cmp;
use core::hint;
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::ptr::{self, NonNull, Unique};
use core::slice;
#[cfg(not(no_global_oom_handling))]
use crate::alloc::handle_alloc_error;
@ -192,7 +191,7 @@ impl<T, A: Allocator> RawVec<T, A> {
let me = ManuallyDrop::new(self);
unsafe {
let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
let slice = ptr::slice_from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
Box::from_raw_in(slice, ptr::read(&me.alloc))
}
}

View File

@ -33,8 +33,6 @@ use crate::vec::Vec;
#[cfg(test)]
mod tests;
#[unstable(feature = "slice_range", issue = "76393")]
pub use core::slice::range;
#[unstable(feature = "array_chunks", issue = "74985")]
pub use core::slice::ArrayChunks;
#[unstable(feature = "array_chunks", issue = "74985")]
@ -51,6 +49,8 @@ pub use core::slice::{from_mut, from_ref};
pub use core::slice::{from_mut_ptr_range, from_ptr_range};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
#[unstable(feature = "slice_range", issue = "76393")]
pub use core::slice::{range, try_range};
#[stable(feature = "slice_group_by", since = "1.77.0")]
pub use core::slice::{ChunkBy, ChunkByMut};
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -204,6 +204,7 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(diagnostic_namespace))]
#![cfg_attr(bootstrap, feature(platform_intrinsics))]
#![cfg_attr(not(bootstrap), feature(freeze_impls))]
#![feature(abi_unadjusted)]
#![feature(adt_const_params)]
#![feature(allow_internal_unsafe)]

View File

@ -810,15 +810,21 @@ pub trait DiscriminantKind {
type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
}
/// Compiler-internal trait used to determine whether a type contains
/// Used to determine whether a type contains
/// any `UnsafeCell` internally, but not through an indirection.
/// This affects, for example, whether a `static` of that type is
/// placed in read-only static memory or writable static memory.
/// This can be used to declare that a constant with a generic type
/// will not contain interior mutability, and subsequently allow
/// placing the constant behind references.
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
#[unstable(feature = "freeze", issue = "121675")]
pub unsafe auto trait Freeze {}
#[unstable(feature = "freeze", issue = "121675")]
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
marker_impls! {
#[unstable(feature = "freeze", issue = "121675")]
unsafe Freeze for
{T: ?Sized} PhantomData<T>,
{T: ?Sized} *const T,

View File

@ -704,8 +704,7 @@ where
{
let len = bounds.end;
let start: ops::Bound<&usize> = range.start_bound();
let start = match start {
let start = match range.start_bound() {
ops::Bound::Included(&start) => start,
ops::Bound::Excluded(start) => {
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
@ -713,8 +712,7 @@ where
ops::Bound::Unbounded => 0,
};
let end: ops::Bound<&usize> = range.end_bound();
let end = match end {
let end = match range.end_bound() {
ops::Bound::Included(end) => {
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
}
@ -732,6 +730,59 @@ where
ops::Range { start, end }
}
/// Performs bounds-checking of a range without panicking.
///
/// This is a version of [`range`] that returns [`None`] instead of panicking.
///
/// # Examples
///
/// ```
/// #![feature(slice_range)]
///
/// use std::slice;
///
/// let v = [10, 40, 30];
/// assert_eq!(Some(1..2), slice::try_range(1..2, ..v.len()));
/// assert_eq!(Some(0..2), slice::try_range(..2, ..v.len()));
/// assert_eq!(Some(1..3), slice::try_range(1.., ..v.len()));
/// ```
///
/// Returns [`None`] when [`Index::index`] would panic:
///
/// ```
/// #![feature(slice_range)]
///
/// use std::slice;
///
/// assert_eq!(None, slice::try_range(2..1, ..3));
/// assert_eq!(None, slice::try_range(1..4, ..3));
/// assert_eq!(None, slice::try_range(1..=usize::MAX, ..3));
/// ```
///
/// [`Index::index`]: ops::Index::index
#[unstable(feature = "slice_range", issue = "76393")]
#[must_use]
pub fn try_range<R>(range: R, bounds: ops::RangeTo<usize>) -> Option<ops::Range<usize>>
where
R: ops::RangeBounds<usize>,
{
let len = bounds.end;
let start = match range.start_bound() {
ops::Bound::Included(&start) => start,
ops::Bound::Excluded(start) => start.checked_add(1)?,
ops::Bound::Unbounded => 0,
};
let end = match range.end_bound() {
ops::Bound::Included(end) => end.checked_add(1)?,
ops::Bound::Excluded(&end) => end,
ops::Bound::Unbounded => len,
};
if start > end || end > len { None } else { Some(ops::Range { start, end }) }
}
/// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
pub(crate) fn into_range_unchecked(
len: usize,

View File

@ -91,7 +91,7 @@ pub use sort::heapsort;
pub use index::SliceIndex;
#[unstable(feature = "slice_range", issue = "76393")]
pub use index::range;
pub use index::{range, try_range};
#[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
pub use ascii::EscapeAscii;

View File

@ -806,9 +806,9 @@ pub mod guard {
#[cfg(any(
target_os = "android",
target_os = "freebsd",
target_os = "netbsd",
target_os = "hurd",
target_os = "linux",
target_os = "netbsd",
target_os = "l4re"
))]
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
@ -911,9 +911,10 @@ pub mod guard {
}
}) * page_size;
Some(guard)
} else if cfg!(target_os = "openbsd") {
} else if cfg!(any(target_os = "openbsd", target_os = "netbsd")) {
// OpenBSD stack already includes a guard page, and stack is
// immutable.
// NetBSD stack includes the guard page.
//
// We'll just note where we expect rlimit to start
// faulting, so our handler can report "stack overflow", and

View File

@ -6,6 +6,7 @@ use crate::ptr;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys::c;
use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};
use core::mem::MaybeUninit;
#[cfg(test)]
mod tests;
@ -94,29 +95,30 @@ static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
// a non-null handle returned by `GetProcessHeap`.
#[inline]
fn init_or_get_process_heap() -> c::HANDLE {
let heap = HEAP.load(Ordering::Relaxed);
if core::intrinsics::unlikely(heap.is_null()) {
// `HEAP` has not yet been successfully initialized
let heap = unsafe { GetProcessHeap() };
if !heap.is_null() {
// SAFETY: No locking is needed because within the same process,
// successful calls to `GetProcessHeap` will always return the same value, even on different threads.
HEAP.store(heap, Ordering::Release);
// `HEAP` has not yet been successfully initialized
let heap = unsafe { GetProcessHeap() };
if !heap.is_null() {
// SAFETY: No locking is needed because within the same process,
// successful calls to `GetProcessHeap` will always return the same value, even on different threads.
HEAP.store(heap, Ordering::Release);
// SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
heap
} else {
// Could not get the current process heap.
ptr::null_mut()
}
} else {
// SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
heap
} else {
// Could not get the current process heap.
ptr::null_mut()
}
}
/// This is outlined from `process_heap_alloc` so that `process_heap_alloc`
/// does not need any stack allocations.
#[inline(never)]
fn process_heap_alloc(flags: c::DWORD, dwBytes: c::SIZE_T) -> c::LPVOID {
#[cold]
extern "C" fn process_heap_init_and_alloc(
_heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`
flags: c::DWORD,
dwBytes: c::SIZE_T,
) -> c::LPVOID {
let heap = init_or_get_process_heap();
if core::intrinsics::unlikely(heap.is_null()) {
return ptr::null_mut();
@ -125,6 +127,21 @@ fn process_heap_alloc(flags: c::DWORD, dwBytes: c::SIZE_T) -> c::LPVOID {
unsafe { HeapAlloc(heap, flags, dwBytes) }
}
#[inline(never)]
fn process_heap_alloc(
_heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`,
flags: c::DWORD,
dwBytes: c::SIZE_T,
) -> c::LPVOID {
let heap = HEAP.load(Ordering::Relaxed);
if core::intrinsics::likely(!heap.is_null()) {
// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
unsafe { HeapAlloc(heap, flags, dwBytes) }
} else {
process_heap_init_and_alloc(MaybeUninit::uninit(), flags, dwBytes)
}
}
// Get a non-null handle to the default heap of the current process.
// SAFETY: `HEAP` must have been successfully initialized.
#[inline]
@ -148,12 +165,12 @@ unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
if layout.align() <= MIN_ALIGN {
// The returned pointer points to the start of an allocated block.
process_heap_alloc(flags, layout.size()) as *mut u8
process_heap_alloc(MaybeUninit::uninit(), flags, layout.size()) as *mut u8
} else {
// Allocate extra padding in order to be able to satisfy the alignment.
let total = layout.align() + layout.size();
let ptr = process_heap_alloc(flags, total) as *mut u8;
let ptr = process_heap_alloc(MaybeUninit::uninit(), flags, total) as *mut u8;
if ptr.is_null() {
// Allocation has failed.
return ptr::null_mut();

View File

@ -344,6 +344,7 @@ compat_fn_with_fallback! {
// >= Win8 / Server 2012
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
#[cfg(target_vendor = "win7")]
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> () {
GetSystemTimeAsFileTime(lpsystemtimeasfiletime)
}

View File

@ -2476,6 +2476,7 @@ Windows.Win32.System.Pipes.PIPE_WAIT
Windows.Win32.System.SystemInformation.GetSystemDirectoryW
Windows.Win32.System.SystemInformation.GetSystemInfo
Windows.Win32.System.SystemInformation.GetSystemTimeAsFileTime
Windows.Win32.System.SystemInformation.GetSystemTimePreciseAsFileTime
Windows.Win32.System.SystemInformation.GetWindowsDirectoryW
Windows.Win32.System.SystemInformation.PROCESSOR_ARCHITECTURE
Windows.Win32.System.SystemInformation.SYSTEM_INFO

View File

@ -345,6 +345,10 @@ extern "system" {
pub fn GetSystemTimeAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> ();
}
#[link(name = "kernel32")]
extern "system" {
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> ();
}
#[link(name = "kernel32")]
extern "system" {
pub fn GetTempPathW(nbufferlength: u32, lpbuffer: PWSTR) -> u32;
}

View File

@ -1971,6 +1971,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
if builder.remote_tested(target) {
cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
} else if let Some(tool) = builder.runner(target) {
cmd.arg("--runner").arg(tool);
}
if suite != "mir-opt" {
@ -2523,6 +2525,8 @@ fn prepare_cargo_test(
format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
);
} else if let Some(tool) = builder.runner(target) {
cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
}
cargo

View File

@ -581,6 +581,7 @@ pub struct Target {
pub musl_libdir: Option<PathBuf>,
pub wasi_root: Option<PathBuf>,
pub qemu_rootfs: Option<PathBuf>,
pub runner: Option<String>,
pub no_std: bool,
pub codegen_backends: Option<Vec<String>>,
}
@ -1144,6 +1145,7 @@ define_config! {
qemu_rootfs: Option<String> = "qemu-rootfs",
no_std: Option<bool> = "no-std",
codegen_backends: Option<Vec<String>> = "codegen-backends",
runner: Option<String> = "runner",
}
}
@ -1864,6 +1866,7 @@ impl Config {
target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
target.wasi_root = cfg.wasi_root.map(PathBuf::from);
target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
target.runner = cfg.runner;
target.sanitizers = cfg.sanitizers;
target.profiler = cfg.profiler;
target.rpath = cfg.rpath;

View File

@ -15,6 +15,7 @@ use std::fs;
use std::path::PathBuf;
use std::process::Command;
use crate::builder::Kind;
use crate::core::config::Target;
use crate::utils::helpers::output;
use crate::Build;
@ -64,6 +65,8 @@ pub fn check(build: &mut Build) {
let mut skip_target_sanity =
env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some_and(|s| s == "1" || s == "true");
skip_target_sanity |= build.config.cmd.kind() == Kind::Check;
// Skip target sanity checks when we are doing anything with mir-opt tests or Miri
let skipped_paths = [OsStr::new("mir-opt"), OsStr::new("miri")];
skip_target_sanity |= build.config.paths.iter().any(|path| {
@ -169,11 +172,8 @@ than building it.
continue;
}
// Some environments don't want or need these tools, such as when testing Miri.
// FIXME: it would be better to refactor this code to split necessary setup from pure sanity
// checks, and have a regular flag for skipping the latter. Also see
// <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
if skip_target_sanity {
// skip check for cross-targets
if skip_target_sanity && target != &build.build {
continue;
}
@ -215,11 +215,8 @@ than building it.
panic!("All the *-none-* and nvptx* targets are no-std targets")
}
// Some environments don't want or need these tools, such as when testing Miri.
// FIXME: it would be better to refactor this code to split necessary setup from pure sanity
// checks, and have a regular flag for skipping the latter. Also see
// <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
if skip_target_sanity {
// skip check for cross-targets
if skip_target_sanity && target != &build.build {
continue;
}

View File

@ -1354,6 +1354,17 @@ impl Build {
|| env::var_os("TEST_DEVICE_ADDR").is_some()
}
/// Returns an optional "runner" to pass to `compiletest` when executing
/// test binaries.
///
/// An example of this would be a WebAssembly runtime when testing the wasm
/// targets.
fn runner(&self, target: TargetSelection) -> Option<String> {
let target = self.config.target_config.get(&target)?;
let runner = target.runner.as_ref()?;
Some(runner.to_owned())
}
/// Returns the root of the "rootfs" image that this target will be using,
/// if one was configured.
///

View File

@ -141,4 +141,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Info,
summary: "A new `boostrap-cache-path` option has been introduced which can be utilized to modify the cache path for bootstrap.",
},
ChangeInfo {
change_id: 122108,
severity: ChangeSeverity::Info,
summary: "a new `target.*.runner` option is available to specify a wrapper executable required to run tests for a target",
},
];

View File

@ -266,8 +266,10 @@ pub struct Config {
pub logfile: Option<PathBuf>,
/// A command line to prefix program execution with,
/// for running under valgrind
pub runtool: Option<String>,
/// for running under valgrind for example.
///
/// Similar to `CARGO_*_RUNNER` configuration.
pub runner: Option<String>,
/// Flags to pass to the compiler when building for the host
pub host_rustcflags: Vec<String>,

View File

@ -86,7 +86,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
.optflag("", "exact", "filters match exactly")
.optopt(
"",
"runtool",
"runner",
"supervisor program to run tests under \
(eg. emulator, valgrind)",
"PROGRAM",
@ -256,7 +256,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
_ => panic!("unknown `--run` option `{}` given", mode),
}),
logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
runtool: matches.opt_str("runtool"),
runner: matches.opt_str("runner"),
host_rustcflags: matches.opt_strs("host-rustcflags"),
target_rustcflags: matches.opt_strs("target-rustcflags"),
optimize_tests: matches.opt_present("optimize-tests"),
@ -341,7 +341,7 @@ pub fn log_config(config: &Config) {
c,
format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
);
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
logv(c, format!("runner: {}", opt_str(&config.runner)));
logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
logv(c, format!("target: {}", config.target));

View File

@ -461,7 +461,7 @@ impl<'test> TestCx<'test> {
}
let mut new_config = self.config.clone();
new_config.runtool = new_config.valgrind_path.clone();
new_config.runner = new_config.valgrind_path.clone();
let new_cx = TestCx { config: &new_config, ..*self };
proc_res = new_cx.exec_compiled_test();
@ -2647,7 +2647,7 @@ impl<'test> TestCx<'test> {
fn make_run_args(&self) -> ProcArgs {
// If we've got another tool to run under (valgrind),
// then split apart its command
let mut args = self.split_maybe_args(&self.config.runtool);
let mut args = self.split_maybe_args(&self.config.runner);
// If this is emscripten, then run tests under nodejs
if self.config.target.contains("emscripten") {

View File

@ -110,12 +110,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
#[allow(non_snake_case, clippy::arithmetic_side_effects)]
fn GetSystemTimeAsFileTime(
&mut self,
shim_name: &str,
LPFILETIME_op: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
this.assert_target_os("windows", "GetSystemTimeAsFileTime");
this.check_no_isolation("`GetSystemTimeAsFileTime`")?;
this.assert_target_os("windows", shim_name);
this.check_no_isolation(shim_name)?;
let filetime = this.deref_pointer_as(LPFILETIME_op, this.windows_ty_layout("FILETIME"))?;

View File

@ -257,11 +257,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
// Time related shims
"GetSystemTimeAsFileTime" => {
"GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => {
#[allow(non_snake_case)]
let [LPFILETIME] =
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
this.GetSystemTimeAsFileTime(LPFILETIME)?;
this.GetSystemTimeAsFileTime(link_name.as_str(), LPFILETIME)?;
}
"QueryPerformanceCounter" => {
#[allow(non_snake_case)]

View File

@ -92,6 +92,8 @@ unsafe impl Allocator for MyAllocator {
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
// Make sure accesses via `self` don't disturb anything.
let _val = self.bins[0].top.get();
// Since manually finding the corresponding bin of `ptr` is very expensive,
// doing pointer arithmetics is preferred.
// But this means we access `top` via `ptr` rather than `self`!
@ -101,22 +103,30 @@ unsafe impl Allocator for MyAllocator {
if self.thread_id == thread_id {
unsafe { (*their_bin).push(ptr) };
} else {
todo!("Deallocating from another thread")
todo!("Deallocating from another thread");
}
// Make sure we can also still access this via `self` after the rest is done.
let _val = self.bins[0].top.get();
}
}
// Make sure to involve `Box` in allocating these,
// as that's where `noalias` may come from.
fn v<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
fn v1<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
(Box::new_in([t], a) as Box<[T], A>).into_vec()
}
fn v2<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
let v = v1(t, a);
// There was a bug in `into_boxed_slice` that caused aliasing issues,
// so round-trip through that as well.
v.into_boxed_slice().into_vec()
}
fn main() {
assert!(mem::size_of::<MyBin>() <= 128); // if it grows bigger, the trick to access the "header" no longer works
let my_alloc = MyAllocator::new();
let a = v(1usize, &my_alloc);
let b = v(2usize, &my_alloc);
let a = v1(1usize, &my_alloc);
let b = v2(2usize, &my_alloc);
assert_eq!(a[0] + 1, b[0]);
assert_eq!(addr_of!(a[0]).wrapping_add(1), addr_of!(b[0]));
drop((a, b));

View File

@ -1,4 +1,4 @@
#![feature(no_core, lang_items)]
#![feature(no_core, lang_items, freeze_impls)]
#![crate_type = "rlib"]
#![no_core]

View File

@ -1,5 +1,5 @@
// https://github.com/rust-lang/rust/issues/50159
#![crate_name="foo"]
#![crate_name = "foo"]
pub trait Signal {
type Item;
@ -9,7 +9,10 @@ pub trait Signal2 {
type Item2;
}
impl<B, C> Signal2 for B where B: Signal<Item = C> {
impl<B, C> Signal2 for B
where
B: Signal<Item = C>,
{
type Item2 = C;
}
@ -17,7 +20,7 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
// @has - '//h3[@class="code-header"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
// @has - '//h3[@class="code-header"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6
pub struct Switch<B: Signal> {
pub inner: <B as Signal2>::Item2,
}

View File

@ -1,6 +1,5 @@
#![crate_name = "foo"]
#![feature(negative_impls)]
#![feature(negative_impls, freeze_impls, freeze)]
pub struct Foo;
@ -8,6 +7,7 @@ pub struct Foo;
// @!hasraw - 'Auto Trait Implementations'
impl !Send for Foo {}
impl !Sync for Foo {}
impl !std::marker::Freeze for Foo {}
impl !std::marker::Unpin for Foo {}
impl !std::panic::RefUnwindSafe for Foo {}
impl !std::panic::UnwindSafe for Foo {}

View File

@ -2,7 +2,7 @@
// @has - '//h3[@class="code-header"]' 'impl<T> Send for Foo<T>where T: Send'
// @has - '//h3[@class="code-header"]' 'impl<T> Sync for Foo<T>where T: Sync'
// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6
pub struct Foo<T> {
field: T,
}

View File

@ -6,7 +6,7 @@
// 'impl<T> Send for Foo<T>'
//
// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 4
// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
pub struct Foo<T> {
field: T,
}

View File

@ -15,7 +15,7 @@ extern crate rustc_span;
use rustc_errors::{
Diag, DiagCtxt, DiagInner, DiagMessage, Diagnostic, EmissionGuarantee, Level, LintDiagnostic,
SubdiagMessageOp, Subdiagnostic,
SubdiagMessageOp, SubdiagMessage, Subdiagnostic,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::Span;
@ -114,9 +114,15 @@ pub fn make_diagnostics<'a>(dcx: &'a DiagCtxt) {
// Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted for
// `diagnostic_outside_of_impl`.
#[rustc_lint_diagnostics]
pub fn skipped_because_of_annotation<'a>(dcx: &'a DiagCtxt) {
#[allow(rustc::untranslatable_diagnostic)]
let _diag = dcx.struct_err("untranslatable diagnostic"); // okay!
}
// Check that multiple translatable params are allowed in a single function (at one point they
// weren't).
fn f(_x: impl Into<DiagMessage>, _y: impl Into<SubdiagMessage>) {}
fn g() {
f(crate::fluent_generated::no_crate_example, crate::fluent_generated::no_crate_example);
}

View File

@ -0,0 +1,12 @@
#![feature(freeze)]
//@ check-pass
use std::marker::Freeze;
trait Trait<T: Freeze + 'static> {
const VALUE: T;
const VALUE_REF: &'static T = &Self::VALUE;
}
fn main() {}

View File

@ -0,0 +1,15 @@
#![feature(freeze, negative_impls)]
use std::marker::Freeze;
struct Foo;
unsafe impl Freeze for Foo {}
//~^ explicit impls for the `Freeze` trait are not permitted
struct Bar;
impl !Freeze for Bar {}
//~^ explicit impls for the `Freeze` trait are not permitted
fn main() {}

View File

@ -0,0 +1,23 @@
error[E0658]: explicit impls for the `Freeze` trait are not permitted
--> $DIR/feature-gate-freeze-impls.rs:7:1
|
LL | unsafe impl Freeze for Foo {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Freeze` not allowed
|
= note: see issue #121675 <https://github.com/rust-lang/rust/issues/121675> for more information
= help: add `#![feature(freeze_impls)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: explicit impls for the `Freeze` trait are not permitted
--> $DIR/feature-gate-freeze-impls.rs:12:1
|
LL | impl !Freeze for Bar {}
| ^^^^^^^^^^^^^^^^^^^^ impl of `Freeze` not allowed
|
= note: see issue #121675 <https://github.com/rust-lang/rust/issues/121675> for more information
= help: add `#![feature(freeze_impls)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,6 +1,7 @@
//@ run-fail
//@ check-run-results
//@ exec-env:RUST_BACKTRACE=0
//@ normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
//
// Regression test for issue #70963
// The captured stderr from this test reports a location

View File

@ -1,3 +1,3 @@
thread 'main' panicked at library/alloc/src/raw_vec.rs:26:5:
thread 'main' panicked at library/alloc/src/raw_vec.rs:LL:CC:
capacity overflow
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace