about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-23 03:31:20 +0000
committerbors <bors@rust-lang.org>2022-03-23 03:31:20 +0000
commit7b0bf9efc939341b48c6e9a335dee8a280085100 (patch)
tree8daa45d4c70bfbd9213d6a04908ff8eb43f130df
parent2b50739b4978936750a0c8de404ff184e49114f9 (diff)
parent2f24923ab3f38e33a2ad98618852e0089d63ba7d (diff)
Auto merge of #95223 - Dylan-DPC:rollup-idpb7ka, r=Dylan-DPC
Rollup of 6 pull requests

Successful merges:

 - #91608 (Fold aarch64 feature +fp into +neon)
 - #92955 (add perf side effect docs to `Iterator::cloned()`)
 - #94713 (Add u16::is_utf16_surrogate)
 - #95212 (Replace `this.clone()` with `this.create_snapshot_for_diagnostic()`)
 - #95219 (Modernize `alloc-no-oom-handling` test)
 - #95222 (interpret/validity: improve clarity)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs5
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs4
-rw-r--r--compiler/rustc_target/src/asm/aarch64.rs2
-rw-r--r--library/core/src/char/decode.rs4
-rw-r--r--library/core/src/iter/traits/iterator.rs16
-rw-r--r--library/core/src/lib.rs4
-rw-r--r--library/core/src/num/mod.rs25
-rw-r--r--library/std/tests/run-time-detect.rs1
-rw-r--r--src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile2
-rw-r--r--src/test/run-make-fulldeps/simd-ffi/Makefile2
-rw-r--r--src/test/ui/asm/aarch64/bad-reg.rs2
-rw-r--r--src/test/ui/target-feature/aarch64-neon-works.rs23
-rw-r--r--src/test/ui/target-feature/feature-hierarchy.rs58
-rw-r--r--src/test/ui/target-feature/no-llvm-leaks.rs64
16 files changed, 206 insertions, 21 deletions
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 3ce594b945a..abcdb81c0e2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -187,7 +187,6 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]
         ("x86", "avx512vaes") => smallvec!["vaes"],
         ("x86", "avx512gfni") => smallvec!["gfni"],
         ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
-        ("aarch64", "fp") => smallvec!["fp-armv8"],
         ("aarch64", "rcpc2") => smallvec!["rcpc-immo"],
         ("aarch64", "dpb") => smallvec!["ccpp"],
         ("aarch64", "dpb2") => smallvec!["ccdp"],
@@ -230,6 +229,8 @@ pub fn check_tied_features(
     None
 }
 
+// Used to generate cfg variables and apply features
+// Must express features in the way Rust understands them
 pub fn target_features(sess: &Session) -> Vec<Symbol> {
     let target_machine = create_informational_target_machine(sess);
     let mut features: Vec<Symbol> =
@@ -239,13 +240,14 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
                 if sess.is_nightly_build() || gate.is_none() { Some(feature) } else { None }
             })
             .filter(|feature| {
+                // check that all features in a given smallvec are enabled
                 for llvm_feature in to_llvm_features(sess, feature) {
                     let cstr = SmallCStr::new(llvm_feature);
-                    if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
-                        return true;
+                    if !unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
+                        return false;
                     }
                 }
-                false
+                true
             })
             .map(|feature| Symbol::intern(feature))
             .collect();
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index dd214d96166..ba1e1862227 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -43,10 +43,8 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
 ];
 
 const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
-    // FEAT_AdvSimd
+    // FEAT_AdvSimd & FEAT_FP
     ("neon", None),
-    // FEAT_FP
-    ("fp", None),
     // FEAT_FP16
     ("fp16", None),
     // FEAT_SVE
