diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 8493354014734..260c9fe44ba80 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -21,7 +21,6 @@ #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(maybe_uninit_slice)] -#![feature(new_uninit)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(strict_provenance)] diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index c88c5bd35a526..bc41d33a609e3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -11,7 +11,6 @@ use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol}; -use smallvec::{smallvec, SmallVec}; use thin_vec::{thin_vec, ThinVec}; macro_rules! path { @@ -68,43 +67,63 @@ pub(crate) fn expand_deriving_smart_ptr( }; // Convert generic parameters (from the struct) into generic args. - let mut pointee_param = None; - let mut multiple_pointee_diag: SmallVec<[_; 2]> = smallvec![]; - let self_params = generics + let self_params: Vec<_> = generics .params .iter() - .enumerate() - .map(|(idx, p)| match p.kind { + .map(|p| match p.kind { GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)), - GenericParamKind::Type { .. } => { - if p.attrs().iter().any(|attr| attr.has_name(sym::pointee)) { - if pointee_param.is_some() { - multiple_pointee_diag.push(cx.dcx().struct_span_err( - p.span(), - "`SmartPointer` can only admit one type as pointee", - )); - } else { - pointee_param = Some(idx); - } - } - GenericArg::Type(cx.ty_ident(p.span(), p.ident)) - } + GenericParamKind::Type { .. } => GenericArg::Type(cx.ty_ident(p.span(), p.ident)), GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)), }) - .collect::>(); - let Some(pointee_param_idx) = pointee_param else { + .collect(); + let type_params: Vec<_> = generics + .params + .iter() + .enumerate() + .filter_map(|(idx, p)| { + if let GenericParamKind::Type { .. } = p.kind { + Some((idx, p.span(), p.attrs().iter().any(|attr| attr.has_name(sym::pointee)))) + } else { + None + } + }) + .collect(); + + let pointee_param_idx = if type_params.is_empty() { + // `#[derive(SmartPointer)]` requires at least one generic type on the target `struct` cx.dcx().struct_span_err( span, - "At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits", + "`SmartPointer` can only be derived on `struct`s that are generic over at least one type", ).emit(); return; - }; - if !multiple_pointee_diag.is_empty() { - for diag in multiple_pointee_diag { - diag.emit(); + } else if type_params.len() == 1 { + // Regardless of the only type param being designed as `#[pointee]` or not, we can just use it as such + type_params[0].0 + } else { + let mut pointees = type_params + .iter() + .filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span))) + .fuse(); + match (pointees.next(), pointees.next()) { + (Some((idx, _span)), None) => idx, + (None, _) => { + cx.dcx().struct_span_err( + span, + "exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits", + ).emit(); + return; + } + (Some((_, one)), Some((_, another))) => { + cx.dcx() + .struct_span_err( + vec![one, another], + "only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits", + ) + .emit(); + return; + } } - return; - } + }; // Create the type of `self`. let path = cx.path_all(span, false, vec![name_ident], self_params.clone()); diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 317e970d70485..92a857c2adcf4 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -521,13 +521,20 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( let function_features = function_features .iter() - .flat_map(|feat| { - llvm_util::to_llvm_features(cx.tcx.sess, feat).into_iter().map(|f| format!("+{f}")) - }) + // Convert to LLVMFeatures and filter out unavailable ones + .flat_map(|feat| llvm_util::to_llvm_features(cx.tcx.sess, feat)) + // Convert LLVMFeatures & dependencies to +s + .flat_map(|feat| feat.into_iter().map(|f| format!("+{f}"))) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(), InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) + // HACK: LLVM versions 19+ do not have the FPMR feature and treat it as always enabled + // It only exists as a feature in LLVM 18, cannot be passed down for any other version + .chain(match &*cx.tcx.sess.target.arch { + "aarch64" if llvm_util::get_version().0 == 18 => vec!["+fpmr".to_string()], + _ => vec![], + }) .collect::>(); if cx.tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 7af5eb9278f38..618602ed70f44 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -209,7 +209,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> { // Though note that Rust can also be build with an external precompiled version of LLVM // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics -pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { +pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option> { let arch = if sess.target.arch == "x86_64" { "x86" } else if sess.target.arch == "arm64ec" { @@ -218,40 +218,59 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a &*sess.target.arch }; match (arch, s) { - ("x86", "sse4.2") => { - LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32")) - } - ("x86", "pclmulqdq") => LLVMFeature::new("pclmul"), - ("x86", "rdrand") => LLVMFeature::new("rdrnd"), - ("x86", "bmi1") => LLVMFeature::new("bmi"), - ("x86", "cmpxchg16b") => LLVMFeature::new("cx16"), - ("x86", "lahfsahf") => LLVMFeature::new("sahf"), - ("aarch64", "rcpc2") => LLVMFeature::new("rcpc-immo"), - ("aarch64", "dpb") => LLVMFeature::new("ccpp"), - ("aarch64", "dpb2") => LLVMFeature::new("ccdp"), - ("aarch64", "frintts") => LLVMFeature::new("fptoint"), - ("aarch64", "fcma") => LLVMFeature::new("complxnum"), - ("aarch64", "pmuv3") => LLVMFeature::new("perfmon"), - ("aarch64", "paca") => LLVMFeature::new("pauth"), - ("aarch64", "pacg") => LLVMFeature::new("pauth"), + ("x86", "sse4.2") => Some(LLVMFeature::with_dependency( + "sse4.2", + TargetFeatureFoldStrength::EnableOnly("crc32"), + )), + ("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")), + ("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")), + ("x86", "bmi1") => Some(LLVMFeature::new("bmi")), + ("x86", "cmpxchg16b") => Some(LLVMFeature::new("cx16")), + ("x86", "lahfsahf") => Some(LLVMFeature::new("sahf")), + ("aarch64", "rcpc2") => Some(LLVMFeature::new("rcpc-immo")), + ("aarch64", "dpb") => Some(LLVMFeature::new("ccpp")), + ("aarch64", "dpb2") => Some(LLVMFeature::new("ccdp")), + ("aarch64", "frintts") => Some(LLVMFeature::new("fptoint")), + ("aarch64", "fcma") => Some(LLVMFeature::new("complxnum")), + ("aarch64", "pmuv3") => Some(LLVMFeature::new("perfmon")), + ("aarch64", "paca") => Some(LLVMFeature::new("pauth")), + ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")), + ("aarch64", "sve-b16b16") => Some(LLVMFeature::new("b16b16")), + ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")), // Rust ties fp and neon together. ("aarch64", "neon") => { - LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8")) + Some(LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8"))) } // In LLVM neon implicitly enables fp, but we manually enable // neon when a feature only implicitly enables fp - ("aarch64", "fhm") => LLVMFeature::new("fp16fml"), - ("aarch64", "fp16") => LLVMFeature::new("fullfp16"), + ("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")), + ("aarch64", "fp16") => Some(LLVMFeature::new("fullfp16")), + // Filter out features that are not supported by the current LLVM version + ("aarch64", "faminmax") if get_version().0 < 18 => None, + ("aarch64", "fp8") if get_version().0 < 18 => None, + ("aarch64", "fp8dot2") if get_version().0 < 18 => None, + ("aarch64", "fp8dot4") if get_version().0 < 18 => None, + ("aarch64", "fp8fma") if get_version().0 < 18 => None, + ("aarch64", "fpmr") if get_version().0 != 18 => None, + ("aarch64", "lut") if get_version().0 < 18 => None, + ("aarch64", "sme-f8f16") if get_version().0 < 18 => None, + ("aarch64", "sme-f8f32") if get_version().0 < 18 => None, + ("aarch64", "sme-fa64") if get_version().0 < 18 => None, + ("aarch64", "sme-lutv2") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8dot2") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8dot4") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8fma") if get_version().0 < 18 => None, + ("aarch64", "v9.5a") if get_version().0 < 18 => None, // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called // `fast-unaligned-access`. In LLVM 19, it was split back out. ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => { - LLVMFeature::new("fast-unaligned-access") + Some(LLVMFeature::new("fast-unaligned-access")) } // For LLVM 18, enable the evex512 target feature if a avx512 target feature is enabled. ("x86", s) if get_version().0 >= 18 && s.starts_with("avx512") => { - LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")) + Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512"))) } - (_, s) => LLVMFeature::new(s), + (_, s) => Some(LLVMFeature::new(s)), } } @@ -291,13 +310,17 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { return true; } // check that all features in a given smallvec are enabled - for llvm_feature in to_llvm_features(sess, feature) { - let cstr = SmallCStr::new(llvm_feature); - if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { - return false; + if let Some(feat) = to_llvm_features(sess, feature) { + for llvm_feature in feat { + let cstr = SmallCStr::new(llvm_feature); + if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { + return false; + } } + true + } else { + false } - true }) .map(|(feature, _, _)| Symbol::intern(feature)), ); @@ -386,9 +409,9 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach .target .supported_target_features() .iter() - .map(|(feature, _gate, _implied)| { + .filter_map(|(feature, _gate, _implied)| { // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. - let llvm_feature = to_llvm_features(sess, *feature).llvm_feature_name; + let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name; let desc = match llvm_target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok() { Some(index) => { @@ -398,7 +421,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach None => "", }; - (*feature, desc) + Some((*feature, desc)) }) .collect::>(); @@ -595,7 +618,7 @@ pub(crate) fn global_llvm_features( if feature_state.is_none() { let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| { - let llvm_features = to_llvm_features(sess, rust_feature); + let llvm_features = to_llvm_features(sess, rust_feature)?; if llvm_features.contains(feature) && !llvm_features.contains(rust_feature) { @@ -641,7 +664,7 @@ pub(crate) fn global_llvm_features( // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. - let llvm_feature = to_llvm_features(sess, feature); + let llvm_feature = to_llvm_features(sess, feature)?; Some( std::iter::once(format!( @@ -691,6 +714,9 @@ fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { let feature = s .strip_prefix(&['+', '-'][..]) .unwrap_or_else(|| sess.dcx().emit_fatal(InvalidTargetFeaturePrefix { feature: s })); + if s.is_empty() { + return None; + } // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 279d02e877731..f7ddc3e2c569e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -302,6 +302,7 @@ declare_features! ( // FIXME: Document these and merge with the list below. // Unstable `#[target_feature]` directives. + (unstable, aarch64_unstable_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)), (unstable, arm_target_feature, "1.27.0", Some(44839)), (unstable, avx512_target_feature, "1.27.0", Some(44839)), diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index eb47ac3c68e90..f773b5b46adae 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,7 +1,7 @@ // tidy-alphabetical-start #![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(feature = "nightly", feature(extend_one, new_uninit, step_trait, test))] +#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))] #![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index ce330b4744bf6..32f79ff72349d 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -53,7 +53,6 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] -#![feature(new_uninit)] #![feature(ptr_alignment_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 35fe28c5d425b..7b020f11cdda0 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -26,7 +26,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(negative_impls)] -#![feature(new_uninit)] #![feature(read_buf)] #![feature(round_char_boundary)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c64fefd457ae2..aba5673272568 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -356,6 +356,7 @@ symbols! { _task_context, a32, aarch64_target_feature, + aarch64_unstable_target_feature, aarch64_ver_target_feature, abi, abi_amdgpu_kernel, @@ -1897,6 +1898,7 @@ symbols! { three_way_compare, thumb2, thumb_mode: "thumb-mode", + time, tmm_reg, to_owned_method, to_string, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs index 1525faf9b7e1d..9fd7c24649896 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs @@ -7,7 +7,7 @@ pub fn target() -> Target { llvm_target: "aarch64-unknown-unknown-musl".into(), metadata: crate::spec::TargetMetadata { description: Some("ARM64 Trusty".into()), - tier: Some(2), + tier: Some(3), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs index ae73de5e64dc5..889cc20156979 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs @@ -8,7 +8,7 @@ pub fn target() -> Target { llvm_target: "armv7-unknown-unknown-gnueabi".into(), metadata: crate::spec::TargetMetadata { description: Some("Armv7-A Trusty".into()), - tier: Some(2), + tier: Some(3), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index da66ba270b33c..8319cb880cc79 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -99,6 +99,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("bti", Stable, &[]), // FEAT_CRC ("crc", Stable, &[]), + // FEAT_CSSC + ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_DIT ("dit", Stable, &[]), // FEAT_DotProd @@ -107,21 +109,37 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("dpb", Stable, &[]), // FEAT_DPB2 ("dpb2", Stable, &["dpb"]), + // FEAT_ECV + ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_F32MM ("f32mm", Stable, &["sve"]), // FEAT_F64MM ("f64mm", Stable, &["sve"]), + // FEAT_FAMINMAX + ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FCMA ("fcma", Stable, &["neon"]), // FEAT_FHM ("fhm", Stable, &["fp16"]), // FEAT_FLAGM ("flagm", Stable, &[]), + // FEAT_FLAGM2 + ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FP16 // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 ("fp16", Stable, &["neon"]), + // FEAT_FP8 + ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]), + // FEAT_FP8DOT2 + ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]), + // FEAT_FP8DOT4 + ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]), + // FEAT_FP8FMA + ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]), // FEAT_FRINTTS ("frintts", Stable, &[]), + // FEAT_HBC + ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_I8MM ("i8mm", Stable, &[]), // FEAT_JSCVT @@ -131,6 +149,14 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("lor", Stable, &[]), // FEAT_LSE ("lse", Stable, &[]), + // FEAT_LSE128 + ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]), + // FEAT_LSE2 + ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_LUT + ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_MOPS + ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_MTE & FEAT_MTE2 ("mte", Stable, &[]), // FEAT_AdvSimd & FEAT_FP @@ -143,14 +169,16 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("pan", Stable, &[]), // FEAT_PMUv3 ("pmuv3", Stable, &[]), - // FEAT_RAND + // FEAT_RNG ("rand", Stable, &[]), // FEAT_RAS & FEAT_RASv1p1 ("ras", Stable, &[]), - // FEAT_RCPC + // FEAT_LRCPC ("rcpc", Stable, &[]), - // FEAT_RCPC2 + // FEAT_LRCPC2 ("rcpc2", Stable, &["rcpc"]), + // FEAT_LRCPC3 + ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), // FEAT_RDM ("rdm", Stable, &["neon"]), // FEAT_SB @@ -161,10 +189,36 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sha3", Stable, &["sha2"]), // FEAT_SM3 & FEAT_SM4 ("sm4", Stable, &["neon"]), + // FEAT_SME + ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SME_F16F16 + ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), + // FEAT_SME_F64F64 + ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_F8F16 + ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]), + // FEAT_SME_F8F32 + ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), + // FEAT_SME_FA64 + ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]), + // FEAT_SME_I16I64 + ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_LUTv2 + ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_SME2 + ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME2p1 + ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SPE ("spe", Stable, &[]), // FEAT_SSBS & FEAT_SSBS2 ("ssbs", Stable, &[]), + // FEAT_SSVE_FP8FDOT2 + ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]), + // FEAT_SSVE_FP8FDOT4 + ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]), + // FEAT_SSVE_FP8FMA + ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), // FEAT_SVE // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608 // @@ -173,9 +227,11 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // // "For backwards compatibility, Neon and VFP are required in the latest architectures." ("sve", Stable, &["neon"]), + // FEAT_SVE_B16B16 (SVE or SME Instructions) + ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SVE2 ("sve2", Stable, &["sve"]), - // FEAT_SVE2_AES + // FEAT_SVE_AES & FEAT_SVE_PMULL128 ("sve2-aes", Stable, &["sve2", "aes"]), // FEAT_SVE2_BitPerm ("sve2-bitperm", Stable, &["sve2"]), @@ -183,6 +239,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sve2-sha3", Stable, &["sve2", "sha3"]), // FEAT_SVE2_SM4 ("sve2-sm4", Stable, &["sve2", "sm4"]), + // FEAT_SVE2p1 + ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]), // FEAT_TME ("tme", Stable, &[]), ( @@ -199,9 +257,19 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]), ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]), - ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &[]), + ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]), + ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]), + ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]), + ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]), + ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]), + ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]), + ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]), + ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]), + ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]), // FEAT_VHE ("vh", Stable, &[]), + // FEAT_WFxT + ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]), // tidy-alphabetical-end ]; diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 137850f31d31e..3ddd23924b5f4 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -446,6 +446,8 @@ trait_selection_type_annotations_needed = {$source_kind -> } .label = type must be known at this point +trait_selection_type_annotations_needed_error_time = this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` + trait_selection_types_declared_different = these two types are declared with different lifetimes... trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 173671059ca93..53f013ac153b1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -6,7 +6,7 @@ use rustc_errors::codes::*; use rustc_errors::{Diag, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource}; use rustc_middle::bug; @@ -18,7 +18,7 @@ use rustc_middle::ty::{ TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, }; use rustc_span::symbol::{sym, Ident}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ @@ -384,6 +384,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label, was_written: false, path: Default::default(), + time_version: false, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -577,6 +578,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } + + let time_version = + self.detect_old_time_crate_version(failure_span, &kind, &mut infer_subdiags); + match error_code { TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired { span, @@ -588,6 +593,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label: None, was_written: path.is_some(), path: path.unwrap_or_default(), + time_version, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -613,6 +619,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }), } } + + /// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error. + /// + // FIXME: we should figure out a more generic version of doing this, ideally in cargo itself. + fn detect_old_time_crate_version( + &self, + span: Option, + kind: &InferSourceKind<'_>, + // We will clear the non-actionable suggestion from the error to reduce noise. + infer_subdiags: &mut Vec>, + ) -> bool { + // FIXME(#129461): We are time-boxing this code in the compiler. It'll start failing + // compilation once we promote 1.89 to beta, which will happen in 9 months from now. + #[cfg(not(version("1.89")))] + const fn version_check() {} + #[cfg(version("1.89"))] + const fn version_check() { + panic!("remove this check as presumably the ecosystem has moved from needing it"); + } + const { version_check() }; + // Only relevant when building the `time` crate. + if self.infcx.tcx.crate_name(LOCAL_CRATE) == sym::time + && let Some(span) = span + && let InferSourceKind::LetBinding { pattern_name, .. } = kind + && let Some(name) = pattern_name + && name.as_str() == "items" + && let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span) + { + let path = file.local_path_if_available().to_string_lossy(); + if path.contains("format_description") && path.contains("parse") { + infer_subdiags.clear(); + return true; + } + } + false + } } #[derive(Debug)] diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 5384084f6d7c3..ebaec0b905936 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -205,6 +205,8 @@ pub struct AnnotationRequired<'a> { #[note(trait_selection_full_type_written)] pub was_written: bool, pub path: PathBuf, + #[note(trait_selection_type_annotations_needed_error_time)] + pub time_version: bool, } // Copy of `AnnotationRequired` for E0283 diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 1bd6626693675..c98d6c5f1dfd2 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -19,6 +19,7 @@ #![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] +#![feature(cfg_version)] #![feature(control_flow_enum)] #![feature(extract_if)] #![feature(if_let_guard)] diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 50d7bae21db72..aeae866e9d344 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -465,6 +465,22 @@ impl Location { } } +/// Location of the statement at the given index for a given basic block. Assumes that `stmt_idx` +/// and `bb_idx` are valid for a given body. +pub fn statement_location(body: &Body, bb_idx: &BasicBlockIdx, stmt_idx: usize) -> Location { + let bb = &body.blocks[*bb_idx]; + let stmt = &bb.statements[stmt_idx]; + Location(stmt.span) +} + +/// Location of the terminator for a given basic block. Assumes that `bb_idx` is valid for a given +/// body. +pub fn terminator_location(body: &Body, bb_idx: &BasicBlockIdx) -> Location { + let bb = &body.blocks[*bb_idx]; + let terminator = &bb.terminator; + Location(terminator.span) +} + /// Reference to a place used to represent a partial projection. pub struct PlaceRef<'a> { pub local: Local, diff --git a/library/Cargo.lock b/library/Cargo.lock index aa22181a4639a..54ad052c52322 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.121" +version = "0.1.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce956e6dc07082ec481f0935a51e83b343f8ca51be560452c0ebf830d0bdf5a5" +checksum = "b47fcbecb558bdad78c7d3a998523c60a50dd6cd046d5fe74163e309e878fff7" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index a39a0a6ce0ea2..4365bcc4ad022 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.121", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.123", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index caaf37f0465ed..38b1766c17440 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -262,8 +262,6 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut five = Box::::new_uninit(); /// /// let five = unsafe { @@ -276,7 +274,7 @@ impl Box { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub fn new_uninit() -> Box> { @@ -292,7 +290,6 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(new_zeroed_alloc)] /// /// let zero = Box::::new_zeroed(); @@ -350,7 +347,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let mut five = Box::::try_new_uninit()?; /// @@ -380,7 +377,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let zero = Box::::try_new_zeroed()?; /// let zero = unsafe { zero.assume_init() }; @@ -460,7 +457,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -498,7 +495,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -538,7 +535,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -576,7 +573,7 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -654,8 +651,6 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { @@ -670,7 +665,7 @@ impl Box<[T]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity(len).into_box(len) } @@ -686,7 +681,6 @@ impl Box<[T]> { /// /// ``` /// #![feature(new_zeroed_alloc)] - /// #![feature(new_uninit)] /// /// let values = Box::<[u32]>::new_zeroed_slice(3); /// let values = unsafe { values.assume_init() }; @@ -708,7 +702,7 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let mut values = Box::<[u32]>::try_new_uninit_slice(3)?; /// let values = unsafe { @@ -746,7 +740,7 @@ impl Box<[T]> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let values = Box::<[u32]>::try_new_zeroed_slice(3)?; /// let values = unsafe { values.assume_init() }; @@ -778,7 +772,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -812,7 +806,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -837,7 +831,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -880,7 +874,7 @@ impl Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -927,8 +921,6 @@ impl Box, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut five = Box::::new_uninit(); /// /// let five: Box = unsafe { @@ -940,7 +932,7 @@ impl Box, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Box { let (raw, alloc) = Box::into_raw_with_allocator(self); @@ -958,7 +950,6 @@ impl Box, A> { /// /// ``` /// #![feature(box_uninit_write)] - /// #![feature(new_uninit)] /// /// let big_box = Box::<[usize; 1024]>::new_uninit(); /// @@ -1001,8 +992,6 @@ impl Box<[mem::MaybeUninit], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { @@ -1016,7 +1005,7 @@ impl Box<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(self); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 5e4b08df6cb55..c459a8da820f6 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -93,7 +93,6 @@ // tidy-alphabetical-start #![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] #![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] -#![cfg_attr(test, feature(new_uninit))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_chunks)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f153aa6d3be9a..1b31a78394eca 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -503,7 +503,6 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -518,7 +517,7 @@ impl Rc { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit() -> Rc> { unsafe { @@ -540,7 +539,6 @@ impl Rc { /// /// ``` /// #![feature(new_zeroed_alloc)] - /// #![feature(new_uninit)] /// /// use std::rc::Rc; /// @@ -594,7 +592,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -630,7 +628,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::rc::Rc; /// @@ -692,7 +690,6 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -736,7 +733,6 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::rc::Rc; @@ -799,7 +795,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -843,7 +839,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -967,7 +963,6 @@ impl Rc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -985,7 +980,7 @@ impl Rc<[T]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } @@ -1000,7 +995,6 @@ impl Rc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(new_zeroed_alloc)] /// /// use std::rc::Rc; @@ -1035,7 +1029,6 @@ impl Rc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -1072,7 +1065,6 @@ impl Rc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::rc::Rc; @@ -1122,7 +1114,6 @@ impl Rc, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -1136,7 +1127,7 @@ impl Rc, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Rc { let (ptr, alloc) = Rc::into_inner_with_allocator(self); @@ -1160,7 +1151,6 @@ impl Rc<[mem::MaybeUninit], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -1177,7 +1167,7 @@ impl Rc<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T], A> { let (ptr, alloc) = Rc::into_inner_with_allocator(self); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4a3522f1a641b..024a794f17b01 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -335,7 +335,7 @@ impl, U: ?Sized, A: Allocator> CoerceUnsized> f impl, U: ?Sized> DispatchFromDyn> for Weak {} #[stable(feature = "arc_weak", since = "1.4.0")] -impl fmt::Debug for Weak { +impl fmt::Debug for Weak { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(Weak)") } @@ -505,7 +505,6 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -521,7 +520,7 @@ impl Arc { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit() -> Arc> { unsafe { @@ -543,7 +542,6 @@ impl Arc { /// /// ``` /// #![feature(new_zeroed_alloc)] - /// #![feature(new_uninit)] /// /// use std::sync::Arc; /// @@ -614,7 +612,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -650,7 +648,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature( allocator_api)] /// /// use std::sync::Arc; /// @@ -711,7 +709,6 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -755,7 +752,6 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::sync::Arc; @@ -845,7 +841,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -889,7 +885,7 @@ impl Arc { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -1101,7 +1097,6 @@ impl Arc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1120,7 +1115,7 @@ impl Arc<[T]> { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } @@ -1136,7 +1131,6 @@ impl Arc<[T]> { /// /// ``` /// #![feature(new_zeroed_alloc)] - /// #![feature(new_uninit)] /// /// use std::sync::Arc; /// @@ -1172,7 +1166,6 @@ impl Arc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -1208,7 +1201,6 @@ impl Arc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::sync::Arc; @@ -1257,7 +1249,6 @@ impl Arc, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1271,7 +1262,7 @@ impl Arc, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc { @@ -1296,7 +1287,6 @@ impl Arc<[mem::MaybeUninit], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1313,7 +1303,7 @@ impl Arc<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc<[T], A> { diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 3d4add6fae452..c5c6a122cfec8 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -15,7 +15,6 @@ #![feature(exact_size_is_empty)] #![feature(linked_list_cursors)] #![feature(map_try_insert)] -#![feature(new_uninit)] #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index 32d15c386cb1b..3f1c58bbd7204 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -8,6 +8,7 @@ #![feature(iter_array_chunks)] #![feature(iter_next_chunk)] #![feature(iter_advance_by)] +#![feature(isqrt)] extern crate test; diff --git a/library/core/benches/num/int_sqrt/mod.rs b/library/core/benches/num/int_sqrt/mod.rs new file mode 100644 index 0000000000000..3c9d173e456a1 --- /dev/null +++ b/library/core/benches/num/int_sqrt/mod.rs @@ -0,0 +1,62 @@ +use rand::Rng; +use test::{black_box, Bencher}; + +macro_rules! int_sqrt_bench { + ($t:ty, $predictable:ident, $random:ident, $random_small:ident, $random_uniform:ident) => { + #[bench] + fn $predictable(bench: &mut Bencher) { + bench.iter(|| { + for n in 0..(<$t>::BITS / 8) { + for i in 1..=(100 as $t) { + let x = black_box(i << (n * 8)); + black_box(x.isqrt()); + } + } + }); + } + + #[bench] + fn $random(bench: &mut Bencher) { + let mut rng = crate::bench_rng(); + /* Exponentially distributed random numbers from the whole range of the type. */ + let numbers: Vec<$t> = + (0..256).map(|_| rng.gen::<$t>() >> rng.gen_range(0..<$t>::BITS)).collect(); + bench.iter(|| { + for x in &numbers { + black_box(black_box(x).isqrt()); + } + }); + } + + #[bench] + fn $random_small(bench: &mut Bencher) { + let mut rng = crate::bench_rng(); + /* Exponentially distributed random numbers from the range 0..256. */ + let numbers: Vec<$t> = + (0..256).map(|_| (rng.gen::() >> rng.gen_range(0..u8::BITS)) as $t).collect(); + bench.iter(|| { + for x in &numbers { + black_box(black_box(x).isqrt()); + } + }); + } + + #[bench] + fn $random_uniform(bench: &mut Bencher) { + let mut rng = crate::bench_rng(); + /* Exponentially distributed random numbers from the whole range of the type. */ + let numbers: Vec<$t> = (0..256).map(|_| rng.gen::<$t>()).collect(); + bench.iter(|| { + for x in &numbers { + black_box(black_box(x).isqrt()); + } + }); + } + }; +} + +int_sqrt_bench! {u8, u8_sqrt_predictable, u8_sqrt_random, u8_sqrt_random_small, u8_sqrt_uniform} +int_sqrt_bench! {u16, u16_sqrt_predictable, u16_sqrt_random, u16_sqrt_random_small, u16_sqrt_uniform} +int_sqrt_bench! {u32, u32_sqrt_predictable, u32_sqrt_random, u32_sqrt_random_small, u32_sqrt_uniform} +int_sqrt_bench! {u64, u64_sqrt_predictable, u64_sqrt_random, u64_sqrt_random_small, u64_sqrt_uniform} +int_sqrt_bench! {u128, u128_sqrt_predictable, u128_sqrt_random, u128_sqrt_random_small, u128_sqrt_uniform} diff --git a/library/core/benches/num/mod.rs b/library/core/benches/num/mod.rs index c1dc3a3062256..7ff7443cfa7fe 100644 --- a/library/core/benches/num/mod.rs +++ b/library/core/benches/num/mod.rs @@ -2,6 +2,7 @@ mod dec2flt; mod flt2dec; mod int_log; mod int_pow; +mod int_sqrt; use std::str::FromStr; diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 42461a3345be9..878a911dde50d 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1641,7 +1641,33 @@ macro_rules! int_impl { if self < 0 { None } else { - Some((self as $UnsignedT).isqrt() as Self) + // SAFETY: Input is nonnegative in this `else` branch. + let result = unsafe { + crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT + }; + + // Inform the optimizer what the range of outputs is. If + // testing `core` crashes with no panic message and a + // `num::int_sqrt::i*` test failed, it's because your edits + // caused these assertions to become false. + // + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never + // cause the output to decrease. Thus, since the input for + // nonnegative signed integers is bounded by + // `[0, <$ActualT>::MAX]`, sqrt(n) will be bounded by + // `[sqrt(0), sqrt(<$ActualT>::MAX)]`. + unsafe { + // SAFETY: `<$ActualT>::MAX` is nonnegative. + const MAX_RESULT: $SelfT = unsafe { + crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT + }; + + crate::hint::assert_unchecked(result >= 0); + crate::hint::assert_unchecked(result <= MAX_RESULT); + } + + Some(result) } } @@ -2862,15 +2888,11 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn isqrt(self) -> Self { - // I would like to implement it as - // ``` - // self.checked_isqrt().expect("argument of integer square root must be non-negative") - // ``` - // but `expect` is not yet stable as a `const fn`. match self.checked_isqrt() { Some(sqrt) => sqrt, - None => panic!("argument of integer square root must be non-negative"), + None => crate::num::int_sqrt::panic_for_negative_argument(), } } diff --git a/library/core/src/num/int_sqrt.rs b/library/core/src/num/int_sqrt.rs new file mode 100644 index 0000000000000..601e81f69930f --- /dev/null +++ b/library/core/src/num/int_sqrt.rs @@ -0,0 +1,316 @@ +//! These functions use the [Karatsuba square root algorithm][1] to compute the +//! [integer square root](https://en.wikipedia.org/wiki/Integer_square_root) +//! for the primitive integer types. +//! +//! The signed integer functions can only handle **nonnegative** inputs, so +//! that must be checked before calling those. +//! +//! [1]: +//! "Paul Zimmermann. Karatsuba Square Root. \[Research Report\] RR-3805, +//! INRIA. 1999, pp.8. (inria-00072854)" + +/// This array stores the [integer square roots]( +/// https://en.wikipedia.org/wiki/Integer_square_root) and remainders of each +/// [`u8`](prim@u8) value. For example, `U8_ISQRT_WITH_REMAINDER[17]` will be +/// `(4, 1)` because the integer square root of 17 is 4 and because 17 is 1 +/// higher than 4 squared. +const U8_ISQRT_WITH_REMAINDER: [(u8, u8); 256] = { + let mut result = [(0, 0); 256]; + + let mut n: usize = 0; + let mut isqrt_n: usize = 0; + while n < result.len() { + result[n] = (isqrt_n as u8, (n - isqrt_n.pow(2)) as u8); + + n += 1; + if n == (isqrt_n + 1).pow(2) { + isqrt_n += 1; + } + } + + result +}; + +/// Returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any [`u8`](prim@u8) +/// input. +#[must_use = "this returns the result of the operation, \ + without modifying the original"] +#[inline] +pub const fn u8(n: u8) -> u8 { + U8_ISQRT_WITH_REMAINDER[n as usize].0 +} + +/// Generates an `i*` function that returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any **nonnegative** +/// input of a specific signed integer type. +macro_rules! signed_fn { + ($SignedT:ident, $UnsignedT:ident) => { + /// Returns the [integer square root]( + /// https://en.wikipedia.org/wiki/Integer_square_root) of any + /// **nonnegative** + #[doc = concat!("[`", stringify!($SignedT), "`](prim@", stringify!($SignedT), ")")] + /// input. + /// + /// # Safety + /// + /// This results in undefined behavior when the input is negative. + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn $SignedT(n: $SignedT) -> $SignedT { + debug_assert!(n >= 0, "Negative input inside `isqrt`."); + $UnsignedT(n as $UnsignedT) as $SignedT + } + }; +} + +signed_fn!(i8, u8); +signed_fn!(i16, u16); +signed_fn!(i32, u32); +signed_fn!(i64, u64); +signed_fn!(i128, u128); + +/// Generates a `u*` function that returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any input of +/// a specific unsigned integer type. +macro_rules! unsigned_fn { + ($UnsignedT:ident, $HalfBitsT:ident, $stages:ident) => { + /// Returns the [integer square root]( + /// https://en.wikipedia.org/wiki/Integer_square_root) of any + #[doc = concat!("[`", stringify!($UnsignedT), "`](prim@", stringify!($UnsignedT), ")")] + /// input. + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn $UnsignedT(mut n: $UnsignedT) -> $UnsignedT { + if n <= <$HalfBitsT>::MAX as $UnsignedT { + $HalfBitsT(n as $HalfBitsT) as $UnsignedT + } else { + // The normalization shift satisfies the Karatsuba square root + // algorithm precondition "a₃ ≥ b/4" where a₃ is the most + // significant quarter of `n`'s bits and b is the number of + // values that can be represented by that quarter of the bits. + // + // b/4 would then be all 0s except the second most significant + // bit (010...0) in binary. Since a₃ must be at least b/4, a₃'s + // most significant bit or its neighbor must be a 1. Since a₃'s + // most significant bits are `n`'s most significant bits, the + // same applies to `n`. + // + // The reason to shift by an even number of bits is because an + // even number of bits produces the square root shifted to the + // left by half of the normalization shift: + // + // sqrt(n << (2 * p)) + // sqrt(2.pow(2 * p) * n) + // sqrt(2.pow(2 * p)) * sqrt(n) + // 2.pow(p) * sqrt(n) + // sqrt(n) << p + // + // Shifting by an odd number of bits leaves an ugly sqrt(2) + // multiplied in: + // + // sqrt(n << (2 * p + 1)) + // sqrt(2.pow(2 * p + 1) * n) + // sqrt(2 * 2.pow(2 * p) * n) + // sqrt(2) * sqrt(2.pow(2 * p)) * sqrt(n) + // sqrt(2) * 2.pow(p) * sqrt(n) + // sqrt(2) * (sqrt(n) << p) + const EVEN_MAKING_BITMASK: u32 = !1; + let normalization_shift = n.leading_zeros() & EVEN_MAKING_BITMASK; + n <<= normalization_shift; + + let s = $stages(n); + + let denormalization_shift = normalization_shift >> 1; + s >> denormalization_shift + } + } + }; +} + +/// Generates the first stage of the computation after normalization. +/// +/// # Safety +/// +/// `$n` must be nonzero. +macro_rules! first_stage { + ($original_bits:literal, $n:ident) => {{ + debug_assert!($n != 0, "`$n` is zero in `first_stage!`."); + + const N_SHIFT: u32 = $original_bits - 8; + let n = $n >> N_SHIFT; + + let (s, r) = U8_ISQRT_WITH_REMAINDER[n as usize]; + + // Inform the optimizer that `s` is nonzero. This will allow it to + // avoid generating code to handle division-by-zero panics in the next + // stage. + // + // SAFETY: If the original `$n` is zero, the top of the `unsigned_fn` + // macro recurses instead of continuing to this point, so the original + // `$n` wasn't a 0 if we've reached here. + // + // Then the `unsigned_fn` macro normalizes `$n` so that at least one of + // its two most-significant bits is a 1. + // + // Then this stage puts the eight most-significant bits of `$n` into + // `n`. This means that `n` here has at least one 1 bit in its two + // most-significant bits, making `n` nonzero. + // + // `U8_ISQRT_WITH_REMAINDER[n as usize]` will give a nonzero `s` when + // given a nonzero `n`. + unsafe { crate::hint::assert_unchecked(s != 0) }; + (s, r) + }}; +} + +/// Generates a middle stage of the computation. +/// +/// # Safety +/// +/// `$s` must be nonzero. +macro_rules! middle_stage { + ($original_bits:literal, $ty:ty, $n:ident, $s:ident, $r:ident) => {{ + debug_assert!($s != 0, "`$s` is zero in `middle_stage!`."); + + const N_SHIFT: u32 = $original_bits - <$ty>::BITS; + let n = ($n >> N_SHIFT) as $ty; + + const HALF_BITS: u32 = <$ty>::BITS >> 1; + const QUARTER_BITS: u32 = <$ty>::BITS >> 2; + const LOWER_HALF_1_BITS: $ty = (1 << HALF_BITS) - 1; + const LOWEST_QUARTER_1_BITS: $ty = (1 << QUARTER_BITS) - 1; + + let lo = n & LOWER_HALF_1_BITS; + let numerator = (($r as $ty) << QUARTER_BITS) | (lo >> QUARTER_BITS); + let denominator = ($s as $ty) << 1; + let q = numerator / denominator; + let u = numerator % denominator; + + let mut s = ($s << QUARTER_BITS) as $ty + q; + let (mut r, overflow) = + ((u << QUARTER_BITS) | (lo & LOWEST_QUARTER_1_BITS)).overflowing_sub(q * q); + if overflow { + r = r.wrapping_add(2 * s - 1); + s -= 1; + } + + // Inform the optimizer that `s` is nonzero. This will allow it to + // avoid generating code to handle division-by-zero panics in the next + // stage. + // + // SAFETY: If the original `$n` is zero, the top of the `unsigned_fn` + // macro recurses instead of continuing to this point, so the original + // `$n` wasn't a 0 if we've reached here. + // + // Then the `unsigned_fn` macro normalizes `$n` so that at least one of + // its two most-significant bits is a 1. + // + // Then these stages take as many of the most-significant bits of `$n` + // as will fit in this stage's type. For example, the stage that + // handles `u32` deals with the 32 most-significant bits of `$n`. This + // means that each stage has at least one 1 bit in `n`'s two + // most-significant bits, making `n` nonzero. + // + // Then this stage will produce the correct integer square root for + // that `n` value. Since `n` is nonzero, `s` will also be nonzero. + unsafe { crate::hint::assert_unchecked(s != 0) }; + (s, r) + }}; +} + +/// Generates the last stage of the computation before denormalization. +/// +/// # Safety +/// +/// `$s` must be nonzero. +macro_rules! last_stage { + ($ty:ty, $n:ident, $s:ident, $r:ident) => {{ + debug_assert!($s != 0, "`$s` is zero in `last_stage!`."); + + const HALF_BITS: u32 = <$ty>::BITS >> 1; + const QUARTER_BITS: u32 = <$ty>::BITS >> 2; + const LOWER_HALF_1_BITS: $ty = (1 << HALF_BITS) - 1; + + let lo = $n & LOWER_HALF_1_BITS; + let numerator = (($r as $ty) << QUARTER_BITS) | (lo >> QUARTER_BITS); + let denominator = ($s as $ty) << 1; + + let q = numerator / denominator; + let mut s = ($s << QUARTER_BITS) as $ty + q; + let (s_squared, overflow) = s.overflowing_mul(s); + if overflow || s_squared > $n { + s -= 1; + } + s + }}; +} + +/// Takes the normalized [`u16`](prim@u16) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u16_stages(n: u16) -> u16 { + let (s, r) = first_stage!(16, n); + last_stage!(u16, n, s, r) +} + +/// Takes the normalized [`u32`](prim@u32) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u32_stages(n: u32) -> u32 { + let (s, r) = first_stage!(32, n); + let (s, r) = middle_stage!(32, u16, n, s, r); + last_stage!(u32, n, s, r) +} + +/// Takes the normalized [`u64`](prim@u64) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u64_stages(n: u64) -> u64 { + let (s, r) = first_stage!(64, n); + let (s, r) = middle_stage!(64, u16, n, s, r); + let (s, r) = middle_stage!(64, u32, n, s, r); + last_stage!(u64, n, s, r) +} + +/// Takes the normalized [`u128`](prim@u128) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u128_stages(n: u128) -> u128 { + let (s, r) = first_stage!(128, n); + let (s, r) = middle_stage!(128, u16, n, s, r); + let (s, r) = middle_stage!(128, u32, n, s, r); + let (s, r) = middle_stage!(128, u64, n, s, r); + last_stage!(u128, n, s, r) +} + +unsigned_fn!(u16, u8, u16_stages); +unsigned_fn!(u32, u16, u32_stages); +unsigned_fn!(u64, u32, u64_stages); +unsigned_fn!(u128, u64, u128_stages); + +/// Instantiate this panic logic once, rather than for all the isqrt methods +/// on every single primitive type. +#[cold] +#[track_caller] +pub const fn panic_for_negative_argument() -> ! { + panic!("argument of integer square root cannot be negative") +} diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 309e1ba958aee..e9e5324666ada 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -41,6 +41,7 @@ mod uint_macros; // import uint_impl! mod error; mod int_log10; +mod int_sqrt; mod nonzero; mod overflow_panic; mod saturating; diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index c6e9c249048a7..8b888f12da0b1 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -7,7 +7,7 @@ use crate::marker::{Freeze, StructuralPartialEq}; use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign}; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::str::FromStr; -use crate::{fmt, hint, intrinsics, ptr, ub_checks}; +use crate::{fmt, intrinsics, ptr, ub_checks}; /// A marker trait for primitive types which can be zero. /// @@ -1545,31 +1545,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods { without modifying the original"] #[inline] pub const fn isqrt(self) -> Self { - // The algorithm is based on the one presented in - // - // which cites as source the following C code: - // . - - let mut op = self.get(); - let mut res = 0; - let mut one = 1 << (self.ilog2() & !1); - - while one != 0 { - if op >= res + one { - op -= res + one; - res = (res >> 1) + one; - } else { - res >>= 1; - } - one >>= 2; - } + let result = self.get().isqrt(); - // SAFETY: The result fits in an integer with half as many bits. - // Inform the optimizer about it. - unsafe { hint::assert_unchecked(res < 1 << (Self::BITS / 2)) }; - - // SAFETY: The square root of an integer >= 1 is always >= 1. - unsafe { Self::new_unchecked(res) } + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never cause + // the output to decrease. Thus, since the input for nonzero + // unsigned integers has a lower bound of 1, the lower bound of the + // results will be sqrt(1), which is 1, so a result can't be zero. + unsafe { Self::new_unchecked(result) } } }; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0d0bbc5256f78..d9036abecc592 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2762,10 +2762,24 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn isqrt(self) -> Self { - match NonZero::new(self) { - Some(x) => x.isqrt().get(), - None => 0, + let result = crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT; + + // Inform the optimizer what the range of outputs is. If testing + // `core` crashes with no panic message and a `num::int_sqrt::u*` + // test failed, it's because your edits caused these assertions or + // the assertions in `fn isqrt` of `nonzero.rs` to become false. + // + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never + // cause the output to decrease. Thus, since the input for unsigned + // integers is bounded by `[0, <$ActualT>::MAX]`, sqrt(n) will be + // bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]`. + unsafe { + const MAX_RESULT: $SelfT = crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT; + crate::hint::assert_unchecked(result <= MAX_RESULT); } + + result } /// Performs Euclidean division. diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 7cd3b54e3f39a..830a96204ca03 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -288,38 +288,6 @@ macro_rules! int_module { assert_eq!(r.saturating_pow(0), 1 as $T); } - #[test] - fn test_isqrt() { - assert_eq!($T::MIN.checked_isqrt(), None); - assert_eq!((-1 as $T).checked_isqrt(), None); - assert_eq!((0 as $T).isqrt(), 0 as $T); - assert_eq!((1 as $T).isqrt(), 1 as $T); - assert_eq!((2 as $T).isqrt(), 1 as $T); - assert_eq!((99 as $T).isqrt(), 9 as $T); - assert_eq!((100 as $T).isqrt(), 10 as $T); - } - - #[cfg(not(miri))] // Miri is too slow - #[test] - fn test_lots_of_isqrt() { - let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; - for n in 0..=n_max { - let isqrt: $T = n.isqrt(); - - assert!(isqrt.pow(2) <= n); - let (square, overflow) = (isqrt + 1).overflowing_pow(2); - assert!(overflow || square > n); - } - - for n in ($T::MAX - 127)..=$T::MAX { - let isqrt: $T = n.isqrt(); - - assert!(isqrt.pow(2) <= n); - let (square, overflow) = (isqrt + 1).overflowing_pow(2); - assert!(overflow || square > n); - } - } - #[test] fn test_div_floor() { let a: $T = 8; diff --git a/library/core/tests/num/int_sqrt.rs b/library/core/tests/num/int_sqrt.rs new file mode 100644 index 0000000000000..4c126615d4b0b --- /dev/null +++ b/library/core/tests/num/int_sqrt.rs @@ -0,0 +1,239 @@ +macro_rules! tests { + ($isqrt_consistency_check_fn_macro:ident : $($T:ident)+) => { + $( + mod $T { + $isqrt_consistency_check_fn_macro!($T); + + // Check that the following produce the correct values from + // `isqrt`: + // + // * the first and last 128 nonnegative values + // * powers of two, minus one + // * powers of two + // + // For signed types, check that `checked_isqrt` and `isqrt` + // either produce the same numeric value or respectively + // produce `None` and a panic. Make sure to do a consistency + // check for `<$T>::MIN` as well, as no nonnegative values + // negate to it. + // + // For unsigned types check that `isqrt` produces the same + // numeric value for `$T` and `NonZero<$T>`. + #[test] + fn isqrt() { + isqrt_consistency_check(<$T>::MIN); + + for n in (0..=127) + .chain(<$T>::MAX - 127..=<$T>::MAX) + .chain((0..<$T>::MAX.count_ones()).map(|exponent| (1 << exponent) - 1)) + .chain((0..<$T>::MAX.count_ones()).map(|exponent| 1 << exponent)) + { + isqrt_consistency_check(n); + + let isqrt_n = n.isqrt(); + assert!( + isqrt_n + .checked_mul(isqrt_n) + .map(|isqrt_n_squared| isqrt_n_squared <= n) + .unwrap_or(false), + "`{n}.isqrt()` should be lower than {isqrt_n}." + ); + assert!( + (isqrt_n + 1) + .checked_mul(isqrt_n + 1) + .map(|isqrt_n_plus_1_squared| n < isqrt_n_plus_1_squared) + .unwrap_or(true), + "`{n}.isqrt()` should be higher than {isqrt_n})." + ); + } + } + + // Check the square roots of: + // + // * the first 1,024 perfect squares + // * halfway between each of the first 1,024 perfect squares + // and the next perfect square + // * the next perfect square after the each of the first 1,024 + // perfect squares, minus one + // * the last 1,024 perfect squares + // * the last 1,024 perfect squares, minus one + // * halfway between each of the last 1,024 perfect squares + // and the previous perfect square + #[test] + // Skip this test on Miri, as it takes too long to run. + #[cfg(not(miri))] + fn isqrt_extended() { + // The correct value is worked out by using the fact that + // the nth nonzero perfect square is the sum of the first n + // odd numbers: + // + // 1 = 1 + // 4 = 1 + 3 + // 9 = 1 + 3 + 5 + // 16 = 1 + 3 + 5 + 7 + // + // Note also that the last odd number added in is two times + // the square root of the previous perfect square, plus + // one: + // + // 1 = 2*0 + 1 + // 3 = 2*1 + 1 + // 5 = 2*2 + 1 + // 7 = 2*3 + 1 + // + // That means we can add the square root of this perfect + // square once to get about halfway to the next perfect + // square, then we can add the square root of this perfect + // square again to get to the next perfect square, minus + // one, then we can add one to get to the next perfect + // square. + // + // This allows us to, for each of the first 1,024 perfect + // squares, test that the square roots of the following are + // all correct and equal to each other: + // + // * the current perfect square + // * about halfway to the next perfect square + // * the next perfect square, minus one + let mut n: $T = 0; + for sqrt_n in 0..1_024.min((1_u128 << (<$T>::MAX.count_ones()/2)) - 1) as $T { + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "`{sqrt_n}.pow(2).isqrt()` should be {sqrt_n}." + ); + + n += sqrt_n; + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "{n} is about halfway between `{sqrt_n}.pow(2)` and `{}.pow(2)`, so `{n}.isqrt()` should be {sqrt_n}.", + sqrt_n + 1 + ); + + n += sqrt_n; + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "`({}.pow(2) - 1).isqrt()` should be {sqrt_n}.", + sqrt_n + 1 + ); + + n += 1; + } + + // Similarly, for each of the last 1,024 perfect squares, + // check: + // + // * the current perfect square + // * the current perfect square, minus one + // * about halfway to the previous perfect square + // + // `MAX`'s `isqrt` return value is verified in the `isqrt` + // test function above. + let maximum_sqrt = <$T>::MAX.isqrt(); + let mut n = maximum_sqrt * maximum_sqrt; + + for sqrt_n in (maximum_sqrt - 1_024.min((1_u128 << (<$T>::MAX.count_ones()/2)) - 1) as $T..maximum_sqrt).rev() { + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n + 1, + "`{0}.pow(2).isqrt()` should be {0}.", + sqrt_n + 1 + ); + + n -= 1; + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "`({}.pow(2) - 1).isqrt()` should be {sqrt_n}.", + sqrt_n + 1 + ); + + n -= sqrt_n; + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "{n} is about halfway between `{sqrt_n}.pow(2)` and `{}.pow(2)`, so `{n}.isqrt()` should be {sqrt_n}.", + sqrt_n + 1 + ); + + n -= sqrt_n; + } + } + } + )* + }; +} + +macro_rules! signed_check { + ($T:ident) => { + /// This takes an input and, if it's nonnegative or + #[doc = concat!("`", stringify!($T), "::MIN`,")] + /// checks that `isqrt` and `checked_isqrt` produce equivalent results + /// for that input and for the negative of that input. + fn isqrt_consistency_check(n: $T) { + // `<$T>::MIN` will be negative, so ignore it in this nonnegative + // section. + if n >= 0 { + assert_eq!( + Some(n.isqrt()), + n.checked_isqrt(), + "`{n}.checked_isqrt()` should match `Some({n}.isqrt())`.", + ); + } + + // `wrapping_neg` so that `<$T>::MIN` will negate to itself rather + // than panicking. + let negative_n = n.wrapping_neg(); + + // Zero negated will still be nonnegative, so ignore it in this + // negative section. + if negative_n < 0 { + assert_eq!( + negative_n.checked_isqrt(), + None, + "`({negative_n}).checked_isqrt()` should be `None`, as {negative_n} is negative.", + ); + + std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| (-n).isqrt())).expect_err( + &format!("`({negative_n}).isqrt()` should have panicked, as {negative_n} is negative.") + ); + } + } + }; +} + +macro_rules! unsigned_check { + ($T:ident) => { + /// This takes an input and, if it's nonzero, checks that `isqrt` + /// produces the same numeric value for both + #[doc = concat!("`", stringify!($T), "` and ")] + #[doc = concat!("`NonZero<", stringify!($T), ">`.")] + fn isqrt_consistency_check(n: $T) { + // Zero cannot be turned into a `NonZero` value, so ignore it in + // this nonzero section. + if n > 0 { + assert_eq!( + n.isqrt(), + core::num::NonZero::<$T>::new(n) + .expect( + "Was not able to create a new `NonZero` value from a nonzero number." + ) + .isqrt() + .get(), + "`{n}.isqrt` should match `NonZero`'s `{n}.isqrt().get()`.", + ); + } + } + }; +} + +tests!(signed_check: i8 i16 i32 i64 i128); +tests!(unsigned_check: u8 u16 u32 u64 u128); diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index dad46ad88fe19..b14fe0b22c311 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -27,6 +27,7 @@ mod const_from; mod dec2flt; mod flt2dec; mod int_log; +mod int_sqrt; mod ops; mod wrapping; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index c271ac1870624..72b53c60f7439 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -28,7 +28,6 @@ #![feature(decl_macro)] #![feature(maybe_uninit_write_slice)] #![feature(negative_impls)] -#![feature(new_uninit)] #![feature(panic_can_unwind)] #![feature(restricted_std)] #![feature(rustc_attrs)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 334c75df2315a..5f0144922ca69 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.121" } +compiler_builtins = { version = "0.1.123" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index 506d708d0d2eb..b436fe9929c36 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -250,9 +250,14 @@ impl f128 { /// /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is - /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations - /// is not generally guaranteed. See [specification of NaN bit - /// patterns](primitive@f32#nan-bit-patterns) for more info. + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 033a3d4500932..b2cd5fae9d04a 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -249,9 +249,14 @@ impl f16 { /// /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is - /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations - /// is not generally guaranteed. See [specification of NaN bit - /// patterns](primitive@f32#nan-bit-patterns) for more info. + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 35c2a77b5338d..cafbe9761da19 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -228,9 +228,14 @@ impl f32 { /// /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is - /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations - /// is not generally guaranteed. See [specification of NaN bit - /// patterns](primitive@f32#nan-bit-patterns) for more info. + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index c177f74a97e15..fba283e3a44bc 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -228,9 +228,14 @@ impl f64 { /// /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is - /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations - /// is not generally guaranteed. See [specification of NaN bit - /// patterns](primitive@f32#nan-bit-patterns) for more info. + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f65e9bc8d8b5a..bea8eda261968 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -362,7 +362,6 @@ #![feature(allocator_api)] #![feature(get_mut_unchecked)] #![feature(map_try_insert)] -#![feature(new_uninit)] #![feature(new_zeroed_alloc)] #![feature(slice_concat_trait)] #![feature(thin_box)] diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 2f5d75dc4bc23..b888eb7d95ca3 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -109,19 +109,15 @@ if #[cfg(not(target_vendor = "uwp"))] { } // Use raw-dylib to import ProcessPrng as we can't rely on there being an import library. -cfg_if::cfg_if! { -if #[cfg(not(target_vendor = "win7"))] { - #[cfg(target_arch = "x86")] - #[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")] - extern "system" { - pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; - } - #[cfg(not(target_arch = "x86"))] - #[link(name = "bcryptprimitives", kind = "raw-dylib")] - extern "system" { - pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; - } -}} +#[cfg(not(target_vendor = "win7"))] +#[cfg_attr( + target_arch = "x86", + link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated") +)] +#[cfg_attr(not(target_arch = "x86"), link(name = "bcryptprimitives", kind = "raw-dylib"))] +extern "system" { + pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; +} // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 6948670565662..dcd5cd7f6b9c7 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -4,6 +4,10 @@ all(target_arch = "arm", any(target_os = "linux", target_os = "android")), feature(stdarch_arm_feature_detection) )] +#![cfg_attr( + all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")), + feature(stdarch_aarch64_feature_detection) +)] #![cfg_attr( all(target_arch = "powerpc", target_os = "linux"), feature(stdarch_powerpc_feature_detection) @@ -36,21 +40,34 @@ fn aarch64_linux() { println!("bf16: {}", is_aarch64_feature_detected!("bf16")); println!("bti: {}", is_aarch64_feature_detected!("bti")); println!("crc: {}", is_aarch64_feature_detected!("crc")); + println!("cssc: {}", is_aarch64_feature_detected!("cssc")); println!("dit: {}", is_aarch64_feature_detected!("dit")); println!("dotprod: {}", is_aarch64_feature_detected!("dotprod")); println!("dpb2: {}", is_aarch64_feature_detected!("dpb2")); println!("dpb: {}", is_aarch64_feature_detected!("dpb")); + println!("ecv: {}", is_aarch64_feature_detected!("ecv")); println!("f32mm: {}", is_aarch64_feature_detected!("f32mm")); println!("f64mm: {}", is_aarch64_feature_detected!("f64mm")); + println!("faminmax: {}", is_aarch64_feature_detected!("faminmax")); println!("fcma: {}", is_aarch64_feature_detected!("fcma")); println!("fhm: {}", is_aarch64_feature_detected!("fhm")); + println!("flagm2: {}", is_aarch64_feature_detected!("flagm2")); println!("flagm: {}", is_aarch64_feature_detected!("flagm")); println!("fp16: {}", is_aarch64_feature_detected!("fp16")); + println!("fp8: {}", is_aarch64_feature_detected!("fp8")); + println!("fp8dot2: {}", is_aarch64_feature_detected!("fp8dot2")); + println!("fp8dot4: {}", is_aarch64_feature_detected!("fp8dot4")); + println!("fp8fma: {}", is_aarch64_feature_detected!("fp8fma")); + println!("fpmr: {}", is_aarch64_feature_detected!("fpmr")); println!("frintts: {}", is_aarch64_feature_detected!("frintts")); + println!("hbc: {}", is_aarch64_feature_detected!("hbc")); println!("i8mm: {}", is_aarch64_feature_detected!("i8mm")); println!("jsconv: {}", is_aarch64_feature_detected!("jsconv")); + println!("lse128: {}", is_aarch64_feature_detected!("lse128")); println!("lse2: {}", is_aarch64_feature_detected!("lse2")); println!("lse: {}", is_aarch64_feature_detected!("lse")); + println!("lut: {}", is_aarch64_feature_detected!("lut")); + println!("mops: {}", is_aarch64_feature_detected!("mops")); println!("mte: {}", is_aarch64_feature_detected!("mte")); println!("neon: {}", is_aarch64_feature_detected!("neon")); println!("paca: {}", is_aarch64_feature_detected!("paca")); @@ -58,20 +75,37 @@ fn aarch64_linux() { println!("pmull: {}", is_aarch64_feature_detected!("pmull")); println!("rand: {}", is_aarch64_feature_detected!("rand")); println!("rcpc2: {}", is_aarch64_feature_detected!("rcpc2")); + println!("rcpc3: {}", is_aarch64_feature_detected!("rcpc3")); println!("rcpc: {}", is_aarch64_feature_detected!("rcpc")); println!("rdm: {}", is_aarch64_feature_detected!("rdm")); println!("sb: {}", is_aarch64_feature_detected!("sb")); println!("sha2: {}", is_aarch64_feature_detected!("sha2")); println!("sha3: {}", is_aarch64_feature_detected!("sha3")); println!("sm4: {}", is_aarch64_feature_detected!("sm4")); + println!("sme-f16f16: {}", is_aarch64_feature_detected!("sme-f16f16")); + println!("sme-f64f64: {}", is_aarch64_feature_detected!("sme-f64f64")); + println!("sme-f8f16: {}", is_aarch64_feature_detected!("sme-f8f16")); + println!("sme-f8f32: {}", is_aarch64_feature_detected!("sme-f8f32")); + println!("sme-fa64: {}", is_aarch64_feature_detected!("sme-fa64")); + println!("sme-i16i64: {}", is_aarch64_feature_detected!("sme-i16i64")); + println!("sme-lutv2: {}", is_aarch64_feature_detected!("sme-lutv2")); + println!("sme2: {}", is_aarch64_feature_detected!("sme2")); + println!("sme2p1: {}", is_aarch64_feature_detected!("sme2p1")); + println!("sme: {}", is_aarch64_feature_detected!("sme")); println!("ssbs: {}", is_aarch64_feature_detected!("ssbs")); + println!("ssve-fp8dot2: {}", is_aarch64_feature_detected!("ssve-fp8dot2")); + println!("ssve-fp8dot4: {}", is_aarch64_feature_detected!("ssve-fp8dot4")); + println!("ssve-fp8fma: {}", is_aarch64_feature_detected!("ssve-fp8fma")); + println!("sve-b16b16: {}", is_aarch64_feature_detected!("sve-b16b16")); println!("sve2-aes: {}", is_aarch64_feature_detected!("sve2-aes")); println!("sve2-bitperm: {}", is_aarch64_feature_detected!("sve2-bitperm")); println!("sve2-sha3: {}", is_aarch64_feature_detected!("sve2-sha3")); println!("sve2-sm4: {}", is_aarch64_feature_detected!("sve2-sm4")); println!("sve2: {}", is_aarch64_feature_detected!("sve2")); + println!("sve2p1: {}", is_aarch64_feature_detected!("sve2p1")); println!("sve: {}", is_aarch64_feature_detected!("sve")); println!("tme: {}", is_aarch64_feature_detected!("tme")); + println!("wfxt: {}", is_aarch64_feature_detected!("wfxt")); // tidy-alphabetical-end } diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 4ee9fbc314263..a2bb03cd5ac81 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -313,7 +313,7 @@ lint_any!( RemoteTestServer, "src/tools/remote-test-server", "remote-test-server"; Rls, "src/tools/rls", "rls"; RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer"; - Rustdoc, "src/tools/rustdoc", "clippy"; + Rustdoc, "src/librustdoc", "clippy"; Rustfmt, "src/tools/rustfmt", "rustfmt"; RustInstaller, "src/tools/rust-installer", "rust-installer"; Tidy, "src/tools/tidy", "tidy"; diff --git a/src/doc/book b/src/doc/book index 04bc1396bb857..e7d217be2a75e 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 04bc1396bb857f35b5dda1d773c9571e1f253304 +Subproject commit e7d217be2a75ef1753f0988d6ccaba4d7e376259 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index aeeb287d41a03..eeba2cb9c37ab 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit aeeb287d41a0332c210da122bea8e0e91844ab3e +Subproject commit eeba2cb9c37ab74118a4fb5e5233f7397e4a91f8 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 019f3928d8b93..ff5d61d56f11e 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 019f3928d8b939ec71b63722dcc2e46330156441 +Subproject commit ff5d61d56f11e1986bfa9652c6aff7731576c37d diff --git a/src/doc/nomicon b/src/doc/nomicon index 6ecf95c5f2bfa..14649f15d232d 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 6ecf95c5f2bfa0e6314dfe282bf775fd1405f7e9 +Subproject commit 14649f15d232d509478206ee9ed5105641aa60d0 diff --git a/src/doc/reference b/src/doc/reference index 62cd0df95061b..0668397076da3 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 62cd0df95061ba0ac886333f5cd7f3012f149da1 +Subproject commit 0668397076da350c404dadcf07b6cbc433ad3743 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 8f94061936e49..859786c5bc993 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 8f94061936e492159f4f6c09c0f917a7521893ff +Subproject commit 859786c5bc99301bbc22fc631a5c2b341860da08 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 43d83780db545..fa928a6d19e16 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 43d83780db545a1ed6d45773312fc578987e3968 +Subproject commit fa928a6d19e1666d8d811dfe3fd35cdad3b4e459 diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs index c85c0ebe24451..312b7ba05d31c 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs +++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs @@ -1,7 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -Zmiri-disable-stacked-borrows // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -#![feature(new_uninit)] use std::mem::MaybeUninit; use std::ptr::null_mut; diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs index 9e2a430dd94f5..f1f308b37e7bf 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs +++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs @@ -1,7 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -Zmiri-disable-stacked-borrows // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -#![feature(new_uninit)] use std::ptr::null_mut; use std::sync::atomic::{AtomicPtr, Ordering}; diff --git a/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs b/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs index 54bea6c6908e3..79c97a5b75273 100644 --- a/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs +++ b/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs @@ -6,7 +6,6 @@ // run multiple times until one try returns true. // Spurious failure is possible, if you are really unlucky with // the RNG and always read the latest value from the store buffer. -#![feature(new_uninit)] use std::sync::atomic::*; use std::thread::spawn; diff --git a/src/tools/miri/tests/pass/rc.rs b/src/tools/miri/tests/pass/rc.rs index b1470dabc26bd..ce01e611b2ced 100644 --- a/src/tools/miri/tests/pass/rc.rs +++ b/src/tools/miri/tests/pass/rc.rs @@ -1,7 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(new_uninit)] #![feature(get_mut_unchecked)] #![allow(ambiguous_wide_pointer_comparisons)] diff --git a/src/tools/miri/tests/pass/slices.rs b/src/tools/miri/tests/pass/slices.rs index 0b9805681b494..459d04d6761c1 100644 --- a/src/tools/miri/tests/pass/slices.rs +++ b/src/tools/miri/tests/pass/slices.rs @@ -1,7 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(new_uninit)] #![feature(slice_as_chunks)] #![feature(slice_partition_dedup)] #![feature(layout_for_ptr)] diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 3b859fe98c5ab..1394675a9dc60 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -690,6 +690,7 @@ dependencies = [ "mdbook", "once_cell", "pathdiff", + "pulldown-cmark", "regex", "semver", "serde_json", diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 1b4596ae2cb57..1b2b63c3d1ac4 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -3,21 +3,21 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 -// The "+v8a" feature is matched as optional as it isn't added when we -// are targeting older LLVM versions. Once the min supported version -// is LLVM-14 we can remove the optional regex matching for this feature. +// The "+fpmr" feature is matched as optional as it is only an explicit +// feature in LLVM 18. Once the min supported version is LLVM-19 the optional +// regex matching for this feature can be removed. //@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 -// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } +// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" } +// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?))*}}" } //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 -// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } +// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 520cffc4b0268..9b6448fe5a033 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 201 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 239 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 103a7564a0f87..56423d8c30799 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.rs b/tests/ui/deriving/deriving-smart-pointer-expanded.rs index b78258c25290e..e48ad3dd4bc6c 100644 --- a/tests/ui/deriving/deriving-smart-pointer-expanded.rs +++ b/tests/ui/deriving/deriving-smart-pointer-expanded.rs @@ -20,3 +20,9 @@ where data: &'a mut T, x: core::marker::PhantomData, } + +#[derive(SmartPointer)] +#[repr(transparent)] +struct MyPointerWithoutPointee<'a, T: ?Sized> { + ptr: &'a T, +} diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.stdout b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout index 3c7e719818042..68ef17f2b0547 100644 --- a/tests/ui/deriving/deriving-smart-pointer-expanded.stdout +++ b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout @@ -42,3 +42,18 @@ impl<'a, Y, Z: MyTrait + MyTrait<__S>, T: ?Sized + MyTrait + MyTrait<__S>> ::core::ops::CoerceUnsized> for MyPointer2<'a, Y, Z, T, X> where Y: MyTrait, Y: MyTrait<__S> { } + +#[repr(transparent)] +struct MyPointerWithoutPointee<'a, T: ?Sized> { + ptr: &'a T, +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::DispatchFromDyn> for + MyPointerWithoutPointee<'a, T> { +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::CoerceUnsized> for + MyPointerWithoutPointee<'a, T> { +} diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.rs b/tests/ui/deriving/deriving-smart-pointer-neg.rs index 04f52a154fe42..f02fb56130fa7 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.rs +++ b/tests/ui/deriving/deriving-smart-pointer-neg.rs @@ -9,13 +9,6 @@ enum NotStruct<'a, T: ?Sized> { Variant(&'a T), } -#[derive(SmartPointer)] -//~^ ERROR: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits -#[repr(transparent)] -struct NoPointee<'a, T: ?Sized> { - ptr: &'a T, -} - #[derive(SmartPointer)] //~^ ERROR: `SmartPointer` can only be derived on `struct`s with at least one field #[repr(transparent)] @@ -30,6 +23,23 @@ struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); //~^ ERROR: lifetime parameter `'a` is never used //~| ERROR: type parameter `T` is never used +#[derive(SmartPointer)] +//~^ ERROR: `SmartPointer` can only be derived on `struct`s that are generic over at least one type +#[repr(transparent)] +struct NoGeneric<'a>(&'a u8); + +#[derive(SmartPointer)] +//~^ ERROR: exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits +#[repr(transparent)] +struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> { + a: (&'a T1, &'a T2), +} + +#[derive(SmartPointer)] +#[repr(transparent)] +struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B)); +//~^ ERROR: only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits + #[derive(SmartPointer)] //~^ ERROR: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]` struct NotTransparent<'a, #[pointee] T: ?Sized> { diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.stderr b/tests/ui/deriving/deriving-smart-pointer-neg.stderr index 8b0f91d41fb88..e7c2afc8b00c7 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.stderr +++ b/tests/ui/deriving/deriving-smart-pointer-neg.stderr @@ -6,7 +6,7 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) -error: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits +error: `SmartPointer` can only be derived on `struct`s with at least one field --> $DIR/deriving-smart-pointer-neg.rs:12:10 | LL | #[derive(SmartPointer)] @@ -22,7 +22,7 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) -error: `SmartPointer` can only be derived on `struct`s with at least one field +error: `SmartPointer` can only be derived on `struct`s that are generic over at least one type --> $DIR/deriving-smart-pointer-neg.rs:26:10 | LL | #[derive(SmartPointer)] @@ -30,8 +30,22 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) +error: exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits + --> $DIR/deriving-smart-pointer-neg.rs:31:10 + | +LL | #[derive(SmartPointer)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits + --> $DIR/deriving-smart-pointer-neg.rs:40:39 + | +LL | struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B)); + | ^ ^ + error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]` - --> $DIR/deriving-smart-pointer-neg.rs:33:10 + --> $DIR/deriving-smart-pointer-neg.rs:43:10 | LL | #[derive(SmartPointer)] | ^^^^^^^^^^^^ @@ -39,13 +53,13 @@ LL | #[derive(SmartPointer)] = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) error: `derive(SmartPointer)` requires T to be marked `?Sized` - --> $DIR/deriving-smart-pointer-neg.rs:41:36 + --> $DIR/deriving-smart-pointer-neg.rs:51:36 | LL | struct NoMaybeSized<'a, #[pointee] T> { | ^ error[E0392]: lifetime parameter `'a` is never used - --> $DIR/deriving-smart-pointer-neg.rs:22:16 + --> $DIR/deriving-smart-pointer-neg.rs:15:16 | LL | struct NoField<'a, #[pointee] T: ?Sized> {} | ^^ unused lifetime parameter @@ -53,7 +67,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/deriving-smart-pointer-neg.rs:22:31 + --> $DIR/deriving-smart-pointer-neg.rs:15:31 | LL | struct NoField<'a, #[pointee] T: ?Sized> {} | ^ unused type parameter @@ -61,7 +75,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {} = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: lifetime parameter `'a` is never used - --> $DIR/deriving-smart-pointer-neg.rs:29:20 + --> $DIR/deriving-smart-pointer-neg.rs:22:20 | LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | ^^ unused lifetime parameter @@ -69,13 +83,13 @@ LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/deriving-smart-pointer-neg.rs:29:35 + --> $DIR/deriving-smart-pointer-neg.rs:22:35 | LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.rs b/tests/ui/inference/detect-old-time-version-format_description-parse.rs new file mode 100644 index 0000000000000..453a795e7686b --- /dev/null +++ b/tests/ui/inference/detect-old-time-version-format_description-parse.rs @@ -0,0 +1,8 @@ +#![crate_name = "time"] + +fn main() { + let items = Box::new(vec![]); //~ ERROR E0282 + //~^ NOTE type must be known at this point + //~| NOTE this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` + items.into(); +} diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.stderr b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr new file mode 100644 index 0000000000000..2949a5dcfec9c --- /dev/null +++ b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for `Box>` + --> $DIR/detect-old-time-version-format_description-parse.rs:4:9 + | +LL | let items = Box::new(vec![]); + | ^^^^^ ---------------- type must be known at this point + | + = note: this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 94d79d56c5920..5c4fb8479324f 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -17,6 +17,7 @@ // gate-test-ermsb_target_feature // gate-test-bpf_target_feature // gate-test-aarch64_ver_target_feature +// gate-test-aarch64_unstable_target_feature // gate-test-csky_target_feature // gate-test-loongarch_target_feature // gate-test-lahfsahf_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index a69020e6864d2..37c5ed0168890 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:26:18 + --> $DIR/gate.rs:27:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/threads-sendsync/child-outlives-parent.rs b/tests/ui/threads-sendsync/child-outlives-parent.rs index 213fd008cd3de..e965bac5713ce 100644 --- a/tests/ui/threads-sendsync/child-outlives-parent.rs +++ b/tests/ui/threads-sendsync/child-outlives-parent.rs @@ -6,8 +6,8 @@ use std::thread; -fn child2(_s: String) { } +fn child2(_s: String) {} pub fn main() { - let _x = thread::spawn(move|| child2("hi".to_string())); + let _x = thread::spawn(move || child2("hi".to_string())); } diff --git a/tests/ui/threads-sendsync/clone-with-exterior.rs b/tests/ui/threads-sendsync/clone-with-exterior.rs index 67790367e27e4..9d5ac4b16aa66 100644 --- a/tests/ui/threads-sendsync/clone-with-exterior.rs +++ b/tests/ui/threads-sendsync/clone-with-exterior.rs @@ -7,14 +7,15 @@ use std::thread; struct Pair { a: isize, - b: isize + b: isize, } pub fn main() { - let z: Box<_> = Box::new(Pair { a : 10, b : 12}); + let z: Box<_> = Box::new(Pair { a: 10, b: 12 }); - thread::spawn(move|| { + thread::spawn(move || { assert_eq!(z.a, 10); assert_eq!(z.b, 12); - }).join(); + }) + .join(); } diff --git a/tests/ui/threads-sendsync/comm.rs b/tests/ui/threads-sendsync/comm.rs index 0c37fda8a3931..3eb68707e78f1 100644 --- a/tests/ui/threads-sendsync/comm.rs +++ b/tests/ui/threads-sendsync/comm.rs @@ -2,12 +2,12 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move || { child(&tx) }); + let t = thread::spawn(move || child(&tx)); let y = rx.recv().unwrap(); println!("received"); println!("{}", y); diff --git a/tests/ui/threads-sendsync/issue-24313.rs b/tests/ui/threads-sendsync/issue-24313.rs index 1ea862f1e7d6b..99c6c4a5e12de 100644 --- a/tests/ui/threads-sendsync/issue-24313.rs +++ b/tests/ui/threads-sendsync/issue-24313.rs @@ -2,14 +2,15 @@ //@ needs-threads //@ ignore-sgx no processes -use std::thread; -use std::env; use std::process::Command; +use std::{env, thread}; struct Handle(i32); impl Drop for Handle { - fn drop(&mut self) { panic!(); } + fn drop(&mut self) { + panic!(); + } } thread_local!(static HANDLE: Handle = Handle(0)); @@ -19,14 +20,15 @@ fn main() { if args.len() == 1 { let out = Command::new(&args[0]).arg("test").output().unwrap(); let stderr = std::str::from_utf8(&out.stderr).unwrap(); - assert!(stderr.contains("explicit panic"), - "bad failure message:\n{}\n", stderr); + assert!(stderr.contains("explicit panic"), "bad failure message:\n{}\n", stderr); } else { // TLS dtors are not always run on process exit thread::spawn(|| { HANDLE.with(|h| { println!("{}", h.0); }); - }).join().unwrap(); + }) + .join() + .unwrap(); } } diff --git a/tests/ui/threads-sendsync/issue-29488.rs b/tests/ui/threads-sendsync/issue-29488.rs index fbbd6b02a067d..5ce27faed7635 100644 --- a/tests/ui/threads-sendsync/issue-29488.rs +++ b/tests/ui/threads-sendsync/issue-29488.rs @@ -19,5 +19,7 @@ fn main() { thread::spawn(|| { FOO.with(|_| {}); println!("test1"); - }).join().unwrap(); + }) + .join() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/issue-4446.rs b/tests/ui/threads-sendsync/issue-4446.rs index aa2de51974b37..5652ad7de55b5 100644 --- a/tests/ui/threads-sendsync/issue-4446.rs +++ b/tests/ui/threads-sendsync/issue-4446.rs @@ -9,7 +9,10 @@ pub fn main() { tx.send("hello, world").unwrap(); - thread::spawn(move|| { + thread::spawn(move || { println!("{}", rx.recv().unwrap()); - }).join().ok().unwrap(); + }) + .join() + .ok() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/issue-4448.rs b/tests/ui/threads-sendsync/issue-4448.rs index b8324a8c43fb5..1adebd1e25286 100644 --- a/tests/ui/threads-sendsync/issue-4448.rs +++ b/tests/ui/threads-sendsync/issue-4448.rs @@ -7,7 +7,7 @@ use std::thread; pub fn main() { let (tx, rx) = channel::<&'static str>(); - let t = thread::spawn(move|| { + let t = thread::spawn(move || { assert_eq!(rx.recv().unwrap(), "hello, world"); }); diff --git a/tests/ui/threads-sendsync/issue-8827.rs b/tests/ui/threads-sendsync/issue-8827.rs index fa07a4ebc7d6d..57fc87db76869 100644 --- a/tests/ui/threads-sendsync/issue-8827.rs +++ b/tests/ui/threads-sendsync/issue-8827.rs @@ -1,12 +1,12 @@ //@ run-pass //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Receiver}; +use std::thread; fn periodical(n: isize) -> Receiver { let (chan, port) = channel(); - thread::spawn(move|| { + thread::spawn(move || { loop { for _ in 1..n { match chan.send(false) { @@ -16,7 +16,7 @@ fn periodical(n: isize) -> Receiver { } match chan.send(true) { Ok(()) => {} - Err(..) => break + Err(..) => break, } } }); @@ -25,7 +25,7 @@ fn periodical(n: isize) -> Receiver { fn integers() -> Receiver { let (chan, port) = channel(); - thread::spawn(move|| { + thread::spawn(move || { let mut i = 1; loop { match chan.send(i) { @@ -47,7 +47,7 @@ fn main() { (_, true, true) => println!("FizzBuzz"), (_, true, false) => println!("Fizz"), (_, false, true) => println!("Buzz"), - (i, false, false) => println!("{}", i) + (i, false, false) => println!("{}", i), } } } diff --git a/tests/ui/threads-sendsync/issue-9396.rs b/tests/ui/threads-sendsync/issue-9396.rs index 6b5907e5c1d09..b532ddf104dfd 100644 --- a/tests/ui/threads-sendsync/issue-9396.rs +++ b/tests/ui/threads-sendsync/issue-9396.rs @@ -3,12 +3,12 @@ #![allow(deprecated)] //@ needs-threads -use std::sync::mpsc::{TryRecvError, channel}; +use std::sync::mpsc::{channel, TryRecvError}; use std::thread; pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move||{ + let t = thread::spawn(move || { thread::sleep_ms(10); tx.send(()).unwrap(); }); @@ -16,7 +16,7 @@ pub fn main() { match rx.try_recv() { Ok(()) => break, Err(TryRecvError::Empty) => {} - Err(TryRecvError::Disconnected) => unreachable!() + Err(TryRecvError::Disconnected) => unreachable!(), } } t.join(); diff --git a/tests/ui/threads-sendsync/mpsc_stress.rs b/tests/ui/threads-sendsync/mpsc_stress.rs index f5354c60bfce9..fe0b47f3a842e 100644 --- a/tests/ui/threads-sendsync/mpsc_stress.rs +++ b/tests/ui/threads-sendsync/mpsc_stress.rs @@ -2,18 +2,12 @@ //@ compile-flags:--test //@ needs-threads -use std::sync::mpsc::channel; -use std::sync::mpsc::TryRecvError; -use std::sync::mpsc::RecvError; -use std::sync::mpsc::RecvTimeoutError; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::mpsc::{channel, RecvError, RecvTimeoutError, TryRecvError}; use std::sync::Arc; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; - use std::thread; use std::time::Duration; - /// Simple thread synchronization utility struct Barrier { // Not using mutex/condvar for precision @@ -42,7 +36,6 @@ impl Barrier { } } - fn shared_close_sender_does_not_lose_messages_iter() { let (tb, rb) = Barrier::new2(); @@ -71,7 +64,6 @@ fn shared_close_sender_does_not_lose_messages() { }); } - // https://github.com/rust-lang/rust/issues/39364 fn concurrent_recv_timeout_and_upgrade_iter() { // 1 us @@ -85,8 +77,8 @@ fn concurrent_recv_timeout_and_upgrade_iter() { match rx.recv_timeout(sleep) { Ok(_) => { break; - }, - Err(_) => {}, + } + Err(_) => {} } } }); @@ -105,7 +97,6 @@ fn concurrent_recv_timeout_and_upgrade() { }); } - fn concurrent_writes_iter() { const THREADS: usize = 4; const PER_THR: usize = 100; diff --git a/tests/ui/threads-sendsync/send-is-not-static-par-for.rs b/tests/ui/threads-sendsync/send-is-not-static-par-for.rs index b943b0c433da7..dd02166c0fa01 100644 --- a/tests/ui/threads-sendsync/send-is-not-static-par-for.rs +++ b/tests/ui/threads-sendsync/send-is-not-static-par-for.rs @@ -1,12 +1,13 @@ //@ run-pass #![allow(unused_imports)] -use std::thread; use std::sync::Mutex; +use std::thread; fn par_for(iter: I, f: F) - where I: Iterator, - I::Item: Send, - F: Fn(I::Item) + Sync +where + I: Iterator, + I::Item: Send, + F: Fn(I::Item) + Sync, { for item in iter { f(item) @@ -15,9 +16,7 @@ fn par_for(iter: I, f: F) fn sum(x: &[i32]) { let sum_lengths = Mutex::new(0); - par_for(x.windows(4), |x| { - *sum_lengths.lock().unwrap() += x.len() - }); + par_for(x.windows(4), |x| *sum_lengths.lock().unwrap() += x.len()); assert_eq!(*sum_lengths.lock().unwrap(), (x.len() - 3) * 4); } @@ -26,9 +25,7 @@ fn main() { let mut elements = [0; 20]; // iterators over references into this stack frame - par_for(elements.iter_mut().enumerate(), |(i, x)| { - *x = i as i32 - }); + par_for(elements.iter_mut().enumerate(), |(i, x)| *x = i as i32); sum(&elements) } diff --git a/tests/ui/threads-sendsync/send-resource.rs b/tests/ui/threads-sendsync/send-resource.rs index 3e1532b3132ee..c02a3717d3d75 100644 --- a/tests/ui/threads-sendsync/send-resource.rs +++ b/tests/ui/threads-sendsync/send-resource.rs @@ -6,11 +6,11 @@ //@ pretty-expanded FIXME #23616 //@ needs-threads -use std::thread; use std::sync::mpsc::channel; +use std::thread; struct test { - f: isize, + f: isize, } impl Drop for test { @@ -18,15 +18,13 @@ impl Drop for test { } fn test(f: isize) -> test { - test { - f: f - } + test { f: f } } pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move|| { + let t = thread::spawn(move || { let (tx2, rx2) = channel(); tx.send(tx2).unwrap(); diff --git a/tests/ui/threads-sendsync/send-type-inference.rs b/tests/ui/threads-sendsync/send-type-inference.rs index 287b3d567aec8..7608c19b5758e 100644 --- a/tests/ui/threads-sendsync/send-type-inference.rs +++ b/tests/ui/threads-sendsync/send-type-inference.rs @@ -9,11 +9,11 @@ use std::sync::mpsc::{channel, Sender}; // tests that ctrl's type gets inferred properly struct Command { key: K, - val: V + val: V, } -fn cache_server(mut tx: Sender>>) { +fn cache_server(mut tx: Sender>>) { let (tx1, _rx) = channel(); tx.send(tx1); } -pub fn main() { } +pub fn main() {} diff --git a/tests/ui/threads-sendsync/send_str_hashmap.rs b/tests/ui/threads-sendsync/send_str_hashmap.rs index 9cbb0bed4473f..2675b16219094 100644 --- a/tests/ui/threads-sendsync/send_str_hashmap.rs +++ b/tests/ui/threads-sendsync/send_str_hashmap.rs @@ -1,9 +1,7 @@ //@ run-pass -use std::collections::HashMap; use std::borrow::Cow; - -use std::borrow::Cow::Borrowed as B; -use std::borrow::Cow::Owned as O; +use std::borrow::Cow::{Borrowed as B, Owned as O}; +use std::collections::HashMap; type SendStr = Cow<'static, str>; diff --git a/tests/ui/threads-sendsync/send_str_treemap.rs b/tests/ui/threads-sendsync/send_str_treemap.rs index cc1f560f69b2f..3e0eace339953 100644 --- a/tests/ui/threads-sendsync/send_str_treemap.rs +++ b/tests/ui/threads-sendsync/send_str_treemap.rs @@ -1,8 +1,7 @@ //@ run-pass -use std::collections::BTreeMap; use std::borrow::Cow; - -use std::borrow::Cow::{Owned as O, Borrowed as B}; +use std::borrow::Cow::{Borrowed as B, Owned as O}; +use std::collections::BTreeMap; type SendStr = Cow<'static, str>; @@ -51,8 +50,8 @@ fn main() { assert_eq!(map.get(&O("def".to_string())), Some(&d)); assert!(map.remove(&B("foo")).is_some()); - assert_eq!(map.into_iter().map(|(k, v)| format!("{}{}", k, v)) - .collect::>() - .concat(), - "abc50bcd51cde52def53".to_string()); + assert_eq!( + map.into_iter().map(|(k, v)| format!("{}{}", k, v)).collect::>().concat(), + "abc50bcd51cde52def53".to_string() + ); } diff --git a/tests/ui/threads-sendsync/sendable-class.rs b/tests/ui/threads-sendsync/sendable-class.rs index 3ee1b60a04a99..8e5e76d826a06 100644 --- a/tests/ui/threads-sendsync/sendable-class.rs +++ b/tests/ui/threads-sendsync/sendable-class.rs @@ -11,15 +11,12 @@ use std::sync::mpsc::channel; struct foo { - i: isize, - j: char, + i: isize, + j: char, } -fn foo(i:isize, j: char) -> foo { - foo { - i: i, - j: j - } +fn foo(i: isize, j: char) -> foo { + foo { i: i, j: j } } pub fn main() { diff --git a/tests/ui/threads-sendsync/sendfn-is-a-block.rs b/tests/ui/threads-sendsync/sendfn-is-a-block.rs index f01b440424aaf..9afa1c47b65d9 100644 --- a/tests/ui/threads-sendsync/sendfn-is-a-block.rs +++ b/tests/ui/threads-sendsync/sendfn-is-a-block.rs @@ -1,7 +1,9 @@ //@ run-pass - -fn test(f: F) -> usize where F: FnOnce(usize) -> usize { +fn test(f: F) -> usize +where + F: FnOnce(usize) -> usize, +{ return f(22); } diff --git a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs index 63cf3ff40490d..79a71e968f98b 100644 --- a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs +++ b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs @@ -3,19 +3,24 @@ use std::thread; -pub fn main() { test05(); } +pub fn main() { + test05(); +} -fn test05_start(f: F) { +fn test05_start(f: F) { f(22); } fn test05() { let three: Box<_> = Box::new(3); - let fn_to_send = move|n:isize| { + let fn_to_send = move |n: isize| { println!("{}", *three + n); // will copy x into the closure assert_eq!(*three, 3); }; - thread::spawn(move|| { + thread::spawn(move || { test05_start(fn_to_send); - }).join().ok().unwrap(); + }) + .join() + .ok() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/spawn-fn.rs b/tests/ui/threads-sendsync/spawn-fn.rs index e4d83b53f3cfa..558c2d515aace 100644 --- a/tests/ui/threads-sendsync/spawn-fn.rs +++ b/tests/ui/threads-sendsync/spawn-fn.rs @@ -10,9 +10,9 @@ fn x(s: String, n: isize) { } pub fn main() { - let t1 = thread::spawn(|| x("hello from first spawned fn".to_string(), 65) ); - let t2 = thread::spawn(|| x("hello from second spawned fn".to_string(), 66) ); - let t3 = thread::spawn(|| x("hello from third spawned fn".to_string(), 67) ); + let t1 = thread::spawn(|| x("hello from first spawned fn".to_string(), 65)); + let t2 = thread::spawn(|| x("hello from second spawned fn".to_string(), 66)); + let t3 = thread::spawn(|| x("hello from third spawned fn".to_string(), 67)); let mut i = 30; while i > 0 { i = i - 1; diff --git a/tests/ui/threads-sendsync/spawn-types.rs b/tests/ui/threads-sendsync/spawn-types.rs index 2a7a9e2f49732..e53385aa7149b 100644 --- a/tests/ui/threads-sendsync/spawn-types.rs +++ b/tests/ui/threads-sendsync/spawn-types.rs @@ -4,13 +4,13 @@ //@ needs-threads /* - Make sure we can spawn tasks that take different types of - parameters. This is based on a test case for #520 provided by Rob - Arnold. - */ + Make sure we can spawn tasks that take different types of + parameters. This is based on a test case for #520 provided by Rob + Arnold. +*/ -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; type ctx = Sender; @@ -20,6 +20,6 @@ fn iotask(_tx: &ctx, ip: String) { pub fn main() { let (tx, _rx) = channel::(); - let t = thread::spawn(move|| iotask(&tx, "localhost".to_string()) ); + let t = thread::spawn(move || iotask(&tx, "localhost".to_string())); t.join().ok().unwrap(); } diff --git a/tests/ui/threads-sendsync/spawn.rs b/tests/ui/threads-sendsync/spawn.rs index c7b344b9f7581..c9f7c40ddb886 100644 --- a/tests/ui/threads-sendsync/spawn.rs +++ b/tests/ui/threads-sendsync/spawn.rs @@ -4,7 +4,10 @@ use std::thread; pub fn main() { - thread::spawn(move|| child(10)).join().ok().unwrap(); + thread::spawn(move || child(10)).join().ok().unwrap(); } -fn child(i: isize) { println!("{}", i); assert_eq!(i, 10); } +fn child(i: isize) { + println!("{}", i); + assert_eq!(i, 10); +} diff --git a/tests/ui/threads-sendsync/spawn2.rs b/tests/ui/threads-sendsync/spawn2.rs index 8278fec1885b9..02dff2a3483dd 100644 --- a/tests/ui/threads-sendsync/spawn2.rs +++ b/tests/ui/threads-sendsync/spawn2.rs @@ -4,7 +4,7 @@ use std::thread; pub fn main() { - let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); + let t = thread::spawn(move || child((10, 20, 30, 40, 50, 60, 70, 80, 90))); t.join().ok().unwrap(); // forget Err value, since it doesn't implement Debug } diff --git a/tests/ui/threads-sendsync/sync-send-in-std.rs b/tests/ui/threads-sendsync/sync-send-in-std.rs index 3a97cbb0c6843..ddf026236a8ed 100644 --- a/tests/ui/threads-sendsync/sync-send-in-std.rs +++ b/tests/ui/threads-sendsync/sync-send-in-std.rs @@ -6,8 +6,16 @@ use std::net::ToSocketAddrs; -fn is_sync(_: T) where T: Sync {} -fn is_send(_: T) where T: Send {} +fn is_sync(_: T) +where + T: Sync, +{ +} +fn is_send(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $($iter:ident),+) => ({ diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs index 3b8fdb60acf5f..51d5e294b38aa 100644 --- a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs +++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs @@ -3,18 +3,20 @@ #![allow(warnings)] #![feature(drain, collections_bound, btree_range)] -use std::collections::BinaryHeap; -use std::collections::{BTreeMap, BTreeSet}; -use std::collections::LinkedList; -use std::collections::VecDeque; -use std::collections::HashMap; -use std::collections::HashSet; - +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; use std::mem; use std::ops::Bound::Included; -fn is_sync(_: T) where T: Sync {} -fn is_send(_: T) where T: Send {} +fn is_sync(_: T) +where + T: Sync, +{ +} +fn is_send(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $($iter:ident),+) => ({ diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs index 4c77b5d2ad889..512c81a85fcaf 100644 --- a/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs +++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs @@ -5,8 +5,16 @@ use std::iter::{empty, once, repeat}; -fn is_sync(_: T) where T: Sync {} -fn is_send(_: T) where T: Send {} +fn is_sync(_: T) +where + T: Sync, +{ +} +fn is_send(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $iter:ident) => ({ @@ -43,12 +51,12 @@ macro_rules! all_sync_send_mutable_ref { } macro_rules! is_sync_send { - ($ctor:expr) => ({ + ($ctor:expr) => {{ let x = $ctor; is_sync(x); let y = $ctor; is_send(y); - }) + }}; } fn main() { @@ -63,24 +71,26 @@ fn main() { let a = [1]; let b = [2]; - all_sync_send!(a.iter(), - cloned, - cycle, - chain([2].iter()), - zip([2].iter()), - map(|_| 1), - filter(|_| true), - filter_map(|_| Some(1)), - enumerate, - peekable, - skip_while(|_| true), - take_while(|_| true), - skip(1), - take(1), - scan(1, |_, _| Some(1)), - flat_map(|_| b.iter()), - fuse, - inspect(|_| ())); + all_sync_send!( + a.iter(), + cloned, + cycle, + chain([2].iter()), + zip([2].iter()), + map(|_| 1), + filter(|_| true), + filter_map(|_| Some(1)), + enumerate, + peekable, + skip_while(|_| true), + take_while(|_| true), + skip(1), + take(1), + scan(1, |_, _| Some(1)), + flat_map(|_| b.iter()), + fuse, + inspect(|_| ()) + ); is_sync_send!((1..).step_by(2)); is_sync_send!((1..2).step_by(2)); diff --git a/tests/ui/threads-sendsync/task-comm-0.rs b/tests/ui/threads-sendsync/task-comm-0.rs index 50f2b59189481..c4fe36e770d17 100644 --- a/tests/ui/threads-sendsync/task-comm-0.rs +++ b/tests/ui/threads-sendsync/task-comm-0.rs @@ -2,12 +2,14 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { test05(); } +pub fn main() { + test05(); +} -fn test05_start(tx : &Sender) { +fn test05_start(tx: &Sender) { tx.send(10).unwrap(); println!("sent 10"); tx.send(20).unwrap(); @@ -18,7 +20,7 @@ fn test05_start(tx : &Sender) { fn test05() { let (tx, rx) = channel(); - let t = thread::spawn(move|| { test05_start(&tx) }); + let t = thread::spawn(move || test05_start(&tx)); let mut value: isize = rx.recv().unwrap(); println!("{}", value); value = rx.recv().unwrap(); diff --git a/tests/ui/threads-sendsync/task-comm-1.rs b/tests/ui/threads-sendsync/task-comm-1.rs index 41592bd916b4e..75d9e887cd124 100644 --- a/tests/ui/threads-sendsync/task-comm-1.rs +++ b/tests/ui/threads-sendsync/task-comm-1.rs @@ -4,11 +4,15 @@ use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn start() { println!("Started / Finished task."); } +fn start() { + println!("Started / Finished task."); +} fn test00() { - thread::spawn(move|| start() ).join(); + thread::spawn(move || start()).join(); println!("Completing."); } diff --git a/tests/ui/threads-sendsync/task-comm-10.rs b/tests/ui/threads-sendsync/task-comm-10.rs index 844652c0dde49..44c31aeed7765 100644 --- a/tests/ui/threads-sendsync/task-comm-10.rs +++ b/tests/ui/threads-sendsync/task-comm-10.rs @@ -3,8 +3,8 @@ #![allow(unused_mut)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; fn start(tx: &Sender>) { let (tx2, rx) = channel(); @@ -22,7 +22,7 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let child = thread::spawn(move|| { start(&tx) }); + let child = thread::spawn(move || start(&tx)); let mut c = rx.recv().unwrap(); c.send("A".to_string()).unwrap(); diff --git a/tests/ui/threads-sendsync/task-comm-11.rs b/tests/ui/threads-sendsync/task-comm-11.rs index 199082fda96de..7c349c716fa35 100644 --- a/tests/ui/threads-sendsync/task-comm-11.rs +++ b/tests/ui/threads-sendsync/task-comm-11.rs @@ -13,9 +13,7 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let child = thread::spawn(move|| { - start(&tx) - }); + let child = thread::spawn(move || start(&tx)); let _tx = rx.recv().unwrap(); child.join(); } diff --git a/tests/ui/threads-sendsync/task-comm-12.rs b/tests/ui/threads-sendsync/task-comm-12.rs index 7be7ec4c988b1..95c5d5c45efc6 100644 --- a/tests/ui/threads-sendsync/task-comm-12.rs +++ b/tests/ui/threads-sendsync/task-comm-12.rs @@ -5,15 +5,17 @@ use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn start(_task_number: isize) { println!("Started / Finished task."); } +fn start(_task_number: isize) { + println!("Started / Finished task."); +} fn test00() { let i: isize = 0; - let mut result = thread::spawn(move|| { - start(i) - }); + let mut result = thread::spawn(move || start(i)); // Sleep long enough for the thread to finish. let mut i = 0_usize; diff --git a/tests/ui/threads-sendsync/task-comm-13.rs b/tests/ui/threads-sendsync/task-comm-13.rs index 414e6e0db76da..88ea3cbff0815 100644 --- a/tests/ui/threads-sendsync/task-comm-13.rs +++ b/tests/ui/threads-sendsync/task-comm-13.rs @@ -7,12 +7,15 @@ use std::thread; fn start(tx: &Sender, start: isize, number_of_messages: isize) { let mut i: isize = 0; - while i< number_of_messages { tx.send(start + i).unwrap(); i += 1; } + while i < number_of_messages { + tx.send(start + i).unwrap(); + i += 1; + } } pub fn main() { println!("Check that we don't deadlock."); let (tx, rx) = channel(); - let _ = thread::spawn(move|| { start(&tx, 0, 10) }).join(); + let _ = thread::spawn(move || start(&tx, 0, 10)).join(); println!("Joined task"); } diff --git a/tests/ui/threads-sendsync/task-comm-14.rs b/tests/ui/threads-sendsync/task-comm-14.rs index 54deb221294ae..ff4ffd2968da3 100644 --- a/tests/ui/threads-sendsync/task-comm-14.rs +++ b/tests/ui/threads-sendsync/task-comm-14.rs @@ -13,7 +13,10 @@ pub fn main() { while (i > 0) { println!("{}", i); let tx = tx.clone(); - thread::spawn({let i = i; move|| { child(i, &tx) }}); + thread::spawn({ + let i = i; + move || child(i, &tx) + }); i = i - 1; } diff --git a/tests/ui/threads-sendsync/task-comm-15.rs b/tests/ui/threads-sendsync/task-comm-15.rs index f487bf3cc84b3..1308446893b86 100644 --- a/tests/ui/threads-sendsync/task-comm-15.rs +++ b/tests/ui/threads-sendsync/task-comm-15.rs @@ -20,9 +20,7 @@ pub fn main() { // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! let (tx, rx) = channel(); - let t = thread::spawn(move|| { - start(&tx, 10) - }); + let t = thread::spawn(move || start(&tx, 10)); rx.recv(); t.join(); } diff --git a/tests/ui/threads-sendsync/task-comm-16.rs b/tests/ui/threads-sendsync/task-comm-16.rs index 3b0fec11acd1b..e76f7bedc93f1 100644 --- a/tests/ui/threads-sendsync/task-comm-16.rs +++ b/tests/ui/threads-sendsync/task-comm-16.rs @@ -3,15 +3,19 @@ #![allow(unused_parens)] #![allow(non_camel_case_types)] -use std::sync::mpsc::channel; use std::cmp; +use std::sync::mpsc::channel; // Tests of ports and channels on various types fn test_rec() { - struct R {val0: isize, val1: u8, val2: char} + struct R { + val0: isize, + val1: u8, + val2: char, + } let (tx, rx) = channel(); - let r0: R = R {val0: 0, val1: 1, val2: '2'}; + let r0: R = R { val0: 0, val1: 1, val2: '2' }; tx.send(r0).unwrap(); let mut r1: R; r1 = rx.recv().unwrap(); @@ -45,34 +49,29 @@ fn test_str() { enum t { tag1, tag2(isize), - tag3(isize, u8, char) + tag3(isize, u8, char), } impl cmp::PartialEq for t { fn eq(&self, other: &t) -> bool { match *self { - t::tag1 => { - match (*other) { - t::tag1 => true, - _ => false - } - } - t::tag2(e0a) => { - match (*other) { - t::tag2(e0b) => e0a == e0b, - _ => false - } - } - t::tag3(e0a, e1a, e2a) => { - match (*other) { - t::tag3(e0b, e1b, e2b) => - e0a == e0b && e1a == e1b && e2a == e2b, - _ => false - } - } + t::tag1 => match (*other) { + t::tag1 => true, + _ => false, + }, + t::tag2(e0a) => match (*other) { + t::tag2(e0b) => e0a == e0b, + _ => false, + }, + t::tag3(e0a, e1a, e2a) => match (*other) { + t::tag3(e0b, e1b, e2b) => e0a == e0b && e1a == e1b && e2a == e2b, + _ => false, + }, } } - fn ne(&self, other: &t) -> bool { !(*self).eq(other) } + fn ne(&self, other: &t) -> bool { + !(*self).eq(other) + } } fn test_tag() { diff --git a/tests/ui/threads-sendsync/task-comm-17.rs b/tests/ui/threads-sendsync/task-comm-17.rs index 687322d4dc963..a545beee59913 100644 --- a/tests/ui/threads-sendsync/task-comm-17.rs +++ b/tests/ui/threads-sendsync/task-comm-17.rs @@ -9,9 +9,8 @@ use std::thread; -fn f() { -} +fn f() {} pub fn main() { - thread::spawn(move|| f() ).join(); + thread::spawn(move || f()).join(); } diff --git a/tests/ui/threads-sendsync/task-comm-3.rs b/tests/ui/threads-sendsync/task-comm-3.rs index 26f3eaf9dc6c4..565d97596c76b 100644 --- a/tests/ui/threads-sendsync/task-comm-3.rs +++ b/tests/ui/threads-sendsync/task-comm-3.rs @@ -2,10 +2,13 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } +pub fn main() { + println!("===== WITHOUT THREADS ====="); + test00(); +} fn test00_start(ch: &Sender, message: isize, count: isize) { println!("Starting test00_start"); @@ -34,9 +37,7 @@ fn test00() { let tx = tx.clone(); results.push(thread::spawn({ let i = i; - move|| { - test00_start(&tx, i, number_of_messages) - } + move || test00_start(&tx, i, number_of_messages) })); i = i + 1; } @@ -53,7 +54,9 @@ fn test00() { } // Join spawned threads... - for r in results { r.join(); } + for r in results { + r.join(); + } println!("Completed: Final number is: "); println!("{}", sum); diff --git a/tests/ui/threads-sendsync/task-comm-4.rs b/tests/ui/threads-sendsync/task-comm-4.rs index 1210cee558211..6223f6a1ded11 100644 --- a/tests/ui/threads-sendsync/task-comm-4.rs +++ b/tests/ui/threads-sendsync/task-comm-4.rs @@ -3,7 +3,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let mut r: isize = 0; diff --git a/tests/ui/threads-sendsync/task-comm-5.rs b/tests/ui/threads-sendsync/task-comm-5.rs index e07aa18c24dff..e008b28f56ca6 100644 --- a/tests/ui/threads-sendsync/task-comm-5.rs +++ b/tests/ui/threads-sendsync/task-comm-5.rs @@ -2,7 +2,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let _r: isize = 0; @@ -10,8 +12,14 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: isize = 1000; let mut i: isize = 0; - while i < number_of_messages { tx.send(i + 0).unwrap(); i += 1; } + while i < number_of_messages { + tx.send(i + 0).unwrap(); + i += 1; + } i = 0; - while i < number_of_messages { sum += rx.recv().unwrap(); i += 1; } + while i < number_of_messages { + sum += rx.recv().unwrap(); + i += 1; + } assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); } diff --git a/tests/ui/threads-sendsync/task-comm-6.rs b/tests/ui/threads-sendsync/task-comm-6.rs index 6a7dea63993d0..60697c908af47 100644 --- a/tests/ui/threads-sendsync/task-comm-6.rs +++ b/tests/ui/threads-sendsync/task-comm-6.rs @@ -4,7 +4,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let mut r: isize = 0; @@ -38,5 +40,4 @@ fn test00() { assert_eq!(sum, 1998000); // assert (sum == 4 * ((number_of_messages * // (number_of_messages - 1)) / 2)); - } diff --git a/tests/ui/threads-sendsync/task-comm-7.rs b/tests/ui/threads-sendsync/task-comm-7.rs index d9b322daa66bf..bb59e4b4a722a 100644 --- a/tests/ui/threads-sendsync/task-comm-7.rs +++ b/tests/ui/threads-sendsync/task-comm-7.rs @@ -6,12 +6,16 @@ use std::sync::mpsc::{channel, Sender}; use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn test00_start(c: &Sender, start: isize, - number_of_messages: isize) { +fn test00_start(c: &Sender, start: isize, number_of_messages: isize) { let mut i: isize = 0; - while i < number_of_messages { c.send(start + i).unwrap(); i += 1; } + while i < number_of_messages { + c.send(start + i).unwrap(); + i += 1; + } } fn test00() { @@ -21,19 +25,19 @@ fn test00() { let number_of_messages: isize = 10; let tx2 = tx.clone(); - let t1 = thread::spawn(move|| { + let t1 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 0, number_of_messages); }); let tx2 = tx.clone(); - let t2 = thread::spawn(move|| { + let t2 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 1, number_of_messages); }); let tx2 = tx.clone(); - let t3 = thread::spawn(move|| { + let t3 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 2, number_of_messages); }); let tx2 = tx.clone(); - let t4 = thread::spawn(move|| { + let t4 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 3, number_of_messages); }); diff --git a/tests/ui/threads-sendsync/task-comm-9.rs b/tests/ui/threads-sendsync/task-comm-9.rs index 3e617e4a40c28..2e1f3cb673aa3 100644 --- a/tests/ui/threads-sendsync/task-comm-9.rs +++ b/tests/ui/threads-sendsync/task-comm-9.rs @@ -2,14 +2,19 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00_start(c: &Sender, number_of_messages: isize) { let mut i: isize = 0; - while i < number_of_messages { c.send(i + 0).unwrap(); i += 1; } + while i < number_of_messages { + c.send(i + 0).unwrap(); + i += 1; + } } fn test00() { @@ -18,7 +23,7 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: isize = 10; - let result = thread::spawn(move|| { + let result = thread::spawn(move || { test00_start(&tx, number_of_messages); }); diff --git a/tests/ui/threads-sendsync/task-life-0.rs b/tests/ui/threads-sendsync/task-life-0.rs index d3eca5d371fb8..f08a281e76c6d 100644 --- a/tests/ui/threads-sendsync/task-life-0.rs +++ b/tests/ui/threads-sendsync/task-life-0.rs @@ -6,9 +6,7 @@ use std::thread; pub fn main() { - thread::spawn(move|| child("Hello".to_string()) ).join(); + thread::spawn(move || child("Hello".to_string())).join(); } -fn child(_s: String) { - -} +fn child(_s: String) {} diff --git a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs index ea1c6a9b1081b..07d1a3d5c36ef 100644 --- a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs +++ b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs @@ -2,8 +2,8 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::channel; +use std::thread; pub fn main() { let (tx, rx) = channel::(); diff --git a/tests/ui/threads-sendsync/task-stderr.rs b/tests/ui/threads-sendsync/task-stderr.rs index cad10c7a7922c..3934084e02a0a 100644 --- a/tests/ui/threads-sendsync/task-stderr.rs +++ b/tests/ui/threads-sendsync/task-stderr.rs @@ -4,20 +4,21 @@ #![feature(internal_output_capture)] -use std::io; -use std::str; use std::sync::{Arc, Mutex}; -use std::thread; +use std::{io, str, thread}; fn main() { let data = Arc::new(Mutex::new(Vec::new())); - let res = thread::Builder::new().spawn({ - let data = data.clone(); - move || { - io::set_output_capture(Some(data)); - panic!("Hello, world!") - } - }).unwrap().join(); + let res = thread::Builder::new() + .spawn({ + let data = data.clone(); + move || { + io::set_output_capture(Some(data)); + panic!("Hello, world!") + } + }) + .unwrap() + .join(); assert!(res.is_err()); let output = data.lock().unwrap(); diff --git a/tests/ui/threads-sendsync/tcp-stress.rs b/tests/ui/threads-sendsync/tcp-stress.rs index 429a465731408..b2f76a55fb976 100644 --- a/tests/ui/threads-sendsync/tcp-stress.rs +++ b/tests/ui/threads-sendsync/tcp-stress.rs @@ -8,14 +8,14 @@ use std::io::prelude::*; use std::net::{TcpListener, TcpStream}; use std::process; use std::sync::mpsc::channel; -use std::time::Duration; use std::thread::{self, Builder}; +use std::time::Duration; const TARGET_CNT: usize = 200; fn main() { // This test has a chance to time out, try to not let it time out - thread::spawn(move|| -> () { + thread::spawn(move || -> () { thread::sleep(Duration::from_secs(30)); process::exit(1); }); @@ -38,12 +38,12 @@ fn main() { let mut spawned_cnt = 0; for _ in 0..TARGET_CNT { let tx = tx.clone(); - let res = Builder::new().stack_size(64 * 1024).spawn(move|| { + let res = Builder::new().stack_size(64 * 1024).spawn(move || { match TcpStream::connect(addr) { Ok(mut stream) => { let _ = stream.write(&[1]); let _ = stream.read(&mut [0]); - }, + } Err(..) => {} } tx.send(()).unwrap(); diff --git a/tests/ui/threads-sendsync/threads.rs b/tests/ui/threads-sendsync/threads.rs index f3ed7890364b5..ad4e4774ea058 100644 --- a/tests/ui/threads-sendsync/threads.rs +++ b/tests/ui/threads-sendsync/threads.rs @@ -7,10 +7,16 @@ use std::thread; pub fn main() { let mut i = 10; while i > 0 { - thread::spawn({let i = i; move|| child(i)}).join(); + thread::spawn({ + let i = i; + move || child(i) + }) + .join(); i = i - 1; } println!("main thread exiting"); } -fn child(x: isize) { println!("{}", x); } +fn child(x: isize) { + println!("{}", x); +} diff --git a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs index 8417665941232..983028681cde8 100644 --- a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs +++ b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs @@ -8,7 +8,9 @@ struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { HIT = true; } + unsafe { + HIT = true; + } } } @@ -17,6 +19,8 @@ thread_local!(static FOO: Foo = Foo); fn main() { std::thread::spawn(|| { FOO.with(|_| {}); - }).join().unwrap(); + }) + .join() + .unwrap(); assert!(unsafe { HIT }); } diff --git a/tests/ui/threads-sendsync/tls-init-on-init.rs b/tests/ui/threads-sendsync/tls-init-on-init.rs index fd764669e7f61..1cae19aae86c7 100644 --- a/tests/ui/threads-sendsync/tls-init-on-init.rs +++ b/tests/ui/threads-sendsync/tls-init-on-init.rs @@ -1,14 +1,14 @@ //@ run-pass #![allow(stable_features)] - //@ needs-threads - #![feature(thread_local_try_with)] -use std::thread; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::thread; -struct Foo { cnt: usize } +struct Foo { + cnt: usize, +} thread_local!(static FOO: Foo = Foo::init()); @@ -40,5 +40,7 @@ impl Drop for Foo { fn main() { thread::spawn(|| { FOO.with(|_| {}); - }).join().unwrap(); + }) + .join() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/tls-try-with.rs b/tests/ui/threads-sendsync/tls-try-with.rs index 72cee219a0abd..04071e77daa48 100644 --- a/tests/ui/threads-sendsync/tls-try-with.rs +++ b/tests/ui/threads-sendsync/tls-try-with.rs @@ -1,8 +1,6 @@ //@ run-pass #![allow(stable_features)] - //@ needs-threads - #![feature(thread_local_try_with)] use std::thread; @@ -16,15 +14,17 @@ thread_local!(static FOO: Foo = Foo {}); impl Drop for Foo { fn drop(&mut self) { assert!(FOO.try_with(|_| panic!("`try_with` closure run")).is_err()); - unsafe { DROP_RUN = true; } + unsafe { + DROP_RUN = true; + } } } fn main() { thread::spawn(|| { - assert_eq!(FOO.try_with(|_| { - 132 - }).expect("`try_with` failed"), 132); - }).join().unwrap(); + assert_eq!(FOO.try_with(|_| { 132 }).expect("`try_with` failed"), 132); + }) + .join() + .unwrap(); assert!(unsafe { DROP_RUN }); } diff --git a/tests/ui/threads-sendsync/trivial-message.rs b/tests/ui/threads-sendsync/trivial-message.rs index 8165737364384..d76ba0009dca2 100644 --- a/tests/ui/threads-sendsync/trivial-message.rs +++ b/tests/ui/threads-sendsync/trivial-message.rs @@ -2,9 +2,9 @@ #![allow(unused_must_use)] /* - This is about the simplest program that can successfully send a - message. - */ + This is about the simplest program that can successfully send a + message. +*/ use std::sync::mpsc::channel; diff --git a/tests/ui/threads-sendsync/unwind-resource.rs b/tests/ui/threads-sendsync/unwind-resource.rs index 3b1ab57b46e3e..ec27a1846fef2 100644 --- a/tests/ui/threads-sendsync/unwind-resource.rs +++ b/tests/ui/threads-sendsync/unwind-resource.rs @@ -21,9 +21,7 @@ impl Drop for complainer { fn complainer(tx: Sender) -> complainer { println!("Hello!"); - complainer { - tx: tx - } + complainer { tx: tx } } fn f(tx: Sender) { @@ -33,7 +31,7 @@ fn f(tx: Sender) { pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move|| f(tx.clone())); + let t = thread::spawn(move || f(tx.clone())); println!("hiiiiiiiii"); assert!(rx.recv().unwrap()); drop(t.join()); diff --git a/tests/ui/threads-sendsync/yield.rs b/tests/ui/threads-sendsync/yield.rs index 99d14bd92eaa5..c2b10b901cf82 100644 --- a/tests/ui/threads-sendsync/yield.rs +++ b/tests/ui/threads-sendsync/yield.rs @@ -17,5 +17,9 @@ pub fn main() { } fn child() { - println!("4"); thread::yield_now(); println!("5"); thread::yield_now(); println!("6"); + println!("4"); + thread::yield_now(); + println!("5"); + thread::yield_now(); + println!("6"); } diff --git a/tests/ui/threads-sendsync/yield1.rs b/tests/ui/threads-sendsync/yield1.rs index c965d2fc3033e..441e93ecf9065 100644 --- a/tests/ui/threads-sendsync/yield1.rs +++ b/tests/ui/threads-sendsync/yield1.rs @@ -13,4 +13,6 @@ pub fn main() { result.join(); } -fn child() { println!("2"); } +fn child() { + println!("2"); +} diff --git a/tests/ui/threads-sendsync/yield2.rs b/tests/ui/threads-sendsync/yield2.rs index 9502f0d33da51..2c24df44af249 100644 --- a/tests/ui/threads-sendsync/yield2.rs +++ b/tests/ui/threads-sendsync/yield2.rs @@ -4,5 +4,9 @@ use std::thread; pub fn main() { let mut i: isize = 0; - while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); } + while i < 100 { + i = i + 1; + println!("{}", i); + thread::yield_now(); + } }