mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 03:38:29 +00:00
Auto merge of #77527 - jonas-schievink:rollup-szgq5he, r=jonas-schievink
Rollup of 8 pull requests Successful merges: - #77072 (Minor `hash_map` doc adjustments + item attribute orderings) - #77368 (Backport LLVM apfloat commit to rustc_apfloat) - #77445 (BTreeMap: complete the compile-time test_variance test case) - #77504 (Support vectors with fewer than 8 elements for simd_select_bitmask) - #77513 (Change DocFragments from enum variant fields to structs with a nested enum) - #77518 (Only use Fira Sans for the first `td` in item lists) - #77521 (Move target feature whitelist from cg_llvm to cg_ssa) - #77525 (Enable RenameReturnPlace MIR optimization on mir-opt-level >= 2) Failed merges: r? `@ghost`
This commit is contained in:
commit
a835b483fe
@ -1511,11 +1511,16 @@ impl<S: Semantics, T: Semantics> FloatConvert<IeeeFloat<T>> for IeeeFloat<S> {
|
|||||||
sig::set_bit(&mut r.sig, T::PRECISION - 1);
|
sig::set_bit(&mut r.sig, T::PRECISION - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// gcc forces the Quiet bit on, which means (float)(double)(float_sNan)
|
// Convert of sNaN creates qNaN and raises an exception (invalid op).
|
||||||
// does not give you back the same bits. This is dubious, and we
|
// This also guarantees that a sNaN does not become Inf on a truncation
|
||||||
// don't currently do it. You're really supposed to get
|
// that loses all payload bits.
|
||||||
// an invalid operation signal at runtime, but nobody does that.
|
if self.is_signaling() {
|
||||||
status = Status::OK;
|
// Quiet signaling NaN.
|
||||||
|
sig::set_bit(&mut r.sig, T::QNAN_BIT);
|
||||||
|
status = Status::INVALID_OP;
|
||||||
|
} else {
|
||||||
|
status = Status::OK;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*loses_info = false;
|
*loses_info = false;
|
||||||
status = Status::OK;
|
status = Status::OK;
|
||||||
|
@ -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]
|
#[test]
|
||||||
fn min_num() {
|
fn min_num() {
|
||||||
let f1 = Double::from_f64(1.0);
|
let f1 = Double::from_f64(1.0);
|
||||||
@ -1492,27 +1503,32 @@ fn convert() {
|
|||||||
assert_eq!(4294967295.0, test.to_f64());
|
assert_eq!(4294967295.0, test.to_f64());
|
||||||
assert!(!loses_info);
|
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 test = Single::qnan(None);
|
||||||
let x87_qnan = X87DoubleExtended::qnan(None);
|
let x87_qnan = X87DoubleExtended::qnan(None);
|
||||||
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
||||||
assert!(test.bitwise_eq(x87_qnan));
|
assert!(test.bitwise_eq(x87_qnan));
|
||||||
assert!(!loses_info);
|
assert!(!loses_info);
|
||||||
|
|
||||||
let test = X87DoubleExtended::snan(None);
|
let test = Single::snan(None);
|
||||||
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
let sta = test.convert(&mut loses_info);
|
||||||
assert!(test.bitwise_eq(x87_snan));
|
let test: X87DoubleExtended = sta.value;
|
||||||
|
assert!(test.is_nan());
|
||||||
|
assert!(!test.is_signaling());
|
||||||
assert!(!loses_info);
|
assert!(!loses_info);
|
||||||
|
assert_eq!(sta.status, Status::INVALID_OP);
|
||||||
|
|
||||||
let test = X87DoubleExtended::qnan(None);
|
let test = X87DoubleExtended::qnan(None);
|
||||||
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
||||||
assert!(test.bitwise_eq(x87_qnan));
|
assert!(test.bitwise_eq(x87_qnan));
|
||||||
assert!(!loses_info);
|
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]
|
#[test]
|
||||||
|
@ -349,17 +349,15 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
|
use rustc_codegen_ssa::target_features::{all_known_features, supported_target_features};
|
||||||
providers.supported_target_features = |tcx, cnum| {
|
providers.supported_target_features = |tcx, cnum| {
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
if tcx.sess.opts.actually_rustdoc {
|
if tcx.sess.opts.actually_rustdoc {
|
||||||
// rustdoc needs to be able to document functions that use all the features, so
|
// rustdoc needs to be able to document functions that use all the features, so
|
||||||
// provide them all.
|
// 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 {
|
} else {
|
||||||
llvm_util::supported_target_features(tcx.sess)
|
supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
|
||||||
.iter()
|
|
||||||
.map(|&(a, b)| (a.to_string(), b))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -793,14 +793,18 @@ fn generic_simd_intrinsic(
|
|||||||
require_simd!(arg_tys[1], "argument");
|
require_simd!(arg_tys[1], "argument");
|
||||||
let v_len = arg_tys[1].simd_size(tcx);
|
let v_len = arg_tys[1].simd_size(tcx);
|
||||||
require!(
|
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 `{}`",
|
"mismatched lengths: mask length `{}` != other vector length `{}`",
|
||||||
m_len,
|
m_len,
|
||||||
v_len
|
v_len
|
||||||
);
|
);
|
||||||
let i1 = bx.type_i1();
|
let i1 = bx.type_i1();
|
||||||
let i1xn = bx.type_vector(i1, m_len);
|
let im = bx.type_ix(v_len);
|
||||||
let m_i1s = bx.bitcast(args[0].immediate(), i1xn);
|
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()));
|
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use crate::back::write::create_informational_target_machine;
|
use crate::back::write::create_informational_target_machine;
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
|
use rustc_codegen_ssa::target_features::supported_target_features;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_feature::UnstableFeatures;
|
use rustc_feature::UnstableFeatures;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_session::config::PrintRequest;
|
use rustc_session::config::PrintRequest;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::sym;
|
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
||||||
use std::ffi::CString;
|
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
|
// 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
|
// to LLVM or the feature detection code will walk past the end of the feature
|
||||||
// array, leading to crashes.
|
// array, leading to crashes.
|
||||||
|
|
||||||
const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
|
||||||
("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<Symbol>)] = &[
|
|
||||||
("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<Symbol>)] = &[
|
|
||||||
("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<Symbol>)] = &[
|
|
||||||
("hvx", Some(sym::hexagon_target_feature)),
|
|
||||||
("hvx-length128b", Some(sym::hexagon_target_feature)),
|
|
||||||
];
|
|
||||||
|
|
||||||
const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
|
||||||
("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<Symbol>)] =
|
|
||||||
&[("fp64", Some(sym::mips_target_feature)), ("msa", Some(sym::mips_target_feature))];
|
|
||||||
|
|
||||||
const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
|
||||||
("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<Symbol>)] = &[
|
|
||||||
("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<Item = (&'static str, Option<Symbol>)> {
|
|
||||||
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 {
|
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 };
|
let arch = if sess.target.target.arch == "x86_64" { "x86" } else { &*sess.target.target.arch };
|
||||||
match (arch, s) {
|
match (arch, s) {
|
||||||
@ -306,20 +172,6 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] {
|
|
||||||
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() {
|
pub fn print_version() {
|
||||||
// Can be called without initializing LLVM
|
// Can be called without initializing LLVM
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -42,6 +42,7 @@ pub mod glue;
|
|||||||
pub mod meth;
|
pub mod meth;
|
||||||
pub mod mir;
|
pub mod mir;
|
||||||
pub mod mono_item;
|
pub mod mono_item;
|
||||||
|
pub mod target_features;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
|
||||||
pub struct ModuleCodegen<M> {
|
pub struct ModuleCodegen<M> {
|
||||||
|
150
compiler/rustc_codegen_ssa/src/target_features.rs
Normal file
150
compiler/rustc_codegen_ssa/src/target_features.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
use rustc_session::Session;
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
|
use rustc_span::symbol::Symbol;
|
||||||
|
|
||||||
|
const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||||
|
("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<Symbol>)] = &[
|
||||||
|
("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<Symbol>)] = &[
|
||||||
|
("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<Symbol>)] = &[
|
||||||
|
("hvx", Some(sym::hexagon_target_feature)),
|
||||||
|
("hvx-length128b", Some(sym::hexagon_target_feature)),
|
||||||
|
];
|
||||||
|
|
||||||
|
const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||||
|
("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<Symbol>)] =
|
||||||
|
&[("fp64", Some(sym::mips_target_feature)), ("msa", Some(sym::mips_target_feature))];
|
||||||
|
|
||||||
|
const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||||
|
("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<Symbol>)] = &[
|
||||||
|
("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<Item = (&'static str, Option<Symbol>)> {
|
||||||
|
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<Symbol>)] {
|
||||||
|
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,
|
||||||
|
_ => &[],
|
||||||
|
}
|
||||||
|
}
|
@ -36,12 +36,6 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
|
|||||||
return;
|
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) {
|
let returned_local = match local_eligible_for_nrvo(body) {
|
||||||
Some(l) => l,
|
Some(l) => l,
|
||||||
None => {
|
None => {
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
|
use super::super::{navigate::Position, node, DeterministicRng};
|
||||||
|
use super::Entry::{Occupied, Vacant};
|
||||||
|
use super::*;
|
||||||
use crate::boxed::Box;
|
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::fmt::Debug;
|
||||||
use crate::rc::Rc;
|
use crate::rc::Rc;
|
||||||
use crate::string::String;
|
use crate::string::{String, ToString};
|
||||||
use crate::string::ToString;
|
|
||||||
use crate::vec::Vec;
|
use crate::vec::Vec;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
@ -16,19 +14,17 @@ use std::ops::RangeBounds;
|
|||||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
use super::super::DeterministicRng;
|
|
||||||
|
|
||||||
// Capacity of a tree with a single level,
|
// 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;
|
const NODE_CAPACITY: usize = node::CAPACITY;
|
||||||
|
|
||||||
// Minimum number of elements to insert, to guarantee a tree with 2 levels,
|
// 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.
|
// 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;
|
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,
|
// 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.
|
// 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;
|
const MIN_INSERTS_HEIGHT_2: usize = 89;
|
||||||
|
|
||||||
@ -1386,44 +1382,65 @@ fn test_clone_from() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn test_variance() {
|
fn test_variance() {
|
||||||
use std::collections::btree_map::{IntoIter, Iter, Keys, Range, Values};
|
|
||||||
|
|
||||||
fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
|
fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> {
|
fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> {
|
fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> {
|
fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> {
|
fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> {
|
fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> {
|
||||||
v
|
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, ()> {
|
fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> {
|
fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> {
|
||||||
v
|
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
|
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
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn test_sync() {
|
fn test_sync() {
|
||||||
fn map<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
|
fn map<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
|
||||||
@ -1493,7 +1510,6 @@ fn test_sync() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn test_send() {
|
fn test_send() {
|
||||||
fn map<T: Send>(v: BTreeMap<T, T>) -> impl Send {
|
fn map<T: Send>(v: BTreeMap<T, T>) -> impl Send {
|
||||||
@ -1520,7 +1536,7 @@ fn test_send() {
|
|||||||
v.iter()
|
v.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_mut<T: Send + Sync>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
|
fn iter_mut<T: Send>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
|
||||||
v.iter_mut()
|
v.iter_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1532,7 +1548,7 @@ fn test_send() {
|
|||||||
v.values()
|
v.values()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn values_mut<T: Send + Sync>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
|
fn values_mut<T: Send>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
|
||||||
v.values_mut()
|
v.values_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1540,7 +1556,7 @@ fn test_send() {
|
|||||||
v.range(..)
|
v.range(..)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn range_mut<T: Send + Sync + Ord>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
|
fn range_mut<T: Send + Ord>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
|
||||||
v.range_mut(..)
|
v.range_mut(..)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
use crate::collections::BTreeSet;
|
use super::super::DeterministicRng;
|
||||||
|
use super::*;
|
||||||
use crate::vec::Vec;
|
use crate::vec::Vec;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
use super::super::DeterministicRng;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clone_eq() {
|
fn test_clone_eq() {
|
||||||
let mut m = BTreeSet::new();
|
let mut m = BTreeSet::new();
|
||||||
@ -528,11 +527,8 @@ fn test_recovery() {
|
|||||||
assert_eq!(s.iter().next(), None);
|
assert_eq!(s.iter().next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn test_variance() {
|
fn test_variance() {
|
||||||
use std::collections::btree_set::{IntoIter, Iter, Range};
|
|
||||||
|
|
||||||
fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
|
fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
@ -545,6 +541,85 @@ fn test_variance() {
|
|||||||
fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
|
fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
// not applied to Difference, Intersection, SymmetricDifference, Union
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn test_sync() {
|
||||||
|
fn set<T: Sync>(v: &BTreeSet<T>) -> impl Sync + '_ {
|
||||||
|
v
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter<T: Sync>(v: &BTreeSet<T>) -> impl Sync + '_ {
|
||||||
|
v.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_iter<T: Sync>(v: BTreeSet<T>) -> impl Sync {
|
||||||
|
v.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn range<T: Sync + Ord>(v: &BTreeSet<T>) -> impl Sync + '_ {
|
||||||
|
v.range(..)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drain_filter<T: Sync + Ord>(v: &mut BTreeSet<T>) -> impl Sync + '_ {
|
||||||
|
v.drain_filter(|_| false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn difference<T: Sync + Ord>(v: &BTreeSet<T>) -> impl Sync + '_ {
|
||||||
|
v.difference(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intersection<T: Sync + Ord>(v: &BTreeSet<T>) -> impl Sync + '_ {
|
||||||
|
v.intersection(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symmetric_difference<T: Sync + Ord>(v: &BTreeSet<T>) -> impl Sync + '_ {
|
||||||
|
v.symmetric_difference(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn union<T: Sync + Ord>(v: &BTreeSet<T>) -> impl Sync + '_ {
|
||||||
|
v.union(&v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn test_send() {
|
||||||
|
fn set<T: Send>(v: BTreeSet<T>) -> impl Send {
|
||||||
|
v
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter<T: Send + Sync>(v: &BTreeSet<T>) -> impl Send + '_ {
|
||||||
|
v.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_iter<T: Send>(v: BTreeSet<T>) -> impl Send {
|
||||||
|
v.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn range<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {
|
||||||
|
v.range(..)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drain_filter<T: Send + Ord>(v: &mut BTreeSet<T>) -> impl Send + '_ {
|
||||||
|
v.drain_filter(|_| false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn difference<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {
|
||||||
|
v.difference(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intersection<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {
|
||||||
|
v.intersection(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symmetric_difference<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {
|
||||||
|
v.symmetric_difference(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn union<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {
|
||||||
|
v.union(&v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -554,8 +554,8 @@ impl<K, V, S> HashMap<K, V, S> {
|
|||||||
/// a.clear();
|
/// a.clear();
|
||||||
/// assert!(a.is_empty());
|
/// assert!(a.is_empty());
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.base.clear();
|
self.base.clear();
|
||||||
}
|
}
|
||||||
@ -746,8 +746,8 @@ where
|
|||||||
/// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
|
/// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
|
||||||
/// assert_eq!(map.get_key_value(&2), None);
|
/// assert_eq!(map.get_key_value(&2), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "map_get_key_value", since = "1.40.0")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "map_get_key_value", since = "1.40.0")]
|
||||||
pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
|
pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
|
||||||
where
|
where
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
@ -772,8 +772,8 @@ where
|
|||||||
/// assert_eq!(map.contains_key(&1), true);
|
/// assert_eq!(map.contains_key(&1), true);
|
||||||
/// assert_eq!(map.contains_key(&2), false);
|
/// assert_eq!(map.contains_key(&2), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
|
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
|
||||||
where
|
where
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
@ -800,8 +800,8 @@ where
|
|||||||
/// }
|
/// }
|
||||||
/// assert_eq!(map[&1], "b");
|
/// assert_eq!(map[&1], "b");
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
|
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
|
||||||
where
|
where
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
@ -834,8 +834,8 @@ where
|
|||||||
/// assert_eq!(map.insert(37, "c"), Some("b"));
|
/// assert_eq!(map.insert(37, "c"), Some("b"));
|
||||||
/// assert_eq!(map[&37], "c");
|
/// assert_eq!(map[&37], "c");
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
|
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
|
||||||
self.base.insert(k, v)
|
self.base.insert(k, v)
|
||||||
}
|
}
|
||||||
@ -857,8 +857,8 @@ where
|
|||||||
/// assert_eq!(map.remove(&1), Some("a"));
|
/// assert_eq!(map.remove(&1), Some("a"));
|
||||||
/// assert_eq!(map.remove(&1), None);
|
/// assert_eq!(map.remove(&1), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
|
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
|
||||||
where
|
where
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
@ -886,8 +886,8 @@ where
|
|||||||
/// assert_eq!(map.remove(&1), None);
|
/// assert_eq!(map.remove(&1), None);
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "hash_map_remove_entry", since = "1.27.0")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "hash_map_remove_entry", since = "1.27.0")]
|
||||||
pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
|
pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
|
||||||
where
|
where
|
||||||
K: Borrow<Q>,
|
K: Borrow<Q>,
|
||||||
@ -909,8 +909,8 @@ where
|
|||||||
/// map.retain(|&k, _| k % 2 == 0);
|
/// map.retain(|&k, _| k % 2 == 0);
|
||||||
/// assert_eq!(map.len(), 4);
|
/// assert_eq!(map.len(), 4);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "retain_hash_collection", since = "1.18.0")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "retain_hash_collection", since = "1.18.0")]
|
||||||
pub fn retain<F>(&mut self, f: F)
|
pub fn retain<F>(&mut self, f: F)
|
||||||
where
|
where
|
||||||
F: FnMut(&K, &mut V) -> bool,
|
F: FnMut(&K, &mut V) -> bool,
|
||||||
@ -1647,7 +1647,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> {
|
|||||||
self.base.get()
|
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.
|
/// with a lifetime bound to the map itself.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash_raw_entry", issue = "56167")]
|
#[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()
|
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.
|
/// with a lifetime bound to the map itself.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash_raw_entry", issue = "56167")]
|
#[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> {
|
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.
|
/// and returns a mutable reference to it.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash_raw_entry", issue = "56167")]
|
#[unstable(feature = "hash_raw_entry", issue = "56167")]
|
||||||
@ -2173,7 +2173,6 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V> Entry<'a, K, V> {
|
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
|
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
||||||
/// a mutable reference to the value in the entry.
|
/// 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);
|
/// assert_eq!(map["poneyland"], 6);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn or_insert(self, default: V) -> &'a mut V {
|
pub fn or_insert(self, default: V) -> &'a mut V {
|
||||||
match self {
|
match self {
|
||||||
Occupied(entry) => entry.into_mut(),
|
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,
|
/// 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.
|
/// 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());
|
/// assert_eq!(map["poneyland"], "hoho".to_string());
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
||||||
match self {
|
match self {
|
||||||
Occupied(entry) => entry.into_mut(),
|
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,
|
/// 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
|
/// which takes the key as its argument, and returns a mutable reference to the value in the
|
||||||
/// entry.
|
/// entry.
|
||||||
@ -2240,6 +2239,7 @@ impl<'a, K, V> Entry<'a, K, V> {
|
|||||||
/// assert_eq!(map["poneyland"], 9);
|
/// assert_eq!(map["poneyland"], 9);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[unstable(feature = "or_insert_with_key", issue = "71024")]
|
||||||
pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
|
pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
|
||||||
match self {
|
match self {
|
||||||
Occupied(entry) => entry.into_mut(),
|
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
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -2331,7 +2331,6 @@ impl<'a, K, V> Entry<'a, K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V: Default> 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,
|
/// 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.
|
/// 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]
|
#[inline]
|
||||||
|
#[stable(feature = "entry_or_default", since = "1.28.0")]
|
||||||
pub fn or_default(self) -> &'a mut V {
|
pub fn or_default(self) -> &'a mut V {
|
||||||
match self {
|
match self {
|
||||||
Occupied(entry) => entry.into_mut(),
|
Occupied(entry) => entry.into_mut(),
|
||||||
@ -2452,7 +2452,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
|
|||||||
self.base.get_mut()
|
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.
|
/// with a lifetime bound to the map itself.
|
||||||
///
|
///
|
||||||
/// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
|
/// 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()
|
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.
|
/// and returns a mutable reference to it.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -2646,8 +2646,8 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
|
|||||||
self.base.insert(value)
|
self.base.insert(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the value of the entry with the VacantEntry's key,
|
/// Sets the value of the entry with the `VacantEntry`'s key,
|
||||||
/// and returns an OccupiedEntry.
|
/// and returns an `OccupiedEntry`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -370,32 +370,22 @@ impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
|
|||||||
/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
|
/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
|
||||||
/// kept separate because of issue #42760.
|
/// kept separate because of issue #42760.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
pub enum DocFragment {
|
pub struct DocFragment {
|
||||||
/// A doc fragment created from a `///` or `//!` doc comment.
|
pub line: usize,
|
||||||
SugaredDoc(usize, rustc_span::Span, String),
|
pub span: rustc_span::Span,
|
||||||
/// A doc fragment created from a "raw" `#[doc=""]` attribute.
|
pub doc: String,
|
||||||
RawDoc(usize, rustc_span::Span, String),
|
pub kind: DocFragmentKind,
|
||||||
/// 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),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DocFragment {
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
pub fn as_str(&self) -> &str {
|
pub enum DocFragmentKind {
|
||||||
match *self {
|
/// A doc fragment created from a `///` or `//!` doc comment.
|
||||||
DocFragment::SugaredDoc(_, _, ref s) => &s[..],
|
SugaredDoc,
|
||||||
DocFragment::RawDoc(_, _, ref s) => &s[..],
|
/// A doc fragment created from a "raw" `#[doc=""]` attribute.
|
||||||
DocFragment::Include(_, _, _, ref s) => &s[..],
|
RawDoc,
|
||||||
}
|
/// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
|
||||||
}
|
/// given filename and the file contents.
|
||||||
|
Include { filename: String },
|
||||||
pub fn span(&self) -> rustc_span::Span {
|
|
||||||
match *self {
|
|
||||||
DocFragment::SugaredDoc(_, span, _)
|
|
||||||
| DocFragment::RawDoc(_, span, _)
|
|
||||||
| DocFragment::Include(_, span, _, _) => span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromIterator<&'a DocFragment> for String {
|
impl<'a> FromIterator<&'a DocFragment> for String {
|
||||||
@ -407,12 +397,7 @@ impl<'a> FromIterator<&'a DocFragment> for String {
|
|||||||
if !acc.is_empty() {
|
if !acc.is_empty() {
|
||||||
acc.push('\n');
|
acc.push('\n');
|
||||||
}
|
}
|
||||||
match *frag {
|
acc.push_str(&frag.doc);
|
||||||
DocFragment::SugaredDoc(_, _, ref docs)
|
|
||||||
| DocFragment::RawDoc(_, _, ref docs)
|
|
||||||
| DocFragment::Include(_, _, _, ref docs) => acc.push_str(docs),
|
|
||||||
}
|
|
||||||
|
|
||||||
acc
|
acc
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -547,15 +532,15 @@ impl Attributes {
|
|||||||
.filter_map(|attr| {
|
.filter_map(|attr| {
|
||||||
if let Some(value) = attr.doc_str() {
|
if let Some(value) = attr.doc_str() {
|
||||||
let value = beautify_doc_string(value);
|
let value = beautify_doc_string(value);
|
||||||
let mk_fragment: fn(_, _, _) -> _ = if attr.is_doc_comment() {
|
let kind = if attr.is_doc_comment() {
|
||||||
DocFragment::SugaredDoc
|
DocFragmentKind::SugaredDoc
|
||||||
} else {
|
} else {
|
||||||
DocFragment::RawDoc
|
DocFragmentKind::RawDoc
|
||||||
};
|
};
|
||||||
|
|
||||||
let line = doc_line;
|
let line = doc_line;
|
||||||
doc_line += value.lines().count();
|
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() {
|
if sp.is_none() {
|
||||||
sp = Some(attr.span);
|
sp = Some(attr.span);
|
||||||
@ -575,9 +560,12 @@ impl Attributes {
|
|||||||
{
|
{
|
||||||
let line = doc_line;
|
let line = doc_line;
|
||||||
doc_line += contents.lines().count();
|
doc_line += contents.lines().count();
|
||||||
doc_strings.push(DocFragment::Include(
|
doc_strings.push(DocFragment {
|
||||||
line, attr.span, filename, contents,
|
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
|
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
||||||
/// value found.
|
/// value found.
|
||||||
pub fn doc_value(&self) -> Option<&str> {
|
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
|
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
|
||||||
|
@ -120,7 +120,7 @@ h3.impl, h3.method, h3.type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4,
|
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,
|
.collapse-toggle, div.item-list .out-of-band,
|
||||||
#source-sidebar, #sidebar-toggle {
|
#source-sidebar, #sidebar-toggle {
|
||||||
font-family: "Fira Sans", sans-serif;
|
font-family: "Fira Sans", sans-serif;
|
||||||
|
@ -232,7 +232,12 @@ impl fold::DocFolder for CoverageCalculator {
|
|||||||
let mut tests = Tests { found_tests: 0 };
|
let mut tests = Tests { found_tests: 0 };
|
||||||
|
|
||||||
find_testable_code(
|
find_testable_code(
|
||||||
&i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
|
&i.attrs
|
||||||
|
.doc_strings
|
||||||
|
.iter()
|
||||||
|
.map(|d| d.doc.as_str())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n"),
|
||||||
&mut tests,
|
&mut tests,
|
||||||
ErrorCodes::No,
|
ErrorCodes::No,
|
||||||
false,
|
false,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::clean::{self, DocFragment, Item};
|
use crate::clean::{self, DocFragment, DocFragmentKind, Item};
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::fold;
|
use crate::fold;
|
||||||
use crate::fold::DocFolder;
|
use crate::fold::DocFolder;
|
||||||
@ -12,23 +12,6 @@ pub const COLLAPSE_DOCS: Pass = Pass {
|
|||||||
description: "concatenates all document attributes into one document attribute",
|
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 {
|
pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
|
||||||
let mut krate = Collapser.fold_crate(krate);
|
let mut krate = Collapser.fold_crate(krate);
|
||||||
krate.collapsed = true;
|
krate.collapsed = true;
|
||||||
@ -50,30 +33,22 @@ fn collapse(doc_strings: &mut Vec<DocFragment>) {
|
|||||||
|
|
||||||
for frag in take(doc_strings) {
|
for frag in take(doc_strings) {
|
||||||
if let Some(mut curr_frag) = last_frag.take() {
|
if let Some(mut curr_frag) = last_frag.take() {
|
||||||
let curr_kind = curr_frag.kind();
|
let curr_kind = &curr_frag.kind;
|
||||||
let new_kind = frag.kind();
|
let new_kind = &frag.kind;
|
||||||
|
|
||||||
if curr_kind == DocFragmentKind::Include || curr_kind != new_kind {
|
if matches!(*curr_kind, DocFragmentKind::Include { .. }) || curr_kind != new_kind {
|
||||||
match curr_frag {
|
if *curr_kind == DocFragmentKind::SugaredDoc
|
||||||
DocFragment::SugaredDoc(_, _, ref mut doc_string)
|
|| *curr_kind == DocFragmentKind::RawDoc
|
||||||
| DocFragment::RawDoc(_, _, ref mut doc_string) => {
|
{
|
||||||
// add a newline for extra padding between segments
|
// add a newline for extra padding between segments
|
||||||
doc_string.push('\n');
|
curr_frag.doc.push('\n');
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
docs.push(curr_frag);
|
docs.push(curr_frag);
|
||||||
last_frag = Some(frag);
|
last_frag = Some(frag);
|
||||||
} else {
|
} else {
|
||||||
match curr_frag {
|
curr_frag.doc.push('\n');
|
||||||
DocFragment::SugaredDoc(_, ref mut span, ref mut doc_string)
|
curr_frag.doc.push_str(&frag.doc);
|
||||||
| DocFragment::RawDoc(_, ref mut span, ref mut doc_string) => {
|
curr_frag.span = curr_frag.span.to(frag.span);
|
||||||
doc_string.push('\n');
|
|
||||||
doc_string.push_str(frag.as_str());
|
|
||||||
*span = span.to(frag.span());
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
last_frag = Some(curr_frag);
|
last_frag = Some(curr_frag);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,7 +8,7 @@ use std::mem;
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use self::Condition::*;
|
use self::Condition::*;
|
||||||
use crate::clean::{self, GetDefId, Item};
|
use crate::clean::{self, DocFragmentKind, GetDefId, Item};
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::fold::{DocFolder, StripItem};
|
use crate::fold::{DocFolder, StripItem};
|
||||||
|
|
||||||
@ -314,11 +314,11 @@ crate fn span_of_attrs(attrs: &clean::Attributes) -> Option<Span> {
|
|||||||
if attrs.doc_strings.is_empty() {
|
if attrs.doc_strings.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let start = attrs.doc_strings[0].span();
|
let start = attrs.doc_strings[0].span;
|
||||||
if start == DUMMY_SP {
|
if start == DUMMY_SP {
|
||||||
return None;
|
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))
|
Some(start.to(end))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,10 +333,8 @@ crate fn source_span_for_markdown_range(
|
|||||||
md_range: &Range<usize>,
|
md_range: &Range<usize>,
|
||||||
attrs: &clean::Attributes,
|
attrs: &clean::Attributes,
|
||||||
) -> Option<Span> {
|
) -> Option<Span> {
|
||||||
let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag {
|
let is_all_sugared_doc =
|
||||||
clean::DocFragment::SugaredDoc(..) => true,
|
attrs.doc_strings.iter().all(|frag| frag.kind == DocFragmentKind::SugaredDoc);
|
||||||
_ => false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if !is_all_sugared_doc {
|
if !is_all_sugared_doc {
|
||||||
return None;
|
return None;
|
||||||
|
@ -36,13 +36,7 @@ impl clean::Attributes {
|
|||||||
|
|
||||||
fn unindent_fragments(docs: &mut Vec<DocFragment>) {
|
fn unindent_fragments(docs: &mut Vec<DocFragment>) {
|
||||||
for fragment in docs {
|
for fragment in docs {
|
||||||
match *fragment {
|
fragment.doc = unindent(&fragment.doc);
|
||||||
DocFragment::SugaredDoc(_, _, ref mut doc_string)
|
|
||||||
| DocFragment::RawDoc(_, _, ref mut doc_string)
|
|
||||||
| DocFragment::Include(_, _, _, ref mut doc_string) => {
|
|
||||||
*doc_string = unindent(doc_string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/test/ui/issues/issue-69532.rs
Normal file
24
src/test/ui/issues/issue-69532.rs
Normal file
@ -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());
|
||||||
|
}
|
@ -49,8 +49,8 @@ fn main() {
|
|||||||
simd_select(m4, 0u32, 1u32);
|
simd_select(m4, 0u32, 1u32);
|
||||||
//~^ ERROR found non-SIMD `u32`
|
//~^ ERROR found non-SIMD `u32`
|
||||||
|
|
||||||
simd_select_bitmask(0u8, x, x);
|
simd_select_bitmask(0u16, x, x);
|
||||||
//~^ ERROR mask length `8` != other vector length `4`
|
//~^ ERROR mask length `16` != other vector length `4`
|
||||||
//
|
//
|
||||||
simd_select_bitmask(0u8, 1u32, 2u32);
|
simd_select_bitmask(0u8, 1u32, 2u32);
|
||||||
//~^ ERROR found non-SIMD `u32`
|
//~^ ERROR found non-SIMD `u32`
|
||||||
|
@ -22,11 +22,11 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD
|
|||||||
LL | simd_select(m4, 0u32, 1u32);
|
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
|
--> $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`
|
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
|
--> $DIR/simd-intrinsic-generic-select.rs:55:9
|
||||||
|
@ -167,4 +167,29 @@ fn main() {
|
|||||||
let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7);
|
let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7);
|
||||||
assert_eq!(r, e);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user