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:
bors 2021-08-03 10:42:30 +00:00
commit 2939249f29
17 changed files with 298 additions and 27 deletions

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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 {

View File

@ -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(),

View File

@ -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) {

View File

@ -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.
///
/// ```

View File

@ -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.

View File

@ -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));
}

View File

@ -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

View File

@ -0,0 +1,9 @@
struct Foo {}
impl Foo {
pub fn bar()
//~^ ERROR: expected `;`, found `}`
//~| ERROR: associated function in `impl` without body
}
fn main() {}

View 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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View 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() {}

View File

@ -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",