diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs index e3d941cad7a..71bcb8f090d 100644 --- a/compiler/rustc_apfloat/src/ieee.rs +++ b/compiler/rustc_apfloat/src/ieee.rs @@ -1511,11 +1511,16 @@ impl FloatConvert> for IeeeFloat { sig::set_bit(&mut r.sig, T::PRECISION - 1); } - // gcc forces the Quiet bit on, which means (float)(double)(float_sNan) - // does not give you back the same bits. This is dubious, and we - // don't currently do it. You're really supposed to get - // an invalid operation signal at runtime, but nobody does that. - status = Status::OK; + // Convert of sNaN creates qNaN and raises an exception (invalid op). + // This also guarantees that a sNaN does not become Inf on a truncation + // that loses all payload bits. + if self.is_signaling() { + // Quiet signaling NaN. + sig::set_bit(&mut r.sig, T::QNAN_BIT); + status = Status::INVALID_OP; + } else { + status = Status::OK; + } } else { *loses_info = false; status = Status::OK; diff --git a/compiler/rustc_apfloat/tests/ieee.rs b/compiler/rustc_apfloat/tests/ieee.rs index 2d8bb7d1e8e..63d925cce9a 100644 --- a/compiler/rustc_apfloat/tests/ieee.rs +++ b/compiler/rustc_apfloat/tests/ieee.rs @@ -566,6 +566,17 @@ fn fma() { } } +#[test] +fn issue_69532() { + let f = Double::from_bits(0x7FF0_0000_0000_0001u64 as u128); + let mut loses_info = false; + let sta = f.convert(&mut loses_info); + let r: Single = sta.value; + assert!(loses_info); + assert!(r.is_nan()); + assert_eq!(sta.status, Status::INVALID_OP); +} + #[test] fn min_num() { let f1 = Double::from_f64(1.0); @@ -1492,27 +1503,32 @@ fn convert() { assert_eq!(4294967295.0, test.to_f64()); assert!(!loses_info); - let test = Single::snan(None); - let x87_snan = X87DoubleExtended::snan(None); - let test: X87DoubleExtended = test.convert(&mut loses_info).value; - assert!(test.bitwise_eq(x87_snan)); - assert!(!loses_info); - let test = Single::qnan(None); let x87_qnan = X87DoubleExtended::qnan(None); let test: X87DoubleExtended = test.convert(&mut loses_info).value; assert!(test.bitwise_eq(x87_qnan)); assert!(!loses_info); - let test = X87DoubleExtended::snan(None); - let test: X87DoubleExtended = test.convert(&mut loses_info).value; - assert!(test.bitwise_eq(x87_snan)); + let test = Single::snan(None); + let sta = test.convert(&mut loses_info); + let test: X87DoubleExtended = sta.value; + assert!(test.is_nan()); + assert!(!test.is_signaling()); assert!(!loses_info); + assert_eq!(sta.status, Status::INVALID_OP); let test = X87DoubleExtended::qnan(None); let test: X87DoubleExtended = test.convert(&mut loses_info).value; assert!(test.bitwise_eq(x87_qnan)); assert!(!loses_info); + + let test = X87DoubleExtended::snan(None); + let sta = test.convert(&mut loses_info); + let test: X87DoubleExtended = sta.value; + assert!(test.is_nan()); + assert!(!test.is_signaling()); + assert!(!loses_info); + assert_eq!(sta.status, Status::INVALID_OP); } #[test] diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 73c34818446..a633ea5e5a9 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -349,17 +349,15 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: } pub fn provide(providers: &mut Providers) { + use rustc_codegen_ssa::target_features::{all_known_features, supported_target_features}; providers.supported_target_features = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // provide them all. - llvm_util::all_known_features().map(|(a, b)| (a.to_string(), b)).collect() + all_known_features().map(|(a, b)| (a.to_string(), b)).collect() } else { - llvm_util::supported_target_features(tcx.sess) - .iter() - .map(|&(a, b)| (a.to_string(), b)) - .collect() + supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect() } }; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 7f5b09eac4f..e76e86f5651 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -793,14 +793,18 @@ fn generic_simd_intrinsic( require_simd!(arg_tys[1], "argument"); let v_len = arg_tys[1].simd_size(tcx); require!( - m_len == v_len, + // Allow masks for vectors with fewer than 8 elements to be + // represented with a u8 or i8. + m_len == v_len || (m_len == 8 && v_len < 8), "mismatched lengths: mask length `{}` != other vector length `{}`", m_len, v_len ); let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, m_len); - let m_i1s = bx.bitcast(args[0].immediate(), i1xn); + let im = bx.type_ix(v_len); + let i1xn = bx.type_vector(i1, v_len); + let m_im = bx.trunc(args[0].immediate(), im); + let m_i1s = bx.bitcast(m_im, i1xn); return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 900f2df383a..d42020047fd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,12 +1,12 @@ use crate::back::write::create_informational_target_machine; use crate::llvm; use libc::c_int; +use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxHashSet; use rustc_feature::UnstableFeatures; use rustc_middle::bug; use rustc_session::config::PrintRequest; use rustc_session::Session; -use rustc_span::symbol::sym; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy}; use std::ffi::CString; @@ -139,140 +139,6 @@ pub fn time_trace_profiler_finish(file_name: &str) { // WARNING: the features after applying `to_llvm_feature` must be known // to LLVM or the feature detection code will walk past the end of the feature // array, leading to crashes. - -const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("aclass", Some(sym::arm_target_feature)), - ("mclass", Some(sym::arm_target_feature)), - ("rclass", Some(sym::arm_target_feature)), - ("dsp", Some(sym::arm_target_feature)), - ("neon", Some(sym::arm_target_feature)), - ("crc", Some(sym::arm_target_feature)), - ("crypto", Some(sym::arm_target_feature)), - ("v5te", Some(sym::arm_target_feature)), - ("v6", Some(sym::arm_target_feature)), - ("v6k", Some(sym::arm_target_feature)), - ("v6t2", Some(sym::arm_target_feature)), - ("v7", Some(sym::arm_target_feature)), - ("v8", Some(sym::arm_target_feature)), - ("vfp2", Some(sym::arm_target_feature)), - ("vfp3", Some(sym::arm_target_feature)), - ("vfp4", Some(sym::arm_target_feature)), - // This is needed for inline assembly, but shouldn't be stabilized as-is - // since it should be enabled per-function using #[instruction_set], not - // #[target_feature]. - ("thumb-mode", Some(sym::arm_target_feature)), -]; - -const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("fp", Some(sym::aarch64_target_feature)), - ("neon", Some(sym::aarch64_target_feature)), - ("sve", Some(sym::aarch64_target_feature)), - ("crc", Some(sym::aarch64_target_feature)), - ("crypto", Some(sym::aarch64_target_feature)), - ("ras", Some(sym::aarch64_target_feature)), - ("lse", Some(sym::aarch64_target_feature)), - ("rdm", Some(sym::aarch64_target_feature)), - ("fp16", Some(sym::aarch64_target_feature)), - ("rcpc", Some(sym::aarch64_target_feature)), - ("dotprod", Some(sym::aarch64_target_feature)), - ("tme", Some(sym::aarch64_target_feature)), - ("v8.1a", Some(sym::aarch64_target_feature)), - ("v8.2a", Some(sym::aarch64_target_feature)), - ("v8.3a", Some(sym::aarch64_target_feature)), -]; - -const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("adx", Some(sym::adx_target_feature)), - ("aes", None), - ("avx", None), - ("avx2", None), - ("avx512bw", Some(sym::avx512_target_feature)), - ("avx512cd", Some(sym::avx512_target_feature)), - ("avx512dq", Some(sym::avx512_target_feature)), - ("avx512er", Some(sym::avx512_target_feature)), - ("avx512f", Some(sym::avx512_target_feature)), - ("avx512ifma", Some(sym::avx512_target_feature)), - ("avx512pf", Some(sym::avx512_target_feature)), - ("avx512vbmi", Some(sym::avx512_target_feature)), - ("avx512vl", Some(sym::avx512_target_feature)), - ("avx512vpopcntdq", Some(sym::avx512_target_feature)), - ("bmi1", None), - ("bmi2", None), - ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)), - ("f16c", Some(sym::f16c_target_feature)), - ("fma", None), - ("fxsr", None), - ("lzcnt", None), - ("movbe", Some(sym::movbe_target_feature)), - ("pclmulqdq", None), - ("popcnt", None), - ("rdrand", None), - ("rdseed", None), - ("rtm", Some(sym::rtm_target_feature)), - ("sha", None), - ("sse", None), - ("sse2", None), - ("sse3", None), - ("sse4.1", None), - ("sse4.2", None), - ("sse4a", Some(sym::sse4a_target_feature)), - ("ssse3", None), - ("tbm", Some(sym::tbm_target_feature)), - ("xsave", None), - ("xsavec", None), - ("xsaveopt", None), - ("xsaves", None), -]; - -const HEXAGON_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("hvx", Some(sym::hexagon_target_feature)), - ("hvx-length128b", Some(sym::hexagon_target_feature)), -]; - -const POWERPC_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("altivec", Some(sym::powerpc_target_feature)), - ("power8-altivec", Some(sym::powerpc_target_feature)), - ("power9-altivec", Some(sym::powerpc_target_feature)), - ("power8-vector", Some(sym::powerpc_target_feature)), - ("power9-vector", Some(sym::powerpc_target_feature)), - ("vsx", Some(sym::powerpc_target_feature)), -]; - -const MIPS_ALLOWED_FEATURES: &[(&str, Option)] = - &[("fp64", Some(sym::mips_target_feature)), ("msa", Some(sym::mips_target_feature))]; - -const RISCV_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("m", Some(sym::riscv_target_feature)), - ("a", Some(sym::riscv_target_feature)), - ("c", Some(sym::riscv_target_feature)), - ("f", Some(sym::riscv_target_feature)), - ("d", Some(sym::riscv_target_feature)), - ("e", Some(sym::riscv_target_feature)), -]; - -const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("simd128", Some(sym::wasm_target_feature)), - ("atomics", Some(sym::wasm_target_feature)), - ("nontrapping-fptoint", Some(sym::wasm_target_feature)), -]; - -/// When rustdoc is running, provide a list of all known features so that all their respective -/// primitives may be documented. -/// -/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! -pub fn all_known_features() -> impl Iterator)> { - std::iter::empty() - .chain(ARM_ALLOWED_FEATURES.iter()) - .chain(AARCH64_ALLOWED_FEATURES.iter()) - .chain(X86_ALLOWED_FEATURES.iter()) - .chain(HEXAGON_ALLOWED_FEATURES.iter()) - .chain(POWERPC_ALLOWED_FEATURES.iter()) - .chain(MIPS_ALLOWED_FEATURES.iter()) - .chain(RISCV_ALLOWED_FEATURES.iter()) - .chain(WASM_ALLOWED_FEATURES.iter()) - .cloned() -} - pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { let arch = if sess.target.target.arch == "x86_64" { "x86" } else { &*sess.target.target.arch }; match (arch, s) { @@ -306,20 +172,6 @@ pub fn target_features(sess: &Session) -> Vec { .collect() } -pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option)] { - match &*sess.target.target.arch { - "arm" => ARM_ALLOWED_FEATURES, - "aarch64" => AARCH64_ALLOWED_FEATURES, - "x86" | "x86_64" => X86_ALLOWED_FEATURES, - "hexagon" => HEXAGON_ALLOWED_FEATURES, - "mips" | "mips64" => MIPS_ALLOWED_FEATURES, - "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, - "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, - "wasm32" => WASM_ALLOWED_FEATURES, - _ => &[], - } -} - pub fn print_version() { // Can be called without initializing LLVM unsafe { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index d4f3bf37797..e34371ef59a 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -42,6 +42,7 @@ pub mod glue; pub mod meth; pub mod mir; pub mod mono_item; +pub mod target_features; pub mod traits; pub struct ModuleCodegen { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs new file mode 100644 index 00000000000..4c61e21901b --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -0,0 +1,150 @@ +use rustc_session::Session; +use rustc_span::symbol::sym; +use rustc_span::symbol::Symbol; + +const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ + ("aclass", Some(sym::arm_target_feature)), + ("mclass", Some(sym::arm_target_feature)), + ("rclass", Some(sym::arm_target_feature)), + ("dsp", Some(sym::arm_target_feature)), + ("neon", Some(sym::arm_target_feature)), + ("crc", Some(sym::arm_target_feature)), + ("crypto", Some(sym::arm_target_feature)), + ("v5te", Some(sym::arm_target_feature)), + ("v6", Some(sym::arm_target_feature)), + ("v6k", Some(sym::arm_target_feature)), + ("v6t2", Some(sym::arm_target_feature)), + ("v7", Some(sym::arm_target_feature)), + ("v8", Some(sym::arm_target_feature)), + ("vfp2", Some(sym::arm_target_feature)), + ("vfp3", Some(sym::arm_target_feature)), + ("vfp4", Some(sym::arm_target_feature)), + // This is needed for inline assembly, but shouldn't be stabilized as-is + // since it should be enabled per-function using #[instruction_set], not + // #[target_feature]. + ("thumb-mode", Some(sym::arm_target_feature)), +]; + +const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ + ("fp", Some(sym::aarch64_target_feature)), + ("neon", Some(sym::aarch64_target_feature)), + ("sve", Some(sym::aarch64_target_feature)), + ("crc", Some(sym::aarch64_target_feature)), + ("crypto", Some(sym::aarch64_target_feature)), + ("ras", Some(sym::aarch64_target_feature)), + ("lse", Some(sym::aarch64_target_feature)), + ("rdm", Some(sym::aarch64_target_feature)), + ("fp16", Some(sym::aarch64_target_feature)), + ("rcpc", Some(sym::aarch64_target_feature)), + ("dotprod", Some(sym::aarch64_target_feature)), + ("tme", Some(sym::aarch64_target_feature)), + ("v8.1a", Some(sym::aarch64_target_feature)), + ("v8.2a", Some(sym::aarch64_target_feature)), + ("v8.3a", Some(sym::aarch64_target_feature)), +]; + +const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ + ("adx", Some(sym::adx_target_feature)), + ("aes", None), + ("avx", None), + ("avx2", None), + ("avx512bw", Some(sym::avx512_target_feature)), + ("avx512cd", Some(sym::avx512_target_feature)), + ("avx512dq", Some(sym::avx512_target_feature)), + ("avx512er", Some(sym::avx512_target_feature)), + ("avx512f", Some(sym::avx512_target_feature)), + ("avx512ifma", Some(sym::avx512_target_feature)), + ("avx512pf", Some(sym::avx512_target_feature)), + ("avx512vbmi", Some(sym::avx512_target_feature)), + ("avx512vl", Some(sym::avx512_target_feature)), + ("avx512vpopcntdq", Some(sym::avx512_target_feature)), + ("bmi1", None), + ("bmi2", None), + ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)), + ("f16c", Some(sym::f16c_target_feature)), + ("fma", None), + ("fxsr", None), + ("lzcnt", None), + ("movbe", Some(sym::movbe_target_feature)), + ("pclmulqdq", None), + ("popcnt", None), + ("rdrand", None), + ("rdseed", None), + ("rtm", Some(sym::rtm_target_feature)), + ("sha", None), + ("sse", None), + ("sse2", None), + ("sse3", None), + ("sse4.1", None), + ("sse4.2", None), + ("sse4a", Some(sym::sse4a_target_feature)), + ("ssse3", None), + ("tbm", Some(sym::tbm_target_feature)), + ("xsave", None), + ("xsavec", None), + ("xsaveopt", None), + ("xsaves", None), +]; + +const HEXAGON_ALLOWED_FEATURES: &[(&str, Option)] = &[ + ("hvx", Some(sym::hexagon_target_feature)), + ("hvx-length128b", Some(sym::hexagon_target_feature)), +]; + +const POWERPC_ALLOWED_FEATURES: &[(&str, Option)] = &[ + ("altivec", Some(sym::powerpc_target_feature)), + ("power8-altivec", Some(sym::powerpc_target_feature)), + ("power9-altivec", Some(sym::powerpc_target_feature)), + ("power8-vector", Some(sym::powerpc_target_feature)), + ("power9-vector", Some(sym::powerpc_target_feature)), + ("vsx", Some(sym::powerpc_target_feature)), +]; + +const MIPS_ALLOWED_FEATURES: &[(&str, Option)] = + &[("fp64", Some(sym::mips_target_feature)), ("msa", Some(sym::mips_target_feature))]; + +const RISCV_ALLOWED_FEATURES: &[(&str, Option)] = &[ + ("m", Some(sym::riscv_target_feature)), + ("a", Some(sym::riscv_target_feature)), + ("c", Some(sym::riscv_target_feature)), + ("f", Some(sym::riscv_target_feature)), + ("d", Some(sym::riscv_target_feature)), + ("e", Some(sym::riscv_target_feature)), +]; + +const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ + ("simd128", Some(sym::wasm_target_feature)), + ("atomics", Some(sym::wasm_target_feature)), + ("nontrapping-fptoint", Some(sym::wasm_target_feature)), +]; + +/// When rustdoc is running, provide a list of all known features so that all their respective +/// primitives may be documented. +/// +/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! +pub fn all_known_features() -> impl Iterator)> { + std::iter::empty() + .chain(ARM_ALLOWED_FEATURES.iter()) + .chain(AARCH64_ALLOWED_FEATURES.iter()) + .chain(X86_ALLOWED_FEATURES.iter()) + .chain(HEXAGON_ALLOWED_FEATURES.iter()) + .chain(POWERPC_ALLOWED_FEATURES.iter()) + .chain(MIPS_ALLOWED_FEATURES.iter()) + .chain(RISCV_ALLOWED_FEATURES.iter()) + .chain(WASM_ALLOWED_FEATURES.iter()) + .cloned() +} + +pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option)] { + match &*sess.target.target.arch { + "arm" => ARM_ALLOWED_FEATURES, + "aarch64" => AARCH64_ALLOWED_FEATURES, + "x86" | "x86_64" => X86_ALLOWED_FEATURES, + "hexagon" => HEXAGON_ALLOWED_FEATURES, + "mips" | "mips64" => MIPS_ALLOWED_FEATURES, + "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, + "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, + "wasm32" => WASM_ALLOWED_FEATURES, + _ => &[], + } +} diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir/src/transform/nrvo.rs index 1ffb5a87c47..3673b6a4aa2 100644 --- a/compiler/rustc_mir/src/transform/nrvo.rs +++ b/compiler/rustc_mir/src/transform/nrvo.rs @@ -36,12 +36,6 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace { return; } - if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { - // The `DestinationPropagation` pass runs at level 2, so this pass is redundant (and - // fails some asserts). - return; - } - let returned_local = match local_eligible_for_nrvo(body) { Some(l) => l, None => { diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 8018514fa17..118e173bb16 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1,12 +1,10 @@ +use super::super::{navigate::Position, node, DeterministicRng}; +use super::Entry::{Occupied, Vacant}; +use super::*; use crate::boxed::Box; -use crate::collections::btree::navigate::Position; -use crate::collections::btree::node; -use crate::collections::btree_map::Entry::{Occupied, Vacant}; -use crate::collections::BTreeMap; use crate::fmt::Debug; use crate::rc::Rc; -use crate::string::String; -use crate::string::ToString; +use crate::string::{String, ToString}; use crate::vec::Vec; use std::convert::TryFrom; use std::iter::FromIterator; @@ -16,19 +14,17 @@ use std::ops::RangeBounds; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::sync::atomic::{AtomicUsize, Ordering}; -use super::super::DeterministicRng; - // Capacity of a tree with a single level, -// i.e. a tree who's root is a leaf node at height 0. +// i.e., a tree who's root is a leaf node at height 0. const NODE_CAPACITY: usize = node::CAPACITY; // Minimum number of elements to insert, to guarantee a tree with 2 levels, -// i.e. a tree who's root is an internal node at height 1, with edges to leaf nodes. +// i.e., a tree who's root is an internal node at height 1, with edges to leaf nodes. // It's not the minimum size: removing an element from such a tree does not always reduce height. const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1; // Minimum number of elements to insert in ascending order, to guarantee a tree with 3 levels, -// i.e. a tree who's root is an internal node at height 2, with edges to more internal nodes. +// i.e., a tree who's root is an internal node at height 2, with edges to more internal nodes. // It's not the minimum size: removing an element from such a tree does not always reduce height. const MIN_INSERTS_HEIGHT_2: usize = 89; @@ -1386,44 +1382,65 @@ fn test_clone_from() { } } -#[test] #[allow(dead_code)] fn test_variance() { - use std::collections::btree_map::{IntoIter, Iter, Keys, Range, Values}; - fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> { v } fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> { v } + fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> { v } fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> { v } + fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> { v } fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> { v } + + fn into_keys_key<'new>(v: IntoKeys<&'static str, ()>) -> IntoKeys<&'new str, ()> { + v + } + fn into_keys_val<'new>(v: IntoKeys<(), &'static str>) -> IntoKeys<(), &'new str> { + v + } + + fn into_values_key<'new>(v: IntoValues<&'static str, ()>) -> IntoValues<&'new str, ()> { + v + } + fn into_values_val<'new>(v: IntoValues<(), &'static str>) -> IntoValues<(), &'new str> { + v + } + fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> { v } fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> { v } - fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> { + + fn keys_key<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> { v } - fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> { + fn keys_val<'a, 'new>(v: Keys<'a, (), &'static str>) -> Keys<'a, (), &'new str> { + v + } + + fn values_key<'a, 'new>(v: Values<'a, &'static str, ()>) -> Values<'a, &'new str, ()> { + v + } + fn values_val<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> { v } } -#[test] #[allow(dead_code)] fn test_sync() { fn map(v: &BTreeMap) -> impl Sync + '_ { @@ -1493,7 +1510,6 @@ fn test_sync() { } } -#[test] #[allow(dead_code)] fn test_send() { fn map(v: BTreeMap) -> impl Send { @@ -1520,7 +1536,7 @@ fn test_send() { v.iter() } - fn iter_mut(v: &mut BTreeMap) -> impl Send + '_ { + fn iter_mut(v: &mut BTreeMap) -> impl Send + '_ { v.iter_mut() } @@ -1532,7 +1548,7 @@ fn test_send() { v.values() } - fn values_mut(v: &mut BTreeMap) -> impl Send + '_ { + fn values_mut(v: &mut BTreeMap) -> impl Send + '_ { v.values_mut() } @@ -1540,7 +1556,7 @@ fn test_send() { v.range(..) } - fn range_mut(v: &mut BTreeMap) -> impl Send + '_ { + fn range_mut(v: &mut BTreeMap) -> impl Send + '_ { v.range_mut(..) } diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index f4e957e22fe..92674357282 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -1,11 +1,10 @@ -use crate::collections::BTreeSet; +use super::super::DeterministicRng; +use super::*; use crate::vec::Vec; use std::iter::FromIterator; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::sync::atomic::{AtomicU32, Ordering}; -use super::super::DeterministicRng; - #[test] fn test_clone_eq() { let mut m = BTreeSet::new(); @@ -528,11 +527,8 @@ fn test_recovery() { assert_eq!(s.iter().next(), None); } -#[test] #[allow(dead_code)] fn test_variance() { - use std::collections::btree_set::{IntoIter, Iter, Range}; - fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> { v } @@ -545,6 +541,85 @@ fn test_variance() { fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> { v } + // not applied to Difference, Intersection, SymmetricDifference, Union +} + +#[allow(dead_code)] +fn test_sync() { + fn set(v: &BTreeSet) -> impl Sync + '_ { + v + } + + fn iter(v: &BTreeSet) -> impl Sync + '_ { + v.iter() + } + + fn into_iter(v: BTreeSet) -> impl Sync { + v.into_iter() + } + + fn range(v: &BTreeSet) -> impl Sync + '_ { + v.range(..) + } + + fn drain_filter(v: &mut BTreeSet) -> impl Sync + '_ { + v.drain_filter(|_| false) + } + + fn difference(v: &BTreeSet) -> impl Sync + '_ { + v.difference(&v) + } + + fn intersection(v: &BTreeSet) -> impl Sync + '_ { + v.intersection(&v) + } + + fn symmetric_difference(v: &BTreeSet) -> impl Sync + '_ { + v.symmetric_difference(&v) + } + + fn union(v: &BTreeSet) -> impl Sync + '_ { + v.union(&v) + } +} + +#[allow(dead_code)] +fn test_send() { + fn set(v: BTreeSet) -> impl Send { + v + } + + fn iter(v: &BTreeSet) -> impl Send + '_ { + v.iter() + } + + fn into_iter(v: BTreeSet) -> impl Send { + v.into_iter() + } + + fn range(v: &BTreeSet) -> impl Send + '_ { + v.range(..) + } + + fn drain_filter(v: &mut BTreeSet) -> impl Send + '_ { + v.drain_filter(|_| false) + } + + fn difference(v: &BTreeSet) -> impl Send + '_ { + v.difference(&v) + } + + fn intersection(v: &BTreeSet) -> impl Send + '_ { + v.intersection(&v) + } + + fn symmetric_difference(v: &BTreeSet) -> impl Send + '_ { + v.symmetric_difference(&v) + } + + fn union(v: &BTreeSet) -> impl Send + '_ { + v.union(&v) + } } #[test] diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index f12cefffbf6..114707b639b 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -554,8 +554,8 @@ impl HashMap { /// a.clear(); /// assert!(a.is_empty()); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn clear(&mut self) { self.base.clear(); } @@ -746,8 +746,8 @@ where /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); /// assert_eq!(map.get_key_value(&2), None); /// ``` - #[stable(feature = "map_get_key_value", since = "1.40.0")] #[inline] + #[stable(feature = "map_get_key_value", since = "1.40.0")] pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> where K: Borrow, @@ -772,8 +772,8 @@ where /// assert_eq!(map.contains_key(&1), true); /// assert_eq!(map.contains_key(&2), false); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn contains_key(&self, k: &Q) -> bool where K: Borrow, @@ -800,8 +800,8 @@ where /// } /// assert_eq!(map[&1], "b"); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> where K: Borrow, @@ -834,8 +834,8 @@ where /// assert_eq!(map.insert(37, "c"), Some("b")); /// assert_eq!(map[&37], "c"); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, k: K, v: V) -> Option { self.base.insert(k, v) } @@ -857,8 +857,8 @@ where /// assert_eq!(map.remove(&1), Some("a")); /// assert_eq!(map.remove(&1), None); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, k: &Q) -> Option where K: Borrow, @@ -886,8 +886,8 @@ where /// assert_eq!(map.remove(&1), None); /// # } /// ``` - #[stable(feature = "hash_map_remove_entry", since = "1.27.0")] #[inline] + #[stable(feature = "hash_map_remove_entry", since = "1.27.0")] pub fn remove_entry(&mut self, k: &Q) -> Option<(K, V)> where K: Borrow, @@ -909,8 +909,8 @@ where /// map.retain(|&k, _| k % 2 == 0); /// assert_eq!(map.len(), 4); /// ``` - #[stable(feature = "retain_hash_collection", since = "1.18.0")] #[inline] + #[stable(feature = "retain_hash_collection", since = "1.18.0")] pub fn retain(&mut self, f: F) where F: FnMut(&K, &mut V) -> bool, @@ -1647,7 +1647,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { self.base.get() } - /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry /// with a lifetime bound to the map itself. #[inline] #[unstable(feature = "hash_raw_entry", issue = "56167")] @@ -1676,7 +1676,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { self.base.get_key_value_mut() } - /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry + /// Converts the `OccupiedEntry` into a mutable reference to the key and value in the entry /// with a lifetime bound to the map itself. #[inline] #[unstable(feature = "hash_raw_entry", issue = "56167")] @@ -1714,7 +1714,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { } impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { - /// Sets the value of the entry with the VacantEntry's key, + /// Sets the value of the entry with the `VacantEntry`'s key, /// and returns a mutable reference to it. #[inline] #[unstable(feature = "hash_raw_entry", issue = "56167")] @@ -2173,7 +2173,6 @@ where } impl<'a, K, V> Entry<'a, K, V> { - #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. /// @@ -2191,6 +2190,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], 6); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert(self, default: V) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), @@ -2198,7 +2198,6 @@ impl<'a, K, V> Entry<'a, K, V> { } } - #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the result of the default function if empty, /// and returns a mutable reference to the value in the entry. /// @@ -2215,6 +2214,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], "hoho".to_string()); /// ``` #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), @@ -2222,7 +2222,6 @@ impl<'a, K, V> Entry<'a, K, V> { } } - #[unstable(feature = "or_insert_with_key", issue = "71024")] /// Ensures a value is in the entry by inserting, if empty, the result of the default function, /// which takes the key as its argument, and returns a mutable reference to the value in the /// entry. @@ -2240,6 +2239,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], 9); /// ``` #[inline] + #[unstable(feature = "or_insert_with_key", issue = "71024")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), @@ -2304,7 +2304,7 @@ impl<'a, K, V> Entry<'a, K, V> { } } - /// Sets the value of the entry, and returns an OccupiedEntry. + /// Sets the value of the entry, and returns an `OccupiedEntry`. /// /// # Examples /// @@ -2331,7 +2331,6 @@ impl<'a, K, V> Entry<'a, K, V> { } impl<'a, K, V: Default> Entry<'a, K, V> { - #[stable(feature = "entry_or_default", since = "1.28.0")] /// Ensures a value is in the entry by inserting the default value if empty, /// and returns a mutable reference to the value in the entry. /// @@ -2348,6 +2347,7 @@ impl<'a, K, V: Default> Entry<'a, K, V> { /// # } /// ``` #[inline] + #[stable(feature = "entry_or_default", since = "1.28.0")] pub fn or_default(self) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), @@ -2452,7 +2452,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { self.base.get_mut() } - /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry /// with a lifetime bound to the map itself. /// /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`]. @@ -2624,7 +2624,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { self.base.into_key() } - /// Sets the value of the entry with the VacantEntry's key, + /// Sets the value of the entry with the `VacantEntry`'s key, /// and returns a mutable reference to it. /// /// # Examples @@ -2646,8 +2646,8 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { self.base.insert(value) } - /// Sets the value of the entry with the VacantEntry's key, - /// and returns an OccupiedEntry. + /// Sets the value of the entry with the `VacantEntry`'s key, + /// and returns an `OccupiedEntry`. /// /// # Examples /// diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 8fbfb04bac3..d70446d2574 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -370,32 +370,22 @@ impl> NestedAttributesExt for I { /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are /// kept separate because of issue #42760. #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum DocFragment { - /// A doc fragment created from a `///` or `//!` doc comment. - SugaredDoc(usize, rustc_span::Span, String), - /// A doc fragment created from a "raw" `#[doc=""]` attribute. - RawDoc(usize, rustc_span::Span, String), - /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the - /// given filename and the file contents. - Include(usize, rustc_span::Span, String, String), +pub struct DocFragment { + pub line: usize, + pub span: rustc_span::Span, + pub doc: String, + pub kind: DocFragmentKind, } -impl DocFragment { - pub fn as_str(&self) -> &str { - match *self { - DocFragment::SugaredDoc(_, _, ref s) => &s[..], - DocFragment::RawDoc(_, _, ref s) => &s[..], - DocFragment::Include(_, _, _, ref s) => &s[..], - } - } - - pub fn span(&self) -> rustc_span::Span { - match *self { - DocFragment::SugaredDoc(_, span, _) - | DocFragment::RawDoc(_, span, _) - | DocFragment::Include(_, span, _, _) => span, - } - } +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum DocFragmentKind { + /// A doc fragment created from a `///` or `//!` doc comment. + SugaredDoc, + /// A doc fragment created from a "raw" `#[doc=""]` attribute. + RawDoc, + /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the + /// given filename and the file contents. + Include { filename: String }, } impl<'a> FromIterator<&'a DocFragment> for String { @@ -407,12 +397,7 @@ impl<'a> FromIterator<&'a DocFragment> for String { if !acc.is_empty() { acc.push('\n'); } - match *frag { - DocFragment::SugaredDoc(_, _, ref docs) - | DocFragment::RawDoc(_, _, ref docs) - | DocFragment::Include(_, _, _, ref docs) => acc.push_str(docs), - } - + acc.push_str(&frag.doc); acc }) } @@ -547,15 +532,15 @@ impl Attributes { .filter_map(|attr| { if let Some(value) = attr.doc_str() { let value = beautify_doc_string(value); - let mk_fragment: fn(_, _, _) -> _ = if attr.is_doc_comment() { - DocFragment::SugaredDoc + let kind = if attr.is_doc_comment() { + DocFragmentKind::SugaredDoc } else { - DocFragment::RawDoc + DocFragmentKind::RawDoc }; let line = doc_line; doc_line += value.lines().count(); - doc_strings.push(mk_fragment(line, attr.span, value)); + doc_strings.push(DocFragment { line, span: attr.span, doc: value, kind }); if sp.is_none() { sp = Some(attr.span); @@ -575,9 +560,12 @@ impl Attributes { { let line = doc_line; doc_line += contents.lines().count(); - doc_strings.push(DocFragment::Include( - line, attr.span, filename, contents, - )); + doc_strings.push(DocFragment { + line, + span: attr.span, + doc: contents, + kind: DocFragmentKind::Include { filename }, + }); } } } @@ -621,7 +609,7 @@ impl Attributes { /// Finds the `doc` attribute as a NameValue and returns the corresponding /// value found. pub fn doc_value(&self) -> Option<&str> { - self.doc_strings.first().map(|s| s.as_str()) + self.doc_strings.first().map(|s| s.doc.as_str()) } /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 935b96e51fc..3f4bd2886b1 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -120,7 +120,7 @@ h3.impl, h3.method, h3.type { } h1, h2, h3, h4, -.sidebar, a.source, .search-input, .content table :not(code)>a, +.sidebar, a.source, .search-input, .content table td:first-child > a, .collapse-toggle, div.item-list .out-of-band, #source-sidebar, #sidebar-toggle { font-family: "Fira Sans", sans-serif; diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 671e0825567..4bca3996eb4 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -232,7 +232,12 @@ impl fold::DocFolder for CoverageCalculator { let mut tests = Tests { found_tests: 0 }; find_testable_code( - &i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::>().join("\n"), + &i.attrs + .doc_strings + .iter() + .map(|d| d.doc.as_str()) + .collect::>() + .join("\n"), &mut tests, ErrorCodes::No, false, diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs index c2185592d14..be7250f833f 100644 --- a/src/librustdoc/passes/collapse_docs.rs +++ b/src/librustdoc/passes/collapse_docs.rs @@ -1,4 +1,4 @@ -use crate::clean::{self, DocFragment, Item}; +use crate::clean::{self, DocFragment, DocFragmentKind, Item}; use crate::core::DocContext; use crate::fold; use crate::fold::DocFolder; @@ -12,23 +12,6 @@ pub const COLLAPSE_DOCS: Pass = Pass { description: "concatenates all document attributes into one document attribute", }; -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -enum DocFragmentKind { - Sugared, - Raw, - Include, -} - -impl DocFragment { - fn kind(&self) -> DocFragmentKind { - match *self { - DocFragment::SugaredDoc(..) => DocFragmentKind::Sugared, - DocFragment::RawDoc(..) => DocFragmentKind::Raw, - DocFragment::Include(..) => DocFragmentKind::Include, - } - } -} - pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate { let mut krate = Collapser.fold_crate(krate); krate.collapsed = true; @@ -50,30 +33,22 @@ fn collapse(doc_strings: &mut Vec) { for frag in take(doc_strings) { if let Some(mut curr_frag) = last_frag.take() { - let curr_kind = curr_frag.kind(); - let new_kind = frag.kind(); + let curr_kind = &curr_frag.kind; + let new_kind = &frag.kind; - if curr_kind == DocFragmentKind::Include || curr_kind != new_kind { - match curr_frag { - DocFragment::SugaredDoc(_, _, ref mut doc_string) - | DocFragment::RawDoc(_, _, ref mut doc_string) => { - // add a newline for extra padding between segments - doc_string.push('\n'); - } - _ => {} + if matches!(*curr_kind, DocFragmentKind::Include { .. }) || curr_kind != new_kind { + if *curr_kind == DocFragmentKind::SugaredDoc + || *curr_kind == DocFragmentKind::RawDoc + { + // add a newline for extra padding between segments + curr_frag.doc.push('\n'); } docs.push(curr_frag); last_frag = Some(frag); } else { - match curr_frag { - DocFragment::SugaredDoc(_, ref mut span, ref mut doc_string) - | DocFragment::RawDoc(_, ref mut span, ref mut doc_string) => { - doc_string.push('\n'); - doc_string.push_str(frag.as_str()); - *span = span.to(frag.span()); - } - _ => unreachable!(), - } + curr_frag.doc.push('\n'); + curr_frag.doc.push_str(&frag.doc); + curr_frag.span = curr_frag.span.to(frag.span); last_frag = Some(curr_frag); } } else { diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 75a65966667..f8e395bfb41 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -8,7 +8,7 @@ use std::mem; use std::ops::Range; use self::Condition::*; -use crate::clean::{self, GetDefId, Item}; +use crate::clean::{self, DocFragmentKind, GetDefId, Item}; use crate::core::DocContext; use crate::fold::{DocFolder, StripItem}; @@ -314,11 +314,11 @@ crate fn span_of_attrs(attrs: &clean::Attributes) -> Option { if attrs.doc_strings.is_empty() { return None; } - let start = attrs.doc_strings[0].span(); + let start = attrs.doc_strings[0].span; if start == DUMMY_SP { return None; } - let end = attrs.doc_strings.last().expect("no doc strings provided").span(); + let end = attrs.doc_strings.last().expect("no doc strings provided").span; Some(start.to(end)) } @@ -333,10 +333,8 @@ crate fn source_span_for_markdown_range( md_range: &Range, attrs: &clean::Attributes, ) -> Option { - let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag { - clean::DocFragment::SugaredDoc(..) => true, - _ => false, - }); + let is_all_sugared_doc = + attrs.doc_strings.iter().all(|frag| frag.kind == DocFragmentKind::SugaredDoc); if !is_all_sugared_doc { return None; diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index 5604a9c2dc1..a9cf5a87f54 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -36,13 +36,7 @@ impl clean::Attributes { fn unindent_fragments(docs: &mut Vec) { for fragment in docs { - match *fragment { - DocFragment::SugaredDoc(_, _, ref mut doc_string) - | DocFragment::RawDoc(_, _, ref mut doc_string) - | DocFragment::Include(_, _, _, ref mut doc_string) => { - *doc_string = unindent(doc_string) - } - } + fragment.doc = unindent(&fragment.doc); } } diff --git a/src/test/ui/issues/issue-69532.rs b/src/test/ui/issues/issue-69532.rs new file mode 100644 index 00000000000..81007b15074 --- /dev/null +++ b/src/test/ui/issues/issue-69532.rs @@ -0,0 +1,24 @@ +// run-pass +#![feature(const_fn_transmute)] + +const fn make_nans() -> (f64, f64, f32, f32) { + let nan1: f64 = unsafe { std::mem::transmute(0x7FF0_0001_0000_0001u64) }; + let nan2: f64 = unsafe { std::mem::transmute(0x7FF0_0000_0000_0001u64) }; + + let nan1_32 = nan1 as f32; + let nan2_32 = nan2 as f32; + + (nan1, nan2, nan1_32, nan2_32) +} + +static NANS: (f64, f64, f32, f32) = make_nans(); + +fn main() { + let (nan1, nan2, nan1_32, nan2_32) = NANS; + + assert!(nan1.is_nan()); + assert!(nan2.is_nan()); + + assert!(nan1_32.is_nan()); + assert!(nan2_32.is_nan()); +} diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs index a719b314150..7d68af49e28 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs @@ -49,8 +49,8 @@ fn main() { simd_select(m4, 0u32, 1u32); //~^ ERROR found non-SIMD `u32` - simd_select_bitmask(0u8, x, x); - //~^ ERROR mask length `8` != other vector length `4` + simd_select_bitmask(0u16, x, x); + //~^ ERROR mask length `16` != other vector length `4` // simd_select_bitmask(0u8, 1u32, 2u32); //~^ ERROR found non-SIMD `u32` diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr index f68c969d13e..a1ef0bb8ee0 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr @@ -22,11 +22,11 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD LL | simd_select(m4, 0u32, 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4` +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `16` != other vector length `4` --> $DIR/simd-intrinsic-generic-select.rs:52:9 | -LL | simd_select_bitmask(0u8, x, x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_select_bitmask(0u16, x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32` --> $DIR/simd-intrinsic-generic-select.rs:55:9 diff --git a/src/test/ui/simd/simd-intrinsic-generic-select.rs b/src/test/ui/simd/simd-intrinsic-generic-select.rs index dc9ec5d2760..b850cf9750a 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-select.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-select.rs @@ -167,4 +167,29 @@ fn main() { let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7); assert_eq!(r, e); } + + unsafe { + let a = u32x4(0, 1, 2, 3); + let b = u32x4(4, 5, 6, 7); + + let r: u32x4 = simd_select_bitmask(0u8, a, b); + let e = b; + assert_eq!(r, e); + + let r: u32x4 = simd_select_bitmask(0xfu8, a, b); + let e = a; + assert_eq!(r, e); + + let r: u32x4 = simd_select_bitmask(0b0101u8, a, b); + let e = u32x4(0, 5, 2, 7); + assert_eq!(r, e); + + let r: u32x4 = simd_select_bitmask(0b1010u8, a, b); + let e = u32x4(4, 1, 6, 3); + assert_eq!(r, e); + + let r: u32x4 = simd_select_bitmask(0b1100u8, a, b); + let e = u32x4(4, 5, 2, 3); + assert_eq!(r, e); + } }