diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index caea53d9200f4..2303d777ddbda 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2720,12 +2720,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Check field access expressions, this works for both structs and tuples. /// Returns the Ty of the field. /// - /// ```not_rust - /// base.field - /// ^^^^^^^^^^ expr - /// ^^^^ base - /// ^^^^^ field - /// ``` + /// ```ignore (illustrative) + /// base.field + /// ^^^^^^^^^^ expr + /// ^^^^ base + /// ^^^^^ field + /// ``` fn check_expr_field( &self, expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7b950b97d301d..cc9ed566edac5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -193,8 +193,10 @@ enum ImplTraitContext { } /// Used for tracking import use types which will be used for redundant import checking. +/// /// ### Used::Scope Example -/// ```rust,compile_fail +/// +/// ```rust,compile_fail /// #![deny(redundant_imports)] /// use std::mem::drop; /// fn main() { @@ -202,6 +204,7 @@ enum ImplTraitContext { /// drop(s); /// } /// ``` +/// /// Used::Other is for other situations like module-relative uses. #[derive(Clone, Copy, PartialEq, PartialOrd, Debug)] enum Used { diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs index 4fc395c221cb6..173977b77bd13 100644 --- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs @@ -1,10 +1,11 @@ -use crate::spec::{LinkerFlavor, Lld, Target, base}; +use crate::spec::{LinkerFlavor, Lld, SanitizerSet, Target, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); + base.vendor = "win7".into(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); - base.vendor = "win7".into(); + base.supported_sanitizers = SanitizerSet::ADDRESS; base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &[ // Mark all dynamic libraries and executables as compatible with the larger 4GiB address @@ -19,7 +20,7 @@ pub(crate) fn target() -> Target { Target { llvm_target: "i686-pc-windows-msvc".into(), metadata: crate::spec::TargetMetadata { - description: Some("32-bit Windows 7 support".into()), + description: Some("32-bit MSVC (Windows 7+)".into()), tier: Some(3), host_tools: Some(false), std: Some(true), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs index f42188ec61ac8..2eceb6881087d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs @@ -1,16 +1,17 @@ -use crate::spec::{Target, base}; +use crate::spec::{SanitizerSet, Target, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); + base.vendor = "win7".into(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); - base.vendor = "win7".into(); + base.supported_sanitizers = SanitizerSet::ADDRESS; Target { llvm_target: "x86_64-pc-windows-msvc".into(), metadata: crate::spec::TargetMetadata { - description: Some("64-bit Windows 7 support".into()), + description: Some("64-bit MSVC (Windows 7+)".into()), tier: Some(3), host_tools: Some(false), std: Some(true), diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cfa4c1fb56479..306d565a77e66 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -252,7 +252,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; -use crate::marker::{PhantomData, Unsize}; +use crate::marker::{PhantomData, PointerLike, Unsize}; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; use crate::pin::PinCoerceUnsized; @@ -677,6 +677,9 @@ impl, U> CoerceUnsized> for Cell {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U> DispatchFromDyn> for Cell {} +#[unstable(feature = "pointer_like_trait", issue = "none")] +impl PointerLike for Cell {} + impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` /// @@ -2258,6 +2261,9 @@ impl, U> CoerceUnsized> for UnsafeCell {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U> DispatchFromDyn> for UnsafeCell {} +#[unstable(feature = "pointer_like_trait", issue = "none")] +impl PointerLike for UnsafeCell {} + /// [`UnsafeCell`], but [`Sync`]. /// /// This is just an `UnsafeCell`, except it implements `Sync` @@ -2364,6 +2370,9 @@ impl, U> CoerceUnsized> for SyncUnsafeCell //#[unstable(feature = "sync_unsafe_cell", issue = "95439")] impl, U> DispatchFromDyn> for SyncUnsafeCell {} +#[unstable(feature = "pointer_like_trait", issue = "none")] +impl PointerLike for SyncUnsafeCell {} + #[allow(unused)] fn assert_coerce_unsized( a: UnsafeCell<&i32>, diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d0d8609f43f08..29fc01d37fe3f 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1003,6 +1003,7 @@ pub trait PointerLike {} marker_impls! { #[unstable(feature = "pointer_like_trait", issue = "none")] PointerLike for + isize, usize, {T} &T, {T} &mut T, diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 9b3d690209856..58fb5be5812c8 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -232,6 +232,26 @@ use crate::{fmt, intrinsics, ptr, slice}; /// remain `#[repr(transparent)]`. That said, `MaybeUninit` will *always* guarantee that it has /// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that /// guarantee may evolve. +/// +/// Note that even though `T` and `MaybeUninit` are ABI compatible it is still unsound to +/// transmute `&mut T` to `&mut MaybeUninit` and expose that to safe code because it would allow +/// safe code to access uninitialized memory: +/// +/// ```rust,no_run +/// use core::mem::MaybeUninit; +/// +/// fn unsound_transmute(val: &mut T) -> &mut MaybeUninit { +/// unsafe { core::mem::transmute(val) } +/// } +/// +/// fn main() { +/// let mut code = 0; +/// let code = &mut code; +/// let code2 = unsound_transmute(code); +/// *code2 = MaybeUninit::uninit(); +/// std::process::exit(*code); // UB! Accessing uninitialized memory. +/// } +/// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] // Lang item so we can wrap other types in it. This is useful for coroutines. #[lang = "maybe_uninit"] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 3eeb9129347f5..e0ba469272ed1 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1555,6 +1555,10 @@ impl DispatchFromDyn> for NonNull where T: U #[stable(feature = "pin", since = "1.33.0")] unsafe impl PinCoerceUnsized for NonNull {} +#[unstable(feature = "pointer_like_trait", issue = "none")] +#[cfg(not(bootstrap))] +impl core::marker::PointerLike for NonNull {} + #[stable(feature = "nonnull", since = "1.25.0")] impl fmt::Debug for NonNull { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 0178691c0e551..9b752ed14437c 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1869,8 +1869,10 @@ impl Permissions { /// /// # Note /// - /// This function does not take Access Control Lists (ACLs) or Unix group - /// membership into account. + /// This function does not take Access Control Lists (ACLs), Unix group + /// membership and other nuances into account. + /// Therefore the return value of this function cannot be relied upon + /// to predict whether attempts to read or write the file will actually succeed. /// /// # Windows /// @@ -1885,10 +1887,13 @@ impl Permissions { /// # Unix (including macOS) /// /// On Unix-based platforms this checks if *any* of the owner, group or others - /// write permission bits are set. It does not check if the current - /// user is in the file's assigned group. It also does not check ACLs. - /// Therefore the return value of this function cannot be relied upon - /// to predict whether attempts to read or write the file will actually succeed. + /// write permission bits are set. It does not consider anything else, including: + /// + /// * Whether the current user is in the file's assigned group. + /// * Permissions granted by ACL. + /// * That `root` user can write to files that do not have any write bits set. + /// * Writable files on a filesystem that is mounted read-only. + /// /// The [`PermissionsExt`] trait gives direct access to the permission bits but /// also does not read ACLs. /// diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index d3b4631a21285..250ef0794add4 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -37,7 +37,7 @@ use walkdir::WalkDir; use self::header::{EarlyProps, make_test_description}; use crate::common::{ - CompareMode, Config, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, + CompareMode, Config, Debugger, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir, output_relative_path, }; use crate::header::HeadersCache; @@ -183,7 +183,13 @@ pub fn parse_config(args: Vec) -> Config { "What custom diff tool to use for displaying compiletest tests.", "COMMAND", ) - .reqopt("", "minicore-path", "path to minicore aux library", "PATH"); + .reqopt("", "minicore-path", "path to minicore aux library", "PATH") + .optopt( + "", + "debugger", + "only test a specific debugger in debuginfo tests", + "gdb | lldb | cdb", + ); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { @@ -302,7 +308,11 @@ pub fn parse_config(args: Vec) -> Config { stage_id: matches.opt_str("stage-id").unwrap(), mode, suite: matches.opt_str("suite").unwrap(), - debugger: None, + debugger: matches.opt_str("debugger").map(|debugger| { + debugger + .parse::() + .unwrap_or_else(|_| panic!("unknown `--debugger` option `{debugger}` given")) + }), run_ignored, with_rustc_debug_assertions, with_std_debug_assertions, @@ -475,9 +485,16 @@ pub fn run_tests(config: Arc) { if let Mode::DebugInfo = config.mode { // Debugging emscripten code doesn't make sense today if !config.target.contains("emscripten") { - configs.extend(debuggers::configure_cdb(&config)); - configs.extend(debuggers::configure_gdb(&config)); - configs.extend(debuggers::configure_lldb(&config)); + match config.debugger { + Some(Debugger::Cdb) => configs.extend(debuggers::configure_cdb(&config)), + Some(Debugger::Gdb) => configs.extend(debuggers::configure_gdb(&config)), + Some(Debugger::Lldb) => configs.extend(debuggers::configure_lldb(&config)), + None => { + configs.extend(debuggers::configure_cdb(&config)); + configs.extend(debuggers::configure_gdb(&config)); + configs.extend(debuggers::configure_lldb(&config)); + } + } } } else { configs.push(config.clone()); diff --git a/tests/ui/dyn-star/cell.rs b/tests/ui/dyn-star/cell.rs new file mode 100644 index 0000000000000..f4c7927a39dc9 --- /dev/null +++ b/tests/ui/dyn-star/cell.rs @@ -0,0 +1,34 @@ +// This test with Cell also indirectly exercises UnsafeCell in dyn*. +// +//@ run-pass + +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::cell::Cell; + +trait Rw { + fn read(&self) -> T; + fn write(&self, v: T); +} + +impl Rw for Cell { + fn read(&self) -> T { + self.get() + } + fn write(&self, v: T) { + self.set(v) + } +} + +fn make_dyn_star() -> dyn* Rw { + Cell::new(42usize) as dyn* Rw +} + +fn main() { + let x = make_dyn_star(); + + assert_eq!(x.read(), 42); + x.write(24); + assert_eq!(x.read(), 24); +} diff --git a/tests/ui/dyn-star/error.rs b/tests/ui/dyn-star/error.rs index 7288596f3fa8a..1d252d2ce42b2 100644 --- a/tests/ui/dyn-star/error.rs +++ b/tests/ui/dyn-star/error.rs @@ -6,7 +6,7 @@ use std::fmt::Debug; trait Foo {} fn make_dyn_star() { - let i = 42; + let i = 42usize; let dyn_i: dyn* Foo = i; //~ ERROR trait bound `usize: Foo` is not satisfied } diff --git a/tests/ui/dyn-star/float-as-dyn-star.stderr b/tests/ui/dyn-star/float-as-dyn-star.stderr index 9caba512e5f43..06071a27afc61 100644 --- a/tests/ui/dyn-star/float-as-dyn-star.stderr +++ b/tests/ui/dyn-star/float-as-dyn-star.stderr @@ -14,7 +14,9 @@ LL | f32::from_bits(0x1) as f64 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `f64` needs to be a pointer-like type | = help: the trait `PointerLike` is not implemented for `f64` - = help: the trait `PointerLike` is implemented for `usize` + = help: the following other types implement trait `PointerLike`: + isize + usize error: aborting due to 1 previous error; 1 warning emitted