diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 4e7afca6a4930..aedfe88f68878 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -50,8 +50,8 @@ //! the optional owned box, [`Option`]`<`[`Box`]`>`. //! //! The following example uses [`Option`] to create an optional box of -//! [`i32`]. Notice that in order to use the inner [`i32`] value first, the -//! `check_optional` function needs to use pattern matching to +//! [`i32`]. Notice that in order to use the inner [`i32`] value, the +//! `check_optional` function first needs to use pattern matching to //! determine whether the box has a value (i.e., it is [`Some(...)`][`Some`]) or //! not ([`None`]). //! @@ -1350,7 +1350,7 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original. /// The [`map`] method takes the `self` argument by value, consuming the original, - /// so this technique uses `as_ref` to first take an `Option` to a reference + /// so this technique uses `from` to first take an `Option` to a reference /// to the value inside the original. /// /// [`map`]: Option::map diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6b2f49cfe48c9..a8baf265aabc7 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -225,13 +225,14 @@ #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(async_stream)] #![feature(arbitrary_self_types)] #![feature(array_error_internals)] #![feature(asm)] #![feature(assert_matches)] #![feature(associated_type_bounds)] +#![feature(async_stream)] #![feature(atomic_mut_ptr)] +#![feature(auto_traits)] #![feature(bench_black_box)] #![feature(box_syntax)] #![feature(c_variadic)] @@ -244,14 +245,14 @@ #![feature(concat_idents)] #![feature(const_cstr_unchecked)] #![feature(const_fn_floating_point_arithmetic)] -#![feature(const_fn_transmute)] #![feature(const_fn_fn_ptr_basics)] +#![feature(const_fn_transmute)] #![feature(const_io_structs)] #![feature(const_ip)] +#![feature(const_ipv4)] #![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] #![feature(const_socketaddr)] -#![feature(const_ipv4)] #![feature(container_error_extra)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] @@ -297,7 +298,6 @@ #![feature(nll)] #![feature(nonnull_slice_from_raw_parts)] #![feature(once_cell)] -#![feature(auto_traits)] #![feature(panic_info_message)] #![feature(panic_internals)] #![feature(panic_unwind)] @@ -329,6 +329,7 @@ #![feature(unboxed_closures)] #![feature(unsafe_cell_raw_get)] #![feature(unwind_attributes)] +#![feature(unwrap_infallible)] #![feature(vec_into_raw_parts)] #![feature(vec_spare_capacity)] // NB: the above list is sorted to minimize merge conflicts. diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 2b6d0d7d5daa7..baf1c5aa2b941 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1346,47 +1346,6 @@ impl Ipv6Addr { (self.segments()[0] & 0xffc0) == 0xfe80 } - /// Returns [`true`] if this is a deprecated unicast site-local address (`fec0::/10`). The - /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as: - /// - /// ```no_rust - /// | 10 | - /// | bits | 54 bits | 64 bits | - /// +----------+-------------------------+----------------------------+ - /// |1111111011| subnet ID | interface ID | - /// +----------+-------------------------+----------------------------+ - /// ``` - /// - /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// assert_eq!( - /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), - /// false - /// ); - /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); - /// ``` - /// - /// # Warning - /// - /// As per [RFC 3879], the whole `fec0::/10` prefix is - /// deprecated. New software must not support site-local - /// addresses. - /// - /// [RFC 3879]: https://tools.ietf.org/html/rfc3879 - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[unstable(feature = "ip", issue = "27709")] - #[inline] - pub const fn is_unicast_site_local(&self) -> bool { - (self.segments()[0] & 0xffc0) == 0xfec0 - } - /// Returns [`true`] if this is an address reserved for documentation /// (`2001:db8::/32`). /// diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index 05f8dea0b7cb1..2109980ad058d 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -480,7 +480,6 @@ fn ipv6_properties() { let unique_local: u16 = 1 << 2; let global: u16 = 1 << 3; let unicast_link_local: u16 = 1 << 4; - let unicast_site_local: u16 = 1 << 6; let unicast_global: u16 = 1 << 7; let documentation: u16 = 1 << 8; let multicast_interface_local: u16 = 1 << 9; @@ -523,11 +522,6 @@ fn ipv6_properties() { } else { assert!(!ip!($s).is_unicast_link_local()); } - if ($mask & unicast_site_local) == unicast_site_local { - assert!(ip!($s).is_unicast_site_local()); - } else { - assert!(!ip!($s).is_unicast_site_local()); - } if ($mask & unicast_global) == unicast_global { assert!(ip!($s).is_unicast_global()); } else { @@ -581,7 +575,6 @@ fn ipv6_properties() { let unique_local: u16 = 1 << 2; let global: u16 = 1 << 3; let unicast_link_local: u16 = 1 << 4; - let unicast_site_local: u16 = 1 << 6; let unicast_global: u16 = 1 << 7; let documentation: u16 = 1 << 8; let multicast_interface_local: u16 = 1 << 9; @@ -651,7 +644,7 @@ fn ipv6_properties() { check!( "fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_site_local | unicast_global | global + unicast_global | global ); check!( @@ -889,9 +882,6 @@ fn ipv6_const() { const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local(); assert!(!IS_UNICAST_LINK_LOCAL); - const IS_UNICAST_SITE_LOCAL: bool = IP_ADDRESS.is_unicast_site_local(); - assert!(!IS_UNICAST_SITE_LOCAL); - const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation(); assert!(!IS_DOCUMENTATION); diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 1e19aff51f8d6..72e6c23ee4990 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -24,18 +24,32 @@ fn lang_start_internal( main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe), argc: isize, argv: *const *const u8, -) -> isize { - use crate::panic; - use crate::sys_common; - +) -> Result { + use crate::{mem, panic, sys, sys_common}; + let rt_abort = move |e| { + mem::forget(e); + rtabort!("initialization or cleanup bug"); + }; + // Guard against the code called by this function from unwinding outside of the Rust-controlled + // code, which is UB. This is a requirement imposed by a combination of how the + // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking + // mechanism itself. + // + // There are a couple of instances where unwinding can begin. First is inside of the + // `rt::init`, `rt::cleanup` and similar functions controlled by libstd. In those instances a + // panic is a libstd implementation bug. A quite likely one too, as there isn't any way to + // prevent libstd from accidentally introducing a panic to these functions. Another is from + // user code from `main` or, more nefariously, as described in e.g. issue #86030. // SAFETY: Only called once during runtime initialization. - unsafe { sys_common::rt::init(argc, argv) }; - - let exit_code = panic::catch_unwind(main); - - sys_common::rt::cleanup(); - - exit_code.unwrap_or(101) as isize + panic::catch_unwind(move || unsafe { sys_common::rt::init(argc, argv) }).map_err(rt_abort)?; + let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize) + .map_err(move |e| { + mem::forget(e); + rtprintpanic!("drop of the panic payload panicked"); + sys::abort_internal() + }); + panic::catch_unwind(sys_common::rt::cleanup).map_err(rt_abort)?; + ret_code } #[cfg(not(test))] @@ -50,4 +64,5 @@ fn lang_start( argc, argv, ) + .into_ok() } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d1c18821ea644..bc04480ab7c51 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -26,6 +26,8 @@ use rustc_mir::const_eval::{is_const_fn, is_unstable_const_fn}; use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, ExpnKind}; +use rustc_target::spec::abi::Abi; +use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety; use rustc_typeck::hir_ty_to_ty; use std::collections::hash_map::Entry; @@ -350,12 +352,12 @@ impl<'a> Clean> for ty::Predicate<'a> { ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx), ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx), ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)), + ty::PredicateKind::ConstEvaluatable(..) => None, ty::PredicateKind::Subtype(..) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), } @@ -2132,7 +2134,11 @@ impl Clean for (&hir::ForeignItem<'_>, Option) { decl, generics, header: hir::FnHeader { - unsafety: hir::Unsafety::Unsafe, + unsafety: if abi == Abi::RustIntrinsic { + intrinsic_operation_unsafety(item.ident.name) + } else { + hir::Unsafety::Unsafe + }, abi, constness: hir::Constness::NotConst, asyncness: hir::IsAsync::NotAsync, diff --git a/src/test/rustdoc/const-generics/const-evaluatable-checked.rs b/src/test/rustdoc/const-generics/const-evaluatable-checked.rs new file mode 100644 index 0000000000000..1c074fdb3f882 --- /dev/null +++ b/src/test/rustdoc/const-generics/const-evaluatable-checked.rs @@ -0,0 +1,7 @@ +#![crate_name = "foo"] +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] +// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647 +// @has foo/struct.Ice.html '//pre[@class="rust struct"]' \ +// 'pub struct Ice where [(); N + 1]: ;' +pub struct Ice where [(); N + 1]:; diff --git a/src/test/rustdoc/safe-intrinsic.rs b/src/test/rustdoc/safe-intrinsic.rs new file mode 100644 index 0000000000000..d3bb8514b7e43 --- /dev/null +++ b/src/test/rustdoc/safe-intrinsic.rs @@ -0,0 +1,20 @@ +#![feature(intrinsics)] +#![feature(no_core)] + +#![no_core] +#![crate_name = "foo"] + +extern "rust-intrinsic" { + // @has 'foo/fn.abort.html' + // @has - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !' + pub fn abort() -> !; + // @has 'foo/fn.unreachable.html' + // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !' + pub fn unreachable() -> !; +} + +extern "C" { + // @has 'foo/fn.needs_drop.html' + // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "C" fn needs_drop() -> !' + pub fn needs_drop() -> !; +} diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr new file mode 100644 index 0000000000000..965bc67a381ae --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr @@ -0,0 +1,36 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + +error[E0658]: mutation through a reference is not allowed in constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-76510.rs:5:1 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─alloc2──╼ 07 00 00 00 │ ╾──╼.... + } + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr new file mode 100644 index 0000000000000..ac7d5993585e8 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr @@ -0,0 +1,36 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + +error[E0658]: mutation through a reference is not allowed in constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-76510.rs:5:1 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────alloc2────────╼ 07 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs new file mode 100644 index 0000000000000..892f6c98116c2 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs @@ -0,0 +1,18 @@ +// stderr-per-bitwidth + +use std::mem::{transmute, ManuallyDrop}; + +const S: &'static mut str = &mut " hello "; +//~^ ERROR: mutable references are not allowed in the final value of constants +//~| ERROR: mutation through a reference is not allowed in constants +//~| ERROR: cannot borrow data in a `&` reference as mutable +//~| ERROR: it is undefined behavior to use this value + +const fn trigger() -> [(); unsafe { + let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + 0 + }] { + [(); 0] +} + +fn main() {} diff --git a/src/test/ui/rt-explody-panic-payloads.rs b/src/test/ui/rt-explody-panic-payloads.rs new file mode 100644 index 0000000000000..6a00547d336fd --- /dev/null +++ b/src/test/ui/rt-explody-panic-payloads.rs @@ -0,0 +1,24 @@ +// run-pass +use std::env; +use std::process::Command; + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + std::panic::panic_any(Bomb); + } +} + +fn main() { + let args = env::args().collect::>(); + let output = match &args[..] { + [me] => Command::new(&me).arg("plant the").output(), + [..] => std::panic::panic_any(Bomb), + }.expect("running the command should have succeeded"); + println!("{:#?}", output); + let stderr = std::str::from_utf8(&output.stderr); + assert!(stderr.map(|v| { + v.ends_with("drop of the panic payload panicked") + }).unwrap_or(false)); +}