mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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:
commit
e919669d42
@ -8,6 +8,7 @@
|
||||
rustc_attrs,
|
||||
transparent_unions,
|
||||
auto_traits,
|
||||
freeze_impls,
|
||||
thread_local
|
||||
)]
|
||||
#![no_core]
|
||||
|
@ -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]
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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, ¶m_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)
|
||||
|
@ -864,6 +864,7 @@ symbols! {
|
||||
format_placeholder,
|
||||
format_unsafe_arg,
|
||||
freeze,
|
||||
freeze_impls,
|
||||
freg,
|
||||
frem_algebraic,
|
||||
frem_fast,
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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")]
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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",
|
||||
},
|
||||
];
|
||||
|
@ -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>,
|
||||
|
@ -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));
|
||||
|
@ -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") {
|
||||
|
@ -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"))?;
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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));
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(no_core, lang_items)]
|
||||
#![feature(no_core, lang_items, freeze_impls)]
|
||||
#![crate_type = "rlib"]
|
||||
#![no_core]
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
12
tests/ui/associated-consts/freeze.rs
Normal file
12
tests/ui/associated-consts/freeze.rs
Normal 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() {}
|
15
tests/ui/feature-gates/feature-gate-freeze-impls.rs
Normal file
15
tests/ui/feature-gates/feature-gate-freeze-impls.rs
Normal 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() {}
|
23
tests/ui/feature-gates/feature-gate-freeze-impls.stderr
Normal file
23
tests/ui/feature-gates/feature-gate-freeze-impls.stderr
Normal 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`.
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user