diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 67a0d0dabea94..39988cf64e54b 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -8,6 +8,7 @@ rustc_attrs, transparent_unions, auto_traits, + freeze_impls, thread_local )] #![no_core] diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index cc3d647c8c82f..a868471ed1d4d 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -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] diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a10f4b934ea0a..52421fce86738 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -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. diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index fc7a73e12be0a..054a3af212a55 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -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); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a8426d78cace0..f592c1d3dd373 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -864,6 +864,7 @@ symbols! { format_placeholder, format_unsafe_arg, freeze, + freeze_impls, freg, frem_algebraic, frem_fast, diff --git a/config.example.toml b/config.example.toml index c1939933850c4..4fbdccba91104 100644 --- a/config.example.toml +++ b/config.example.toml @@ -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 = (string) + # ============================================================================= # Distribution options # diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index ace73c0fdaa5e..0ee293db73a93 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -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 RawVec { let me = ManuallyDrop::new(self); unsafe { - let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); + let slice = ptr::slice_from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); Box::from_raw_in(slice, ptr::read(&me.alloc)) } } diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index f4e392760c8e4..21d5dce04a0fc 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -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")] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0f7885769c267..6bcf7c13e64eb 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -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)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 2e22129d7b64d..a56a2578c2241 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -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 !Freeze for UnsafeCell {} marker_impls! { + #[unstable(feature = "freeze", issue = "121675")] unsafe Freeze for {T: ?Sized} PhantomData, {T: ?Sized} *const T, diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 33c2769591d7a..64f1f360821da 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -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(range: R, bounds: ops::RangeTo) -> Option> +where + R: ops::RangeBounds, +{ + 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, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 2dd01ba33afc8..4a574bf034745 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -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; diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 2af6382f3daee..6520ca9fc48ef 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -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 diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 2fc6598d876e4..1c828bac4b662 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -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) } diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index 7667f7611064a..849e64ac59135 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -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 diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 7b751079afbc6..baaa8257d8452 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -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; } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 58bc379136978..248d831b6e30e 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -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 diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 4766f9d426c30..683e0a4302f94 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -581,6 +581,7 @@ pub struct Target { pub musl_libdir: Option, pub wasi_root: Option, pub qemu_rootfs: Option, + pub runner: Option, pub no_std: bool, pub codegen_backends: Option>, } @@ -1144,6 +1145,7 @@ define_config! { qemu_rootfs: Option = "qemu-rootfs", no_std: Option = "no-std", codegen_backends: Option> = "codegen-backends", + runner: Option = "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; diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 1dce8d8ac7184..e03b1e179084e 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -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 - // . - 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 - // . - if skip_target_sanity { + // skip check for cross-targets + if skip_target_sanity && target != &build.build { continue; } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 10c13fecbf367..938b95cc60e4b 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -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 { + 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. /// diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index d166b84e51fc5..a348fa3584147 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -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", + }, ]; diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 06d8f099c33fa..78246136f2a1b 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -266,8 +266,10 @@ pub struct Config { pub logfile: Option, /// A command line to prefix program execution with, - /// for running under valgrind - pub runtool: Option, + /// for running under valgrind for example. + /// + /// Similar to `CARGO_*_RUNNER` configuration. + pub runner: Option, /// Flags to pass to the compiler when building for the host pub host_rustcflags: Vec, diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index b32a5a4bf1a4a..ef02e7fcb4abb 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -86,7 +86,7 @@ pub fn parse_config(args: Vec) -> 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) -> 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)); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ae0db88d873be..9fd83c507edde 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -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") { diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 13ce9d119bc3b..4535bcf6dfedd 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -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"))?; diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 9e0baf86cbcf6..bb4c325b746fc 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -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)] diff --git a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs index 541e5f244db08..ada9cf4537547 100644 --- a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs +++ b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs @@ -92,6 +92,8 @@ unsafe impl Allocator for MyAllocator { } unsafe fn deallocate(&self, ptr: NonNull, _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: T, a: A) -> Vec { +fn v1(t: T, a: A) -> Vec { (Box::new_in([t], a) as Box<[T], A>).into_vec() } +fn v2(t: T, a: A) -> Vec { + 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::() <= 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)); diff --git a/tests/run-make/min-global-align/min_global_align.rs b/tests/run-make/min-global-align/min_global_align.rs index 135792e937205..cd1ef8cb351ff 100644 --- a/tests/run-make/min-global-align/min_global_align.rs +++ b/tests/run-make/min-global-align/min_global_align.rs @@ -1,4 +1,4 @@ -#![feature(no_core, lang_items)] +#![feature(no_core, lang_items, freeze_impls)] #![crate_type = "rlib"] #![no_core] diff --git a/tests/run-make/sigpipe-in-child-processes/Makefile b/tests/run-make/sigpipe-in-child-processes/Makefile new file mode 100644 index 0000000000000..acdca1a416f71 --- /dev/null +++ b/tests/run-make/sigpipe-in-child-processes/Makefile @@ -0,0 +1,15 @@ +# ignore-cross-compile because we run the compiled code +# only-unix + +# See main.rs for a description of this test. + +include ../tools.mk + +all: + $(RUSTC) assert-sigpipe-disposition.rs -o $(TMPDIR)/assert-sigpipe-disposition; + for revision in default sig_dfl sig_ign inherit; do \ + echo -n "Testing revision $$revision ... "; \ + $(RUSTC) main.rs --cfg $$revision -o $(TMPDIR)/main.$$revision || exit 1; \ + $(TMPDIR)/main.$$revision $(TMPDIR)/assert-sigpipe-disposition || exit 1; \ + echo "ok"; \ + done diff --git a/tests/run-make/sigpipe-in-child-processes/assert-sigpipe-disposition.rs b/tests/run-make/sigpipe-in-child-processes/assert-sigpipe-disposition.rs new file mode 100644 index 0000000000000..8c0b8149b819b --- /dev/null +++ b/tests/run-make/sigpipe-in-child-processes/assert-sigpipe-disposition.rs @@ -0,0 +1,25 @@ +#![feature(start, rustc_private)] + +extern crate libc; + +// Use #[start] so we don't have a runtime that messes with SIGPIPE. +#[start] +fn start(argc: isize, argv: *const *const u8) -> isize { + assert_eq!(argc, 2, "Must pass SIG_IGN or SIG_DFL as first arg"); + let expected = + match unsafe { std::ffi::CStr::from_ptr(*argv.offset(1) as *const i8) }.to_str().unwrap() { + "SIG_IGN" => libc::SIG_IGN, + "SIG_DFL" => libc::SIG_DFL, + arg => panic!("Must pass SIG_IGN or SIG_DFL as first arg. Got: {}", arg), + }; + + let actual = unsafe { + let mut actual: libc::sigaction = std::mem::zeroed(); + libc::sigaction(libc::SIGPIPE, std::ptr::null(), &mut actual); + actual.sa_sigaction + }; + + assert_eq!(actual, expected, "actual and expected SIGPIPE disposition in child differs"); + + return 0; +} diff --git a/tests/run-make/sigpipe-in-child-processes/main.rs b/tests/run-make/sigpipe-in-child-processes/main.rs new file mode 100644 index 0000000000000..30c1043538c5d --- /dev/null +++ b/tests/run-make/sigpipe-in-child-processes/main.rs @@ -0,0 +1,51 @@ +// Checks the signal disposition of `SIGPIPE` in child processes, and in our own +// process for robustness. Without any `unix_sigpipe` attribute, `SIG_IGN` is +// the default. But there is a difference in how `SIGPIPE` is treated in child +// processes with and without the attribute. Search for +// `unix_sigpipe_attr_specified()` in the code base to learn more. +// +// Note that there are many other tests for `unix_sigpipe` in +// tests/ui/attributes/unix_sigpipe. + +#![feature(rustc_private)] +#![cfg_attr(any(sig_dfl, sig_ign, inherit), feature(unix_sigpipe))] + +extern crate libc; + +#[cfg_attr(sig_dfl, unix_sigpipe = "sig_dfl")] +#[cfg_attr(sig_ign, unix_sigpipe = "sig_ign")] +#[cfg_attr(inherit, unix_sigpipe = "inherit")] +fn main() { + // By default, we get SIG_IGN but the child gets SIG_DFL. + #[cfg(default)] + let (we_expect, child_expects) = (libc::SIG_IGN, libc::SIG_DFL); + + // With #[unix_sigpipe = "sig_dfl"] we get SIG_DFL and the child does too. + #[cfg(sig_dfl)] + let (we_expect, child_expects) = (libc::SIG_DFL, libc::SIG_DFL); + + // With #[unix_sigpipe = "sig_ign"] we get SIG_IGN and the child does too. + #[cfg(sig_ign)] + let (we_expect, child_expects) = (libc::SIG_IGN, libc::SIG_IGN); + + // With #[unix_sigpipe = "inherit"] we get SIG_DFL and the child does too. + #[cfg(inherit)] + let (we_expect, child_expects) = (libc::SIG_DFL, libc::SIG_DFL); + + let actual = unsafe { + let mut actual: libc::sigaction = std::mem::zeroed(); + libc::sigaction(libc::SIGPIPE, std::ptr::null(), &mut actual); + actual.sa_sigaction + }; + assert_eq!(actual, we_expect, "we did not get the SIGPIPE disposition we expect"); + + let child_program = std::env::args().nth(1).unwrap(); + let child_expects = match child_expects { + libc::SIG_DFL => "SIG_DFL", + libc::SIG_IGN => "SIG_IGN", + _ => unreachable!(), + }; + assert!( + std::process::Command::new(child_program).arg(child_expects).status().unwrap().success() + ); +} diff --git a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs index 0663ed5fc81ff..7d9133b85a613 100644 --- a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs +++ b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs @@ -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 Signal2 for B where B: Signal { +impl Signal2 for B +where + B: Signal, +{ type Item2 = C; } @@ -17,7 +20,7 @@ impl Signal2 for B where B: Signal { // @has - '//h3[@class="code-header"]' 'impl Send for Switchwhere ::Item: Send' // @has - '//h3[@class="code-header"]' 'impl Sync for Switchwhere ::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 { pub inner: ::Item2, } diff --git a/tests/rustdoc/empty-section.rs b/tests/rustdoc/empty-section.rs index d8241ab96f6dd..0d6afb0e44447 100644 --- a/tests/rustdoc/empty-section.rs +++ b/tests/rustdoc/empty-section.rs @@ -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 {} diff --git a/tests/rustdoc/synthetic_auto/basic.rs b/tests/rustdoc/synthetic_auto/basic.rs index 043ac24148838..16b8cce490c84 100644 --- a/tests/rustdoc/synthetic_auto/basic.rs +++ b/tests/rustdoc/synthetic_auto/basic.rs @@ -2,7 +2,7 @@ // @has - '//h3[@class="code-header"]' 'impl Send for Foowhere T: Send' // @has - '//h3[@class="code-header"]' 'impl Sync for Foowhere 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 { field: T, } diff --git a/tests/rustdoc/synthetic_auto/manual.rs b/tests/rustdoc/synthetic_auto/manual.rs index 7fc8447df3efc..692d68294a7ef 100644 --- a/tests/rustdoc/synthetic_auto/manual.rs +++ b/tests/rustdoc/synthetic_auto/manual.rs @@ -6,7 +6,7 @@ // 'impl Send for Foo' // // @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 { field: T, } diff --git a/tests/ui/associated-consts/freeze.rs b/tests/ui/associated-consts/freeze.rs new file mode 100644 index 0000000000000..2364ee1f4956f --- /dev/null +++ b/tests/ui/associated-consts/freeze.rs @@ -0,0 +1,12 @@ +#![feature(freeze)] + +//@ check-pass + +use std::marker::Freeze; + +trait Trait { + const VALUE: T; + const VALUE_REF: &'static T = &Self::VALUE; +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.rs b/tests/ui/feature-gates/feature-gate-freeze-impls.rs new file mode 100644 index 0000000000000..c14c9494874a2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-freeze-impls.rs @@ -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() {} diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.stderr b/tests/ui/feature-gates/feature-gate-freeze-impls.stderr new file mode 100644 index 0000000000000..eef524fe78e8b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-freeze-impls.stderr @@ -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 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 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`. diff --git a/tests/ui/hygiene/panic-location.rs b/tests/ui/hygiene/panic-location.rs index a98960d74b019..b2f9bfe4f9a7a 100644 --- a/tests/ui/hygiene/panic-location.rs +++ b/tests/ui/hygiene/panic-location.rs @@ -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 diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index ec0ce18c3dfa7..5c1778bc485f9 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -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