diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 7195c41eae92e..b1948ae072be9 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2720,6 +2720,9 @@ declare_lint! { /// The asm block must not contain any operands other than `const` and /// `sym`. Additionally, naked function should specify a non-Rust ABI. /// + /// Naked functions cannot be inlined. All forms of the `inline` attribute + /// are prohibited. + /// /// While other definitions of naked functions were previously accepted, /// they are unsupported and might not work reliably. This is a /// [future-incompatible] lint that will transition into hard error in diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 21534290d1291..d27ce6ec81a90 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -599,13 +599,10 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam Parser<'a> { // the AST for typechecking. err.span_label(ident.span, "while parsing this `fn`"); err.emit(); - (Vec::new(), None) } else { return Err(err); } - } else { - unreachable!() } + (Vec::new(), None) }; attrs.extend(inner_attrs); Ok(body) diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 89bc2e1a9870f..e05ec205b65b8 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -1,6 +1,6 @@ //! Checks validity of naked functions. -use rustc_ast::InlineAsmOptions; +use rustc_ast::{Attribute, InlineAsmOptions}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{ErasedMap, FnKind, NestedVisitorMap, Visitor}; @@ -70,10 +70,20 @@ impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> { check_no_patterns(self.tcx, body.params); check_no_parameters_use(self.tcx, body); check_asm(self.tcx, hir_id, body, span); + check_inline(self.tcx, hir_id, attrs); } } } +/// Check that the function isn't inlined. +fn check_inline(tcx: TyCtxt<'_>, hir_id: HirId, attrs: &[Attribute]) { + for attr in attrs.iter().filter(|attr| attr.has_name(sym::inline)) { + tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, attr.span, |lint| { + lint.build("naked functions cannot be inlined").emit(); + }); + } +} + /// Checks that function uses non-Rust ABI. fn check_abi(tcx: TyCtxt<'_>, hir_id: HirId, abi: Abi, fn_ident_span: Span) { if abi == Abi::Rust { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index b5db3331d0447..ba99e0c03d8e2 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1220,6 +1220,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { match e.kind() { ty::Param(_) => (), // pass struct(T, T, T, T) through, let monomorphization catch errors ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok + ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct([T; N]) through, let monomorphization catch errors ty::Array(t, _clen) if matches!( t.kind(), diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index ca86e569bc127..132733a052510 100644 --- a/library/std/src/lazy.rs +++ b/library/std/src/lazy.rs @@ -87,6 +87,19 @@ impl UnwindSafe for SyncOnceCell {} #[unstable(feature = "once_cell", issue = "74465")] impl Default for SyncOnceCell { + /// Creates a new empty cell. + /// + /// # Example + /// + /// ``` + /// #![feature(once_cell)] + /// + /// use std::lazy::SyncOnceCell; + /// + /// fn main() { + /// assert_eq!(SyncOnceCell::<()>::new(), SyncOnceCell::default()); + /// } + /// ``` fn default() -> SyncOnceCell { SyncOnceCell::new() } @@ -118,6 +131,23 @@ impl Clone for SyncOnceCell { #[unstable(feature = "once_cell", issue = "74465")] impl From for SyncOnceCell { + /// Create a new cell with its contents set to `value`. + /// + /// # Example + /// + /// ``` + /// #![feature(once_cell)] + /// + /// use std::lazy::SyncOnceCell; + /// + /// # fn main() -> Result<(), i32> { + /// let a = SyncOnceCell::from(3); + /// let b = SyncOnceCell::new(); + /// b.set(3)?; + /// assert_eq!(a, b); + /// Ok(()) + /// # } + /// ``` fn from(value: T) -> Self { let cell = Self::new(); match cell.set(value) { diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 19e696bfef89d..ac92cfe19cd33 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -379,6 +379,29 @@ impl IpAddr { pub const fn is_ipv6(&self) -> bool { matches!(self, IpAddr::V6(_)) } + + /// Converts this address to an `IpAddr::V4` if it is a IPv4-mapped IPv6 addresses, otherwise it + /// return `self` as-is. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true); + /// ``` + #[inline] + #[rustc_const_unstable(feature = "const_ip", issue = "76205")] + #[unstable(feature = "ip", issue = "27709")] + pub const fn to_canonical(&self) -> IpAddr { + match self { + &v4 @ IpAddr::V4(_) => v4, + IpAddr::V6(v6) => v6.to_canonical(), + } + } } impl Ipv4Addr { @@ -1598,6 +1621,28 @@ impl Ipv6Addr { } } + /// Converts this address to an `IpAddr::V4` if it is a IPv4-mapped addresses, otherwise it + /// returns self wrapped in a `IpAddr::V6`. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true); + /// ``` + #[inline] + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[unstable(feature = "ip", issue = "27709")] + pub const fn to_canonical(&self) -> IpAddr { + if let Some(mapped) = self.to_ipv4_mapped() { + return IpAddr::V4(mapped); + } + IpAddr::V6(*self) + } + /// Returns the sixteen eight-bit integers the IPv6 address consists of. /// /// ``` diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index e950891ef92bd..8ff600d5334fd 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -402,7 +402,7 @@ assert_eq!(a, 5); This will decrement the `{0}` register value from 10 to 3, then add 2 and store it in `a`. -This example show a few thing: +This example shows a few things: First that the same number can be used as a label multiple times in the same inline block. diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs index a46ca4544a68f..7075995c2cfff 100644 --- a/src/test/ui/asm/naked-functions.rs +++ b/src/test/ui/asm/naked-functions.rs @@ -167,3 +167,46 @@ pub unsafe extern "C" fn valid_c() { pub unsafe extern "C" fn valid_att_syntax() { asm!("", options(noreturn, att_syntax)); } + +#[naked] +pub unsafe extern "C" fn inline_none() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline] +//~^ WARN naked functions cannot be inlined +//~| WARN this was previously accepted +pub unsafe extern "C" fn inline_hint() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline(always)] +//~^ WARN naked functions cannot be inlined +//~| WARN this was previously accepted +pub unsafe extern "C" fn inline_always() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline(never)] +//~^ WARN naked functions cannot be inlined +//~| WARN this was previously accepted +pub unsafe extern "C" fn inline_never() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline] +//~^ WARN naked functions cannot be inlined +//~| WARN this was previously accepted +#[inline(always)] +//~^ WARN naked functions cannot be inlined +//~| WARN this was previously accepted +#[inline(never)] +//~^ WARN naked functions cannot be inlined +//~| WARN this was previously accepted +pub unsafe extern "C" fn inline_all() { + asm!("", options(noreturn)); +} diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr index 9a82da8d90d3c..2a186a69ff460 100644 --- a/src/test/ui/asm/naked-functions.stderr +++ b/src/test/ui/asm/naked-functions.stderr @@ -296,5 +296,59 @@ LL | pub unsafe extern "Rust" fn rust_abi() { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 -error: aborting due to 8 previous errors; 19 warnings emitted +warning: naked functions cannot be inlined + --> $DIR/naked-functions.rs:177:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions cannot be inlined + --> $DIR/naked-functions.rs:185:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions cannot be inlined + --> $DIR/naked-functions.rs:193:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions cannot be inlined + --> $DIR/naked-functions.rs:201:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions cannot be inlined + --> $DIR/naked-functions.rs:204:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +warning: naked functions cannot be inlined + --> $DIR/naked-functions.rs:207:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #32408 + +error: aborting due to 8 previous errors; 25 warnings emitted diff --git a/src/test/ui/parser/issue-87635.rs b/src/test/ui/parser/issue-87635.rs new file mode 100644 index 0000000000000..da74c1877b165 --- /dev/null +++ b/src/test/ui/parser/issue-87635.rs @@ -0,0 +1,9 @@ +struct Foo {} + +impl Foo { + pub fn bar() + //~^ ERROR: expected `;`, found `}` + //~| ERROR: associated function in `impl` without body +} + +fn main() {} diff --git a/src/test/ui/parser/issue-87635.stderr b/src/test/ui/parser/issue-87635.stderr new file mode 100644 index 0000000000000..920a9f937dd6b --- /dev/null +++ b/src/test/ui/parser/issue-87635.stderr @@ -0,0 +1,19 @@ +error: expected `;`, found `}` + --> $DIR/issue-87635.rs:4:17 + | +LL | pub fn bar() + | ^ help: add `;` here +... +LL | } + | - unexpected token + +error: associated function in `impl` without body + --> $DIR/issue-87635.rs:4:5 + | +LL | pub fn bar() + | ^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/simd/simd-generics.rs b/src/test/ui/simd/simd-generics.rs index 50a4bfd9f518a..fa9d35ee4df85 100644 --- a/src/test/ui/simd/simd-generics.rs +++ b/src/test/ui/simd/simd-generics.rs @@ -10,7 +10,15 @@ struct f32x4(f32, f32, f32, f32); #[repr(simd)] #[derive(Copy, Clone)] -struct S([f32; N]); +struct A([f32; N]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct B([T; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct C([T; N]); extern "platform-intrinsic" { @@ -29,7 +37,23 @@ impl ops::Add for f32x4 { } } -impl ops::Add for S<4> { +impl ops::Add for A<4> { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + unsafe { simd_add(self, rhs) } + } +} + +impl ops::Add for B { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + unsafe { simd_add(self, rhs) } + } +} + +impl ops::Add for C { type Output = Self; fn add(self, rhs: Self) -> Self { @@ -39,19 +63,23 @@ impl ops::Add for S<4> { pub fn main() { - let lr = f32x4(1.0f32, 2.0f32, 3.0f32, 4.0f32); + let x = [1.0f32, 2.0f32, 3.0f32, 4.0f32]; + let y = [2.0f32, 4.0f32, 6.0f32, 8.0f32]; // lame-o - let f32x4(x, y, z, w) = add(lr, lr); - assert_eq!(x, 2.0f32); - assert_eq!(y, 4.0f32); - assert_eq!(z, 6.0f32); - assert_eq!(w, 8.0f32); - - let lr2 = S::<4>([1.0f32, 2.0f32, 3.0f32, 4.0f32]); - let [x, y, z, w] = add(lr2, lr2).0; - assert_eq!(x, 2.0f32); - assert_eq!(y, 4.0f32); - assert_eq!(z, 6.0f32); - assert_eq!(w, 8.0f32); + let a = f32x4(1.0f32, 2.0f32, 3.0f32, 4.0f32); + let f32x4(a0, a1, a2, a3) = add(a, a); + assert_eq!(a0, 2.0f32); + assert_eq!(a1, 4.0f32); + assert_eq!(a2, 6.0f32); + assert_eq!(a3, 8.0f32); + + let a = A(x); + assert_eq!(add(a, a).0, y); + + let b = B(x); + assert_eq!(add(b, b).0, y); + + let c = C(x); + assert_eq!(add(c, c).0, y); } diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.rs b/src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.rs new file mode 100644 index 0000000000000..0bc73b155801e --- /dev/null +++ b/src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.rs @@ -0,0 +1,14 @@ +// build-fail + +#![feature(repr_simd)] + +struct E; + +// error-pattern:monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `E` + +#[repr(simd)] +struct S([T; 4]); + +fn main() { + let _v: Option> = None; +} diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.stderr b/src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.stderr new file mode 100644 index 0000000000000..9e8f06b824ccf --- /dev/null +++ b/src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `E` + +error: aborting due to previous error + diff --git a/src/test/ui/unsafe/issue-87414-query-cycle.rs b/src/test/ui/unsafe/issue-87414-query-cycle.rs new file mode 100644 index 0000000000000..99e40ba4b4c04 --- /dev/null +++ b/src/test/ui/unsafe/issue-87414-query-cycle.rs @@ -0,0 +1,15 @@ +// Regression test for #87414. + +// check-pass +// compile-flags: -Zthir-unsafeck + +fn bad() -> Box> { todo!() } + +fn foo() -> [(); { |x: u32| { x }; 4 }] { todo!() } +fn bar() { let _: [(); { |x: u32| { x }; 4 }]; } + +// This one should not cause any errors either: +unsafe fn unsf() {} +fn bad2() -> Box> { todo!() } + +fn main() {} diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 1e19b7b21d8bf..ab63a9e2dfa0b 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -54,6 +54,7 @@ static HOSTS: &[&str] = &[ static TARGETS: &[&str] = &[ "aarch64-apple-darwin", "aarch64-apple-ios", + "aarch64-apple-ios-sim", "aarch64-fuchsia", "aarch64-linux-android", "aarch64-pc-windows-msvc",