@@ -143,7 +141,6 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
 ];
 
 const AARCH64_TIED_FEATURES: &[&[&str]] = &[
-    &["fp", "neon"],   // Silicon always has both, so avoid needless complications
     &["paca", "pacg"], // Together these represent `pauth` in LLVM
 ];
 
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 8fad5e63baf..8bdafa87623 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -432,9 +432,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
         if let Some(ref mut ref_tracking) = self.ref_tracking {
             // Proceed recursively even for ZST, no reason to skip them!
             // `!` is a ZST and we want to validate it.
-            // Skip validation entirely for some external statics
             if let Ok((alloc_id, _offset, _ptr)) = self.ecx.memory.ptr_try_get_alloc(place.ptr) {
-                // not a ZST
+                // Special handling for pointers to statics (irrespective of their type).
                 let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id);
                 if let Some(GlobalAlloc::Static(did)) = alloc_kind {
                     assert!(!self.ecx.tcx.is_thread_local_static(did));
@@ -469,7 +468,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 // We need to clone the path anyway, make sure it gets created
                 // with enough space for the additional `Deref`.
                 let mut new_path = Vec::with_capacity(path.len() + 1);
-                new_path.clone_from(path);
+                new_path.extend(path);
                 new_path.push(PathElem::Deref);
                 new_path
             });
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 1b9eeab0298..d625080dee4 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -118,7 +118,7 @@ impl<'a> Parser<'a> {
                         Some(this.parse_ty_param(attrs)?)
                     } else if this.token.can_begin_type() {
                         // Trying to write an associated type bound? (#26271)
-                        let snapshot = this.clone();
+                        let snapshot = this.create_snapshot_for_diagnostic();
                         match this.parse_ty_where_predicate() {
                             Ok(where_predicate) => {
                                 this.struct_span_err(
@@ -133,7 +133,7 @@ impl<'a> Parser<'a> {
                             Err(err) => {
                                 err.cancel();
                                 // FIXME - maybe we should overwrite 'self' outside of `collect_tokens`?
-                                *this = snapshot;
+                                this.restore_snapshot(snapshot);
                                 return Ok((None, TrailingToken::None));
                             }
                         }
diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs
index 7fb4dbdf2b1..fba8cc6ef8b 100644
--- a/compiler/rustc_target/src/asm/aarch64.rs
+++ b/compiler/rustc_target/src/asm/aarch64.rs
@@ -64,7 +64,7 @@ impl AArch64InlineAsmRegClass {
         match self {
             Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
             Self::vreg | Self::vreg_low16 => types! {
-                fp: I8, I16, I32, I64, F32, F64,
+                neon: I8, I16, I32, I64, F32, F64,
                     VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1),
                     VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
             },
diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs
index 8b9f979b573..794c9c13cc3 100644
--- a/library/core/src/char/decode.rs
+++ b/library/core/src/char/decode.rs
@@ -91,7 +91,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
             None => self.iter.next()?,
         };
 
-        if u < 0xD800 || 0xDFFF < u {
+        if !u.is_utf16_surrogate() {
             // SAFETY: not a surrogate
             Some(Ok(unsafe { from_u32_unchecked(u as u32) }))
         } else if u >= 0xDC00 {
@@ -125,7 +125,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
             // buf is empty, no additional elements from it.
             None => (0, 0),
             // `u` is a non surrogate, so it's always an additional character.
-            Some(u) if u < 0xD800 || 0xDFFF < u => (1, 1),
+            Some(u) if !u.is_utf16_surrogate() => (1, 1),
             // `u` is a leading surrogate (it can never be a trailing surrogate and
             // it's a surrogate due to the previous branch) and `self.iter` is empty.
             //
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index b62e8dfe1d6..53fbe4cbc42 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -3189,6 +3189,10 @@ pub trait Iterator {
     /// This is useful when you have an iterator over `&T`, but you need an
     /// iterator over `T`.
     ///
+    /// There is no guarantee whatsoever about the `clone` method actually
+    /// being called *or* optimized away. So code should not depend on
+    /// either.
+    ///
     /// [`clone`]: Clone::clone
     ///
     /// # Examples
@@ -3206,6 +3210,18 @@ pub trait Iterator {
     /// assert_eq!(v_cloned, vec![1, 2, 3]);
     /// assert_eq!(v_map, vec![1, 2, 3]);
     /// ```
+    ///
+    /// To get the best performance, try to clone late:
+    ///
+    /// ```
+    /// let a = [vec![0_u8, 1, 2], vec![3, 4], vec![23]];
+    /// // don't do this:
+    /// let slower: Vec<_> = a.iter().cloned().filter(|s| s.len() == 1).collect();
+    /// assert_eq!(&[vec![23]], &slower[..]);
+    /// // instead call `cloned` late
+    /// let faster: Vec<_> = a.iter().filter(|s| s.len() == 1).cloned().collect();
+    /// assert_eq!(&[vec![23]], &faster[..]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn cloned<'a, T: 'a>(self) -> Cloned<Self>
     where
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 0860e1bf4ca..1a85e2ef7b6 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -93,7 +93,7 @@
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
 //
-// Library features for const fns:
+// Library features:
 #![feature(const_align_offset)]
 #![feature(const_align_of_val)]
 #![feature(const_alloc_layout)]
@@ -146,6 +146,8 @@
 #![feature(ptr_metadata)]
 #![feature(slice_ptr_get)]
 #![feature(str_internals)]
+#![feature(utf16_extra)]
+#![feature(utf16_extra_const)]
 #![feature(variant_count)]
 #![feature(const_array_from_ref)]
 #![feature(const_slice_from_ref)]
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 07fd317e074..dca8ffa4e2c 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -820,6 +820,31 @@ impl u16 {
     uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
     widening_impl! { u16, u32, 16, unsigned }
+
+    /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(utf16_extra)]
+    ///
+    /// let low_non_surrogate = 0xA000u16;
+    /// let low_surrogate = 0xD800u16;
+    /// let high_surrogate = 0xDC00u16;
+    /// let high_non_surrogate = 0xE000u16;
+    ///
+    /// assert!(!low_non_surrogate.is_utf16_surrogate());
+    /// assert!(low_surrogate.is_utf16_surrogate());
+    /// assert!(high_surrogate.is_utf16_surrogate());
+    /// assert!(!high_non_surrogate.is_utf16_surrogate());
+    /// ```
+    #[must_use]
+    #[unstable(feature = "utf16_extra", issue = "94919")]
+    #[rustc_const_unstable(feature = "utf16_extra_const", issue = "94919")]
+    #[inline]
+    pub const fn is_utf16_surrogate(self) -> bool {
+        matches!(self, 0xD800..=0xDFFF)
+    }
 }
 
 #[lang = "u32"]
diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs
index 54873f5549b..a57a52d9bb0 100644
--- a/library/std/tests/run-time-detect.rs
+++ b/library/std/tests/run-time-detect.rs
@@ -29,7 +29,6 @@ fn aarch64_linux() {
     println!("neon: {}", is_aarch64_feature_detected!("neon"));
     println!("asimd: {}", is_aarch64_feature_detected!("asimd"));
     println!("pmull: {}", is_aarch64_feature_detected!("pmull"));
-    println!("fp: {}", is_aarch64_feature_detected!("fp"));
     println!("fp16: {}", is_aarch64_feature_detected!("fp16"));
     println!("sve: {}", is_aarch64_feature_detected!("sve"));
     println!("crc: {}", is_aarch64_feature_detected!("crc"));
diff --git a/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile b/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile
index c68ae40eb94..6e25eb7e459 100644
--- a/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile
+++ b/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile
@@ -1,4 +1,4 @@
 -include ../tools.mk
 
 all:
-	$(RUSTC) --edition=2018 --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg feature=\"external_crate\" --cfg no_global_oom_handling
+	$(RUSTC) --edition=2021 --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg no_global_oom_handling
diff --git a/src/test/run-make-fulldeps/simd-ffi/Makefile b/src/test/run-make-fulldeps/simd-ffi/Makefile
index 38f2fcd18c5..e9c974a0137 100644
--- a/src/test/run-make-fulldeps/simd-ffi/Makefile
+++ b/src/test/run-make-fulldeps/simd-ffi/Makefile
@@ -41,7 +41,7 @@ define MK_TARGETS
 # now.
 $(1): simd.rs
 	$$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs \
-                -C target-feature='+fp,+neon,+sse2' -C extra-filename=-$(1)
+                -C target-feature='+neon,+sse2' -C extra-filename=-$(1)
 endef
 
 $(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx))))
diff --git a/src/test/ui/asm/aarch64/bad-reg.rs b/src/test/ui/asm/aarch64/bad-reg.rs
index 8619b3960a6..1a314101916 100644
--- a/src/test/ui/asm/aarch64/bad-reg.rs
+++ b/src/test/ui/asm/aarch64/bad-reg.rs
@@ -1,5 +1,5 @@
 // only-aarch64
-// compile-flags: -C target-feature=+fp
+// compile-flags: -C target-feature=+neon
 
 #![feature(asm_const, asm_sym)]
 
diff --git a/src/test/ui/target-feature/aarch64-neon-works.rs b/src/test/ui/target-feature/aarch64-neon-works.rs
new file mode 100644
index 00000000000..3878806fd02
--- /dev/null
+++ b/src/test/ui/target-feature/aarch64-neon-works.rs
@@ -0,0 +1,23 @@
+// only-aarch64
+// run-pass
+#![allow(dead_code)]
+use std::arch::*;
+use std::arch::aarch64::*;
+
+// Smoke test to verify aarch64 code that enables NEON compiles.
+fn main() {
+    let _zero = if is_aarch64_feature_detected!("neon") {
+        unsafe {
+            let zeros = zero_vector();
+            vgetq_lane_u8::<1>(zeros)
+        }
+    } else {
+        0
+    };
+}
+
+
+#[target_feature(enable = "neon")]
+unsafe fn zero_vector() -> uint8x16_t {
+    vmovq_n_u8(0)
+}
diff --git a/src/test/ui/target-feature/feature-hierarchy.rs b/src/test/ui/target-feature/feature-hierarchy.rs
new file mode 100644
index 00000000000..5fbd5e8a28d
--- /dev/null
+++ b/src/test/ui/target-feature/feature-hierarchy.rs
@@ -0,0 +1,58 @@
+// revisions: aarch64-neon aarch64-sve2
+// [aarch64-neon] compile-flags: -Ctarget-feature=+neon --target=aarch64-unknown-linux-gnu
+// [aarch64-neon] needs-llvm-components: aarch64
+// [aarch64-sve2] compile-flags: -Ctarget-feature=-neon,+sve2 --target=aarch64-unknown-linux-gnu
+// [aarch64-sve2] needs-llvm-components: aarch64
+// build-pass
+#![no_core]
+#![crate_type = "rlib"]
+#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api)]
+#![stable(feature = "test", since = "1.0.0")]
+
+// Tests vetting "feature hierarchies" in the cases where we impose them.
+
+// Supporting minimal rust core code
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+impl Copy for bool {}
+
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "test", since = "1.0.0")]
+    fn unreachable() -> !;
+}
+
+#[rustc_builtin_macro]
+macro_rules! cfg {
+    ($($cfg:tt)*) => {};
+}
+
+// Test code
+const fn do_or_die(cond: bool) {
+    if cond {
+    } else {
+        unsafe { unreachable() }
+    }
+}
+
+macro_rules! assert {
+    ($x:expr $(,)?) => {
+        const _: () = do_or_die($x);
+    };
+}
+
+
+#[cfg(aarch64_neon)]
+fn check_neon_not_sve2() {
+    // This checks that a normal aarch64 target doesn't suddenly jump up the feature hierarchy.
+    assert!(cfg!(target_feature = "neon"));
+    assert!(cfg!(not(target_feature = "sve2")));
+}
+
+#[cfg(aarch64_sve2)]
+fn check_sve2_includes_neon() {
+    // This checks that aarch64's sve2 includes neon
+    assert!(cfg!(target_feature = "neon"));
+    assert!(cfg!(target_feature = "sve2"));
+}
diff --git a/src/test/ui/target-feature/no-llvm-leaks.rs b/src/test/ui/target-feature/no-llvm-leaks.rs
new file mode 100644
index 00000000000..5a71b2166c3
--- /dev/null
+++ b/src/test/ui/target-feature/no-llvm-leaks.rs
@@ -0,0 +1,64 @@
+// revisions: aarch64 x86-64
+// [aarch64] compile-flags: -Ctarget-feature=+neon,+fp16,+fhm --target=aarch64-unknown-linux-gnu
+// [aarch64] needs-llvm-components: aarch64
+// [x86-64] compile-flags: -Ctarget-feature=+sse4.2,+rdrand --target=x86_64-unknown-linux-gnu
+// [x86-64] needs-llvm-components: x86
+// build-pass
+#![no_core]
+#![crate_type = "rlib"]
+#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api)]
+#![stable(feature = "test", since = "1.0.0")]
+
+// Supporting minimal rust core code
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+impl Copy for bool {}
+
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "test", since = "1.0.0")]
+    fn unreachable() -> !;
+}
+
+#[rustc_builtin_macro]
+macro_rules! cfg {
+    ($($cfg:tt)*) => {};
+}
+
+// Test code
+const fn do_or_die(cond: bool) {
+    if cond {
+    } else {
+        unsafe { unreachable() }
+    }
+}
+
+macro_rules! assert {
+    ($x:expr $(,)?) => {
+        const _: () = do_or_die($x);
+    };
+}
+
+
+#[cfg(target_arch = "aarch64")]
+fn check_aarch64() {
+    // This checks that the rustc feature name is used, not the LLVM feature.
+    assert!(cfg!(target_feature = "neon"));
+    assert!(cfg!(not(target_feature = "fp-armv8")));
+    assert!(cfg!(target_feature = "fhm"));
+    assert!(cfg!(not(target_feature = "fp16fml")));
+    assert!(cfg!(target_feature = "fp16"));
+    assert!(cfg!(not(target_feature = "fullfp16")));
+}
+
+#[cfg(target_arch = "x86_64")]
+fn check_x86_64() {
+    // This checks that the rustc feature name is used, not the LLVM feature.
+    assert!(cfg!(target_feature = "rdrand"));
+    assert!(cfg!(not(target_feature = "rdrnd")));
+
+    // Likewise: We enable LLVM's crc32 feature with SSE4.2, but Rust says it's just SSE4.2
+    assert!(cfg!(target_feature = "sse4.2"));
+    assert!(cfg!(not(target_feature = "crc32")));
+}