mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 06:26:55 +00:00
Auto merge of #87725 - JohnTitor:rollup-2ywcpuk, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #87645 (Properly find owner of closure in THIR unsafeck) - #87646 (Fix a parser ICE on invalid `fn` body) - #87652 (Validate that naked functions are never inlined) - #87685 (Write docs for SyncOnceCell From and Default impl) - #87693 (Add `aarch64-apple-ios-sim` as a possible target to the manifest) - #87708 (Add convenience method for handling ipv4-mapped addresses by canonicalizing them) - #87711 (Correct typo) - #87716 (Allow generic SIMD array element type) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
2939249f29
@ -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
|
||||
|
@ -599,13 +599,10 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
|
||||
|
||||
// Closures are handled by their owner, if it has a body
|
||||
if tcx.is_closure(def.did.to_def_id()) {
|
||||
let owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
|
||||
let owner_hir_id = tcx.hir().local_def_id_to_hir_id(owner);
|
||||
|
||||
if tcx.hir().maybe_body_owned_by(owner_hir_id).is_some() {
|
||||
tcx.ensure().thir_check_unsafety(owner);
|
||||
return;
|
||||
}
|
||||
let hir = tcx.hir();
|
||||
let owner = hir.enclosing_body_owner(hir.local_def_id_to_hir_id(def.did));
|
||||
tcx.ensure().thir_check_unsafety(hir.local_def_id(owner));
|
||||
return;
|
||||
}
|
||||
|
||||
let (thir, expr) = tcx.thir_body(def);
|
||||
|
@ -1714,13 +1714,11 @@ impl<'a> 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)
|
||||
|
@ -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 {
|
||||
|
@ -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, 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>([T; N]) through, let monomorphization catch errors
|
||||
ty::Array(t, _clen)
|
||||
if matches!(
|
||||
t.kind(),
|
||||
|
@ -87,6 +87,19 @@ impl<T: UnwindSafe> UnwindSafe for SyncOnceCell<T> {}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T> Default for SyncOnceCell<T> {
|
||||
/// Creates a new empty cell.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::SyncOnceCell;
|
||||
///
|
||||
/// fn main() {
|
||||
/// assert_eq!(SyncOnceCell::<()>::new(), SyncOnceCell::default());
|
||||
/// }
|
||||
/// ```
|
||||
fn default() -> SyncOnceCell<T> {
|
||||
SyncOnceCell::new()
|
||||
}
|
||||
@ -118,6 +131,23 @@ impl<T: Clone> Clone for SyncOnceCell<T> {
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T> From<T> for SyncOnceCell<T> {
|
||||
/// 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) {
|
||||
|
@ -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.
|
||||
///
|
||||
/// ```
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
error: aborting due to 8 previous errors; 25 warnings emitted
|
||||
|
||||
|
9
src/test/ui/parser/issue-87635.rs
Normal file
9
src/test/ui/parser/issue-87635.rs
Normal file
@ -0,0 +1,9 @@
|
||||
struct Foo {}
|
||||
|
||||
impl Foo {
|
||||
pub fn bar()
|
||||
//~^ ERROR: expected `;`, found `}`
|
||||
//~| ERROR: associated function in `impl` without body
|
||||
}
|
||||
|
||||
fn main() {}
|
19
src/test/ui/parser/issue-87635.stderr
Normal file
19
src/test/ui/parser/issue-87635.stderr
Normal file
@ -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: `{ <body> }`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -10,7 +10,15 @@ struct f32x4(f32, f32, f32, f32);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct S<const N: usize>([f32; N]);
|
||||
struct A<const N: usize>([f32; N]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct B<T>([T; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct C<T, const N: usize>([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<f32> {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
unsafe { simd_add(self, rhs) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add for C<f32, 4> {
|
||||
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 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 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 = 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);
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
// build-fail
|
||||
|
||||
#![feature(repr_simd)]
|
||||
|
||||
struct E;
|
||||
|
||||
// error-pattern:monomorphising SIMD type `S<E>` with a non-primitive-scalar (integer/float/pointer) element type `E`
|
||||
|
||||
#[repr(simd)]
|
||||
struct S<T>([T; 4]);
|
||||
|
||||
fn main() {
|
||||
let _v: Option<S<E>> = None;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
error: monomorphising SIMD type `S<E>` with a non-primitive-scalar (integer/float/pointer) element type `E`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
15
src/test/ui/unsafe/issue-87414-query-cycle.rs
Normal file
15
src/test/ui/unsafe/issue-87414-query-cycle.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Regression test for #87414.
|
||||
|
||||
// check-pass
|
||||
// compile-flags: -Zthir-unsafeck
|
||||
|
||||
fn bad<T>() -> Box<dyn Iterator<Item = [(); { |x: u32| { x }; 4 }]>> { 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<T>() -> Box<dyn Iterator<Item = [(); { unsafe { || { unsf() } }; 4 }]>> { todo!() }
|
||||
|
||||
fn main() {}
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user