diff options
186 files changed, 1697 insertions, 859 deletions
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index f4f35a4d2ee..a5d8fbfac61 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -3,15 +3,6 @@ //! `TokenStream`s represent syntactic objects before they are converted into ASTs. //! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s, //! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens. -//! -//! ## Ownership -//! -//! `TokenStream`s are persistent data structures constructed as ropes with reference -//! counted-children. In general, this means that calling an operation on a `TokenStream` -//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to -//! the original. This essentially coerces `TokenStream`s into "views" of their subparts, -//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking -//! ownership of the original. use std::borrow::Cow; use std::ops::Range; @@ -99,17 +90,6 @@ impl TokenTree { } } -impl<CTX> HashStable<CTX> for TokenStream -where - CTX: crate::HashStableContext, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - for sub_tt in self.iter() { - sub_tt.hash_stable(hcx, hasher); - } - } -} - /// A lazy version of [`AttrTokenStream`], which defers creation of an actual /// `AttrTokenStream` until it is needed. #[derive(Clone)] @@ -556,10 +536,6 @@ pub struct AttrsTarget { pub tokens: LazyAttrTokenStream, } -/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. -#[derive(Clone, Debug, Default, Encodable, Decodable)] -pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>); - /// Indicates whether a token can join with the following token to form a /// compound token. Used for conversions to `proc_macro::Spacing`. Also used to /// guide pretty-printing, which is where the `JointHidden` value (which isn't @@ -620,58 +596,9 @@ pub enum Spacing { JointHidden, } -impl TokenStream { - /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` - /// separating the two arguments with a comma for diagnostic suggestions. - pub fn add_comma(&self) -> Option<(TokenStream, Span)> { - // Used to suggest if a user writes `foo!(a b);` - let mut suggestion = None; - let mut iter = self.0.iter().enumerate().peekable(); - while let Some((pos, ts)) = iter.next() { - if let Some((_, next)) = iter.peek() { - let sp = match (&ts, &next) { - (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue, - ( - TokenTree::Token(token_left, Spacing::Alone), - TokenTree::Token(token_right, _), - ) if (token_left.is_non_reserved_ident() || token_left.is_lit()) - && (token_right.is_non_reserved_ident() || token_right.is_lit()) => - { - token_left.span - } - (TokenTree::Delimited(sp, ..), _) => sp.entire(), - _ => continue, - }; - let sp = sp.shrink_to_hi(); - let comma = TokenTree::token_alone(token::Comma, sp); - suggestion = Some((pos, comma, sp)); - } - } - if let Some((pos, comma, sp)) = suggestion { - let mut new_stream = Vec::with_capacity(self.0.len() + 1); - let parts = self.0.split_at(pos + 1); - new_stream.extend_from_slice(parts.0); - new_stream.push(comma); - new_stream.extend_from_slice(parts.1); - return Some((TokenStream::new(new_stream), sp)); - } - None - } -} - -impl FromIterator<TokenTree> for TokenStream { - fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self { - TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>()) - } -} - -impl Eq for TokenStream {} - -impl PartialEq<TokenStream> for TokenStream { - fn eq(&self, other: &TokenStream) -> bool { - self.iter().eq(other.iter()) - } -} +/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. +#[derive(Clone, Debug, Default, Encodable, Decodable)] +pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>); impl TokenStream { pub fn new(tts: Vec<TokenTree>) -> TokenStream { @@ -847,6 +774,68 @@ impl TokenStream { } } } + + /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` + /// separating the two arguments with a comma for diagnostic suggestions. + pub fn add_comma(&self) -> Option<(TokenStream, Span)> { + // Used to suggest if a user writes `foo!(a b);` + let mut suggestion = None; + let mut iter = self.0.iter().enumerate().peekable(); + while let Some((pos, ts)) = iter.next() { + if let Some((_, next)) = iter.peek() { + let sp = match (&ts, &next) { + (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue, + ( + TokenTree::Token(token_left, Spacing::Alone), + TokenTree::Token(token_right, _), + ) if (token_left.is_non_reserved_ident() || token_left.is_lit()) + && (token_right.is_non_reserved_ident() || token_right.is_lit()) => + { + token_left.span + } + (TokenTree::Delimited(sp, ..), _) => sp.entire(), + _ => continue, + }; + let sp = sp.shrink_to_hi(); + let comma = TokenTree::token_alone(token::Comma, sp); + suggestion = Some((pos, comma, sp)); + } + } + if let Some((pos, comma, sp)) = suggestion { + let mut new_stream = Vec::with_capacity(self.0.len() + 1); + let parts = self.0.split_at(pos + 1); + new_stream.extend_from_slice(parts.0); + new_stream.push(comma); + new_stream.extend_from_slice(parts.1); + return Some((TokenStream::new(new_stream), sp)); + } + None + } +} + +impl PartialEq<TokenStream> for TokenStream { + fn eq(&self, other: &TokenStream) -> bool { + self.iter().eq(other.iter()) + } +} + +impl Eq for TokenStream {} + +impl FromIterator<TokenTree> for TokenStream { + fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self { + TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>()) + } +} + +impl<CTX> HashStable<CTX> for TokenStream +where + CTX: crate::HashStableContext, +{ + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + for sub_tt in self.iter() { + sub_tt.hash_stable(hcx, hasher); + } + } } #[derive(Clone)] diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 31c698228ef..f96477e28cd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -58,7 +58,7 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser { Allow(Target::AssocTy), Allow(Target::AssocConst), Allow(Target::Variant), - Allow(Target::Impl { of_trait: false }), //FIXME This does not make sense + Allow(Target::Impl { of_trait: false }), Allow(Target::Crate), Error(Target::WherePredicate), ]); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 0e9dbfba658..caa3369f413 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -19,7 +19,9 @@ use rustc_middle::ty::{ self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility, }; use rustc_session::config::{self, DebugInfo, Lto}; -use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Symbol, hygiene}; +use rustc_span::{ + DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span, Symbol, hygiene, +}; use rustc_symbol_mangling::typeid_for_trait_ref; use rustc_target::spec::DebuginfoKind; use smallvec::smallvec; @@ -423,6 +425,14 @@ fn build_slice_type_di_node<'ll, 'tcx>( /// This function will look up the debuginfo node in the TypeMap. If it can't find it, it /// will create the node by dispatching to the corresponding `build_*_di_node()` function. pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { + spanned_type_di_node(cx, t, DUMMY_SP) +} + +pub(crate) fn spanned_type_di_node<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, + span: Span, +) -> &'ll DIType { let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t); if let Some(existing_di_node) = debug_context(cx).type_map.di_node_for_unique_id(unique_type_id) @@ -460,7 +470,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> ty::Adt(def, ..) => match def.adt_kind() { AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id), AdtKind::Union => build_union_type_di_node(cx, unique_type_id), - AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id), + AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span), }, ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 7c701926d2c..caff3586079 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -10,7 +10,7 @@ use rustc_middle::bug; use rustc_middle::mir::CoroutineLayout; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef}; -use rustc_span::Symbol; +use rustc_span::{Span, Symbol}; use super::type_map::{DINodeCreationResult, UniqueTypeId}; use super::{SmallVec, size_and_align_of}; @@ -30,13 +30,14 @@ mod native; pub(super) fn build_enum_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId<'tcx>, + span: Span, ) -> DINodeCreationResult<'ll> { let enum_type = unique_type_id.expect_ty(); let &ty::Adt(enum_adt_def, _) = enum_type.kind() else { bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type) }; - let enum_type_and_layout = cx.layout_of(enum_type); + let enum_type_and_layout = cx.spanned_layout_of(enum_type, span); if wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout) { return build_c_style_enum_di_node(cx, enum_adt_def, enum_type_and_layout); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 2c3a84499ac..79334f7f9fe 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -28,7 +28,9 @@ use rustc_target::spec::DebuginfoKind; use smallvec::SmallVec; use tracing::debug; -use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, type_di_node}; +use self::metadata::{ + UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, spanned_type_di_node, type_di_node, +}; use self::namespace::mangled_name_of_instance; use self::utils::{DIB, create_DIArray, is_node_local_to_unit}; use crate::builder::Builder; @@ -626,7 +628,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file); - let type_metadata = type_di_node(self, variable_type); + let type_metadata = spanned_type_di_node(self, variable_type, span); let (argument_index, dwarf_tag) = match variable_kind { ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index c88c534e135..e27e68d3662 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -202,14 +202,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { Some((normalized_ty, ocx.into_pending_obligations())) } - /// Returns the final type we ended up with, which may be an inference - /// variable (we will resolve it first, if we want). - pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> { - if resolve { - self.infcx.resolve_vars_if_possible(self.state.cur_ty) - } else { - self.state.cur_ty - } + /// Returns the final type we ended up with, which may be an unresolved + /// inference variable. + pub fn final_ty(&self) -> Ty<'tcx> { + self.state.cur_ty } pub fn step_count(&self) -> usize { diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 7af26623ce7..4fe77278706 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut obligations = PredicateObligations::new(); let targets = - steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false))); + steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty())); let steps: Vec<_> = steps .iter() .map(|&(source, kind)| { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 4200afb74e6..c6a4d78dcc8 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef); } - match autoderef.final_ty(false).kind() { + match autoderef.final_ty().kind() { ty::FnDef(def_id, _) => { let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi; self.check_call_abi(abi, call_expr.span); @@ -200,8 +200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs: &'tcx [hir::Expr<'tcx>], autoderef: &Autoderef<'a, 'tcx>, ) -> Option<CallStep<'tcx>> { - let adjusted_ty = - self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty()); // If the callee is a function pointer or a closure, then we're all set. match *adjusted_ty.kind() { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 940f0e3708d..a652e08905a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2918,7 +2918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Emits an error if we deref an infer variable, like calling `.field` on a base type // of `&_`. We can also use this to suppress unnecessary "missing field" errors that // will follow ambiguity errors. - let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty()); if let ty::Error(_) = final_ty.kind() { return final_ty; } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index bb4748b0565..ab584eb7c90 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -629,7 +629,7 @@ pub(crate) fn method_autoderef_steps<'tcx>( .collect(); (steps, autoderef_via_deref.reached_recursion_limit()) }; - let final_ty = autoderef_via_deref.final_ty(true); + let final_ty = autoderef_via_deref.final_ty(); let opt_bad_ty = match final_ty.kind() { ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy { reached_raw_pointer, diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index fedc75abe49..1125e984080 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -109,8 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { index_ty: Ty<'tcx>, index_expr: &hir::Expr<'_>, ) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { - let adjusted_ty = - self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty()); debug!( "try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \ index_ty={:?})", diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index cf0549fa668..5023b2740ef 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -29,6 +29,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::direct_use_of_rustc_type_ir)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(allocator_api)] @@ -51,7 +52,6 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(ptr_alignment_type)] -#![feature(round_char_boundary)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(sized_hierarchy)] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index d647ec28aae..ae6755f0764 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -17,6 +17,7 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] @@ -26,7 +27,6 @@ #![feature(map_try_insert)] #![feature(negative_impls)] #![feature(read_buf)] -#![feature(round_char_boundary)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] // tidy-alphabetical-end diff --git a/compiler/rustc_target/src/spec/base/managarm_mlibc.rs b/compiler/rustc_target/src/spec/base/managarm_mlibc.rs new file mode 100644 index 00000000000..da3856b212d --- /dev/null +++ b/compiler/rustc_target/src/spec/base/managarm_mlibc.rs @@ -0,0 +1,17 @@ +use crate::spec::{RelroLevel, TargetOptions, cvs}; + +pub(crate) fn opts() -> TargetOptions { + TargetOptions { + os: "managarm".into(), + env: "mlibc".into(), + dynamic_linking: true, + executables: true, + families: cvs!["unix"], + has_rpath: true, + position_independent_executables: true, + relro_level: RelroLevel::Full, + has_thread_local: true, + crt_static_respected: true, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index b368d93f007..be15da7329d 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -20,6 +20,7 @@ pub(crate) mod linux_ohos; pub(crate) mod linux_uclibc; pub(crate) mod linux_wasm; pub(crate) mod lynxos178; +pub(crate) mod managarm_mlibc; pub(crate) mod msvc; pub(crate) mod netbsd; pub(crate) mod nto_qnx; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c53d92bee9d..e97a9b9c776 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2032,6 +2032,10 @@ supported_targets! { ("i586-unknown-redox", i586_unknown_redox), ("x86_64-unknown-redox", x86_64_unknown_redox), + ("x86_64-unknown-managarm-mlibc", x86_64_unknown_managarm_mlibc), + ("aarch64-unknown-managarm-mlibc", aarch64_unknown_managarm_mlibc), + ("riscv64gc-unknown-managarm-mlibc", riscv64gc_unknown_managarm_mlibc), + ("i386-apple-ios", i386_apple_ios), ("x86_64-apple-ios", x86_64_apple_ios), ("aarch64-apple-ios", aarch64_apple_ios), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_managarm_mlibc.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_managarm_mlibc.rs new file mode 100644 index 00000000000..1fa9d7131c5 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_managarm_mlibc.rs @@ -0,0 +1,22 @@ +use crate::spec::{StackProbeType, Target, base}; + +pub(crate) fn target() -> Target { + let mut base = base::managarm_mlibc::opts(); + base.max_atomic_width = Some(128); + base.stack_probes = StackProbeType::Inline; + base.features = "+v8a".into(); + + Target { + llvm_target: "aarch64-unknown-managarm-mlibc".into(), + metadata: crate::spec::TargetMetadata { + description: Some("managarm/aarch64".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: base + } +} diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_managarm_mlibc.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_managarm_mlibc.rs new file mode 100644 index 00000000000..abf28310634 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_managarm_mlibc.rs @@ -0,0 +1,24 @@ +use crate::spec::{CodeModel, Target, TargetOptions, base}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "riscv64-unknown-managarm-mlibc".into(), + metadata: crate::spec::TargetMetadata { + description: Some("managarm/riscv64".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), + arch: "riscv64".into(), + options: TargetOptions { + code_model: Some(CodeModel::Medium), + cpu: "generic-rv64".into(), + features: "+m,+a,+f,+d,+c".into(), + llvm_abiname: "lp64d".into(), + max_atomic_width: Some(64), + ..base::managarm_mlibc::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_managarm_mlibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_managarm_mlibc.rs new file mode 100644 index 00000000000..359e38cb800 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_managarm_mlibc.rs @@ -0,0 +1,24 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base}; + +pub(crate) fn target() -> Target { + let mut base = base::managarm_mlibc::opts(); + base.cpu = "x86-64".into(); + base.max_atomic_width = Some(64); + base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); + base.stack_probes = StackProbeType::Inline; + + Target { + llvm_target: "x86_64-unknown-managarm-mlibc".into(), + metadata: crate::spec::TargetMetadata { + description: Some("managarm/amd64".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + options: base, + } +} diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 447af240a4b..bf446ae1ba4 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -24,7 +24,6 @@ #![feature(inplace_iteration)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] -#![feature(round_char_boundary)] #![feature(slice_partition_dedup)] #![feature(string_from_utf8_lossy_owned)] #![feature(string_remove_matches)] diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index c54df2e90b7..3afadbfe894 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -51,8 +51,7 @@ jobs: - target: aarch64-unknown-linux-gnu os: ubuntu-24.04-arm - target: aarch64-pc-windows-msvc - os: windows-2025 - build_only: 1 + os: windows-11-arm - target: arm-unknown-linux-gnueabi os: ubuntu-24.04 - target: arm-unknown-linux-gnueabihf diff --git a/library/compiler-builtins/builtins-test/benches/float_conv.rs b/library/compiler-builtins/builtins-test/benches/float_conv.rs index e0f488eb685..40c13d270ac 100644 --- a/library/compiler-builtins/builtins-test/benches/float_conv.rs +++ b/library/compiler-builtins/builtins-test/benches/float_conv.rs @@ -1,4 +1,3 @@ -#![allow(improper_ctypes)] #![cfg_attr(f128_enabled, feature(f128))] use builtins_test::float_bench; diff --git a/library/compiler-builtins/builtins-test/tests/addsub.rs b/library/compiler-builtins/builtins-test/tests/addsub.rs index abe7dde645e..f3334bd0e2d 100644 --- a/library/compiler-builtins/builtins-test/tests/addsub.rs +++ b/library/compiler-builtins/builtins-test/tests/addsub.rs @@ -1,4 +1,5 @@ #![allow(unused_macros)] +#![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] use builtins_test::*; @@ -115,28 +116,25 @@ macro_rules! float_sum { mod float_addsub { use super::*; + #[cfg(f16_enabled)] + float_sum! { + f16, __addhf3, __subhf3, Half, all(); + } + float_sum! { f32, __addsf3, __subsf3, Single, all(); f64, __adddf3, __subdf3, Double, all(); } -} - -#[cfg(f128_enabled)] -#[cfg(not(x86_no_sse))] -#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] -mod float_addsub_f128 { - use super::*; + #[cfg(f128_enabled)] + #[cfg(not(x86_no_sse))] + #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] float_sum! { f128, __addtf3, __subtf3, Quad, not(feature = "no-sys-f128"); } -} - -#[cfg(f128_enabled)] -#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] -mod float_addsub_f128_ppc { - use super::*; + #[cfg(f128_enabled)] + #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] float_sum! { f128, __addkf3, __subkf3, Quad, not(feature = "no-sys-f128"); } diff --git a/library/compiler-builtins/builtins-test/tests/cmp.rs b/library/compiler-builtins/builtins-test/tests/cmp.rs index a904dc5f7de..4b01b6ca1c7 100644 --- a/library/compiler-builtins/builtins-test/tests/cmp.rs +++ b/library/compiler-builtins/builtins-test/tests/cmp.rs @@ -1,5 +1,6 @@ #![allow(unused_macros)] #![allow(unreachable_code)] +#![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] use builtins_test::*; @@ -52,6 +53,26 @@ mod float_comparisons { } #[test] + #[cfg(f16_enabled)] + fn cmp_f16() { + use compiler_builtins::float::cmp::{ + __eqhf2, __gehf2, __gthf2, __lehf2, __lthf2, __nehf2, __unordhf2, + }; + + fuzz_float_2(N, |x: f16, y: f16| { + assert_eq!(__unordhf2(x, y) != 0, x.is_nan() || y.is_nan()); + cmp!(f16, x, y, Half, all(), + 1, __lthf2; + 1, __lehf2; + 1, __eqhf2; + -1, __gehf2; + -1, __gthf2; + 1, __nehf2; + ); + }); + } + + #[test] fn cmp_f32() { use compiler_builtins::float::cmp::{ __eqsf2, __gesf2, __gtsf2, __lesf2, __ltsf2, __nesf2, __unordsf2, diff --git a/library/compiler-builtins/builtins-test/tests/mul.rs b/library/compiler-builtins/builtins-test/tests/mul.rs index 3072b45dca0..bbf1157db42 100644 --- a/library/compiler-builtins/builtins-test/tests/mul.rs +++ b/library/compiler-builtins/builtins-test/tests/mul.rs @@ -1,5 +1,6 @@ -#![allow(unused_macros)] +#![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] +#![allow(unused_macros)] use builtins_test::*; @@ -117,6 +118,11 @@ macro_rules! float_mul { mod float_mul { use super::*; + #[cfg(f16_enabled)] + float_mul! { + f16, __mulhf3, Half, all(); + } + // FIXME(#616): Stop ignoring arches that don't have native support once fix for builtins is in // nightly. float_mul! { diff --git a/library/compiler-builtins/compiler-builtins/src/float/add.rs b/library/compiler-builtins/compiler-builtins/src/float/add.rs index 0cc362f705b..acdcd2ebe31 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/add.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/add.rs @@ -130,7 +130,7 @@ where return F::from_bits(MinInt::ZERO); } - // If partial cancellation occured, we need to left-shift the result + // If partial cancellation occurred, we need to left-shift the result // and adjust the exponent: if a_significand < implicit_bit << 3 { let shift = a_significand.leading_zeros() as i32 @@ -191,6 +191,11 @@ where } intrinsics! { + #[cfg(f16_enabled)] + pub extern "C" fn __addhf3(a: f16, b: f16) -> f16 { + add(a, b) + } + #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_fadd] pub extern "C" fn __addsf3(a: f32, b: f32) -> f32 { diff --git a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs index f1e54dc1c83..8ab39c2b591 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs @@ -115,6 +115,37 @@ fn unord<F: Float>(a: F, b: F) -> bool { a_abs > inf_rep || b_abs > inf_rep } +#[cfg(f16_enabled)] +intrinsics! { + pub extern "C" fn __lehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_le_abi() + } + + pub extern "C" fn __gehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_ge_abi() + } + + pub extern "C" fn __unordhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + unord(a, b) as crate::float::cmp::CmpResult + } + + pub extern "C" fn __eqhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_le_abi() + } + + pub extern "C" fn __lthf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_le_abi() + } + + pub extern "C" fn __nehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_le_abi() + } + + pub extern "C" fn __gthf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_ge_abi() + } +} + intrinsics! { pub extern "C" fn __lesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult { cmp(a, b).to_le_abi() diff --git a/library/compiler-builtins/compiler-builtins/src/float/mul.rs b/library/compiler-builtins/compiler-builtins/src/float/mul.rs index dbed3095cda..49a2414eb5c 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/mul.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/mul.rs @@ -180,6 +180,11 @@ where } intrinsics! { + #[cfg(f16_enabled)] + pub extern "C" fn __mulhf3(a: f16, b: f16) -> f16 { + mul(a, b) + } + #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_fmul] pub extern "C" fn __mulsf3(a: f32, b: f32) -> f32 { diff --git a/library/compiler-builtins/compiler-builtins/src/float/sub.rs b/library/compiler-builtins/compiler-builtins/src/float/sub.rs index a0fd9dff97f..48ef33b0b82 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/sub.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/sub.rs @@ -1,6 +1,11 @@ use crate::float::Float; intrinsics! { + #[cfg(f16_enabled)] + pub extern "C" fn __subhf3(a: f16, b: f16) -> f16 { + crate::float::add::__addhf3(a, f16::from_bits(b.to_bits() ^ f16::SIGN_MASK)) + } + #[arm_aeabi_alias = __aeabi_fsub] pub extern "C" fn __subsf3(a: f32, b: f32) -> f32 { crate::float::add::__addsf3(a, f32::from_bits(b.to_bits() ^ f32::SIGN_MASK)) diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index ca75f44e02a..b111dc0bd18 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -18,10 +18,6 @@ #![no_std] #![allow(unused_features)] #![allow(internal_features)] -// We use `u128` in a whole bunch of places which we currently agree with the -// compiler on ABIs and such, so we should be "good enough" for now and changes -// to the `u128` ABI will be reflected here. -#![allow(improper_ctypes, improper_ctypes_definitions)] // `mem::swap` cannot be used because it may generate references to memcpy in unoptimized code. #![allow(clippy::manual_swap)] // Support compiling on both stage0 and stage1 which may differ in supported stable features. diff --git a/library/compiler-builtins/compiler-builtins/src/probestack.rs b/library/compiler-builtins/compiler-builtins/src/probestack.rs index 9a18216da99..72975485a77 100644 --- a/library/compiler-builtins/compiler-builtins/src/probestack.rs +++ b/library/compiler-builtins/compiler-builtins/src/probestack.rs @@ -73,7 +73,7 @@ pub unsafe extern "custom" fn __rust_probestack() { // page needed. // // Note that we're also testing against `8(%rsp)` to account for the 8 - // bytes pushed on the stack orginally with our return address. Using + // bytes pushed on the stack originally with our return address. Using // `8(%rsp)` simulates us testing the stack pointer in the caller's // context. diff --git a/library/compiler-builtins/crates/symbol-check/src/main.rs b/library/compiler-builtins/crates/symbol-check/src/main.rs index 1312a717970..4e94552331a 100644 --- a/library/compiler-builtins/crates/symbol-check/src/main.rs +++ b/library/compiler-builtins/crates/symbol-check/src/main.rs @@ -9,7 +9,7 @@ use std::process::{Command, Stdio}; use object::read::archive::{ArchiveFile, ArchiveMember}; use object::{ - File as ObjFile, Object, ObjectSymbol, Symbol, SymbolKind, SymbolScope, SymbolSection, + File as ObjFile, Object, ObjectSection, ObjectSymbol, Symbol, SymbolKind, SymbolScope, }; use serde_json::Value; @@ -154,7 +154,7 @@ struct SymInfo { name: String, kind: SymbolKind, scope: SymbolScope, - section: SymbolSection, + section: String, is_undefined: bool, is_global: bool, is_local: bool, @@ -165,12 +165,22 @@ struct SymInfo { } impl SymInfo { - fn new(sym: &Symbol, member: &ArchiveMember) -> Self { + fn new(sym: &Symbol, obj: &ObjFile, member: &ArchiveMember) -> Self { + // Include the section name if possible. Fall back to the `Section` debug impl if not. + let section = sym.section(); + let section_name = sym + .section() + .index() + .and_then(|idx| obj.section_by_index(idx).ok()) + .and_then(|sec| sec.name().ok()) + .map(ToString::to_string) + .unwrap_or_else(|| format!("{section:?}")); + Self { name: sym.name().expect("missing name").to_owned(), kind: sym.kind(), scope: sym.scope(), - section: sym.section(), + section: section_name, is_undefined: sym.is_undefined(), is_global: sym.is_global(), is_local: sym.is_local(), @@ -192,22 +202,27 @@ fn verify_no_duplicates(archive: &Archive) { let mut dups = Vec::new(); let mut found_any = false; - archive.for_each_symbol(|symbol, member| { + archive.for_each_symbol(|symbol, obj, member| { // Only check defined globals if !symbol.is_global() || symbol.is_undefined() { return; } - let sym = SymInfo::new(&symbol, member); + let sym = SymInfo::new(&symbol, obj, member); // x86-32 includes multiple copies of thunk symbols if sym.name.starts_with("__x86.get_pc_thunk") { return; } + // GDB pretty printing symbols may show up more than once but are weak. + if sym.section == ".debug_gdb_scripts" && sym.is_weak { + return; + } + // Windows has symbols for literal numeric constants, string literals, and MinGW pseudo- // relocations. These are allowed to have repeated definitions. - let win_allowed_dup_pfx = ["__real@", "__xmm@", "??_C@_", ".refptr"]; + let win_allowed_dup_pfx = ["__real@", "__xmm@", "__ymm@", "??_C@_", ".refptr"]; if win_allowed_dup_pfx .iter() .any(|pfx| sym.name.starts_with(pfx)) @@ -244,7 +259,7 @@ fn verify_core_symbols(archive: &Archive) { let mut undefined = Vec::new(); let mut has_symbols = false; - archive.for_each_symbol(|symbol, member| { + archive.for_each_symbol(|symbol, obj, member| { has_symbols = true; // Find only symbols from `core` @@ -252,7 +267,7 @@ fn verify_core_symbols(archive: &Archive) { return; } - let sym = SymInfo::new(&symbol, member); + let sym = SymInfo::new(&symbol, obj, member); if sym.is_undefined { undefined.push(sym); } else { @@ -304,9 +319,9 @@ impl Archive { } /// For a given archive, do something with each symbol. - fn for_each_symbol(&self, mut f: impl FnMut(Symbol, &ArchiveMember)) { + fn for_each_symbol(&self, mut f: impl FnMut(Symbol, &ObjFile, &ArchiveMember)) { self.for_each_object(|obj, member| { - obj.symbols().for_each(|sym| f(sym, member)); + obj.symbols().for_each(|sym| f(sym, &obj, member)); }); } } diff --git a/library/compiler-builtins/etc/update-api-list.py b/library/compiler-builtins/etc/update-api-list.py index 28ff22f4cbb..76c75cbf4dc 100755 --- a/library/compiler-builtins/etc/update-api-list.py +++ b/library/compiler-builtins/etc/update-api-list.py @@ -34,7 +34,7 @@ def eprint(*args, **kwargs): @dataclass class Crate: - """Representation of public interfaces and function defintion locations in + """Representation of public interfaces and function definition locations in `libm`. """ diff --git a/library/compiler-builtins/libm/src/math/rem_pio2_large.rs b/library/compiler-builtins/libm/src/math/rem_pio2_large.rs index f1fdf3673a8..bb2c532916b 100644 --- a/library/compiler-builtins/libm/src/math/rem_pio2_large.rs +++ b/library/compiler-builtins/libm/src/math/rem_pio2_large.rs @@ -146,7 +146,7 @@ const PIO2: [f64; 8] = [ // x[i] = floor(z) // z = (z-x[i])*2**24 // -// y[] ouput result in an array of double precision numbers. +// y[] output result in an array of double precision numbers. // The dimension of y[] is: // 24-bit precision 1 // 53-bit precision 2 diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version index a4db05a8796..8489eacfcda 100644 --- a/library/compiler-builtins/rust-version +++ b/library/compiler-builtins/rust-version @@ -1 +1 @@ -82310651b93a594a3fd69015e1562186a080d94c +d36f964125163c2e698de5559efefb8217b8b7f0 diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 835ee57ce23..c4bb5ab7b21 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -41,8 +41,6 @@ pub use iter::IntoIter; /// /// Creating multiple copies of a `String`: /// ```rust -/// #![feature(array_repeat)] -/// /// use std::array; /// /// let string = "Hello there!".to_string(); @@ -50,7 +48,7 @@ pub use iter::IntoIter; /// assert_eq!(strings, ["Hello there!", "Hello there!"]); /// ``` #[inline] -#[unstable(feature = "array_repeat", issue = "126695")] +#[stable(feature = "array_repeat", since = "CURRENT_RUSTC_VERSION")] pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] { from_trusted_iterator(repeat_n(val, N)) } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 985e669c92d..3336d028e27 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -950,7 +950,11 @@ impl char { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_control(self) -> bool { - unicode::Cc(self) + // According to + // https://www.unicode.org/policies/stability_policy.html#Property_Value, + // the set of codepoints in `Cc` will never change. + // So we can just hard-code the patterns to match against instead of using a table. + matches!(self, '\0'..='\x1f' | '\x7f'..='\u{9f}') } /// Returns `true` if this `char` has the `Grapheme_Extend` property. diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 10d9498d15e..c1e656fdea2 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1491,6 +1491,20 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_ilog(self, base: Self) -> Option<u32> { + // Inform compiler of optimizations when the base is known at + // compile time and there's a cheaper method available. + // + // Note: Like all optimizations, this is not guaranteed to be + // applied by the compiler. If you want those specific bases, + // use `.checked_ilog2()` or `.checked_ilog10()` directly. + if core::intrinsics::is_val_statically_known(base) { + if base == 2 { + return self.checked_ilog2(); + } else if base == 10 { + return self.checked_ilog10(); + } + } + if self <= 0 || base <= 1 { None } else if self < base { @@ -2447,7 +2461,7 @@ macro_rules! uint_impl { } /// Calculates `self` + `rhs` + `carry` and returns a tuple containing - /// the sum and the output carry. + /// the sum and the output carry (in that order). /// /// Performs "ternary addition" of two integer operands and a carry-in /// bit, and returns an output integer and a carry-out bit. This allows @@ -2465,8 +2479,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] - /// #[doc = concat!("// 3 MAX (a = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] #[doc = concat!("// + 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")] /// // --------- @@ -2483,7 +2495,7 @@ macro_rules! uint_impl { /// /// assert_eq!((sum1, sum0), (9, 6)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2559,8 +2571,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] - /// #[doc = concat!("// 9 6 (a = 9 × 2^", stringify!($BITS), " + 6)")] #[doc = concat!("// - 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")] /// // --------- @@ -2577,7 +2587,7 @@ macro_rules! uint_impl { /// #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2651,10 +2661,12 @@ macro_rules! uint_impl { /// indicating whether an arithmetic overflow would occur. If an /// overflow would have occurred then the wrapped value is returned. /// + /// If you want the *value* of the overflow, rather than just *whether* + /// an overflow occurred, see [`Self::carrying_mul`]. + /// /// # Examples /// - /// Please note that this example is shared among integer types, which is why why `u32` - /// is used. + /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` /// assert_eq!(5u32.overflowing_mul(2), (10, false)); @@ -2670,16 +2682,38 @@ macro_rules! uint_impl { (a as Self, b) } - /// Calculates the complete product `self * rhs` without the possibility to overflow. + /// Calculates the complete double-width product `self * rhs`. /// /// This returns the low-order (wrapping) bits and the high-order (overflow) bits - /// of the result as two separate values, in that order. + /// of the result as two separate values, in that order. As such, + /// `a.widening_mul(b).0` produces the same result as `a.wrapping_mul(b)`. + /// + /// If you also need to add a value and carry to the wide result, then you want + /// [`Self::carrying_mul_add`] instead. /// /// If you also need to add a carry to the wide result, then you want /// [`Self::carrying_mul`] instead. /// + /// If you just want to know *whether* the multiplication overflowed, then you + /// want [`Self::overflowing_mul`] instead. + /// /// # Examples /// + /// ``` + /// #![feature(bigint_helper_methods)] + #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".widening_mul(7), (35, 0));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), (1, ", stringify!($SelfT), "::MAX - 1));")] + /// ``` + /// + /// Compared to other `*_mul` methods: + /// ``` + /// #![feature(bigint_helper_methods)] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::widening_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, 3));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::overflowing_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, true));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::wrapping_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), 0);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::checked_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), None);")] + /// ``` + /// /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` @@ -2706,14 +2740,13 @@ macro_rules! uint_impl { /// additional amount of overflow. This allows for chaining together multiple /// multiplications to create "big integers" which represent larger values. /// - /// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead. + /// If you also need to add a value, then use [`Self::carrying_mul_add`]. /// /// # Examples /// /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] /// assert_eq!(5u32.carrying_mul(2, 0), (10, 0)); /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0)); /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2)); @@ -2771,7 +2804,7 @@ macro_rules! uint_impl { /// 789_u16.wrapping_mul(456).wrapping_add(123), /// ); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2780,18 +2813,20 @@ macro_rules! uint_impl { Self::carrying_mul_add(self, rhs, carry, 0) } - /// Calculates the "full multiplication" `self * rhs + carry1 + carry2` - /// without the possibility to overflow. + /// Calculates the "full multiplication" `self * rhs + carry1 + carry2`. /// /// This returns the low-order (wrapping) bits and the high-order (overflow) bits /// of the result as two separate values, in that order. /// + /// This cannot overflow, as the double-width result has exactly enough + /// space for the largest possible result. This is equivalent to how, in + /// decimal, 9 × 9 + 9 + 9 = 81 + 18 = 99 = 9×10⁰ + 9×10¹ = 10² - 1. + /// /// Performs "long multiplication" which takes in an extra amount to add, and may return an /// additional amount of overflow. This allows for chaining together multiple /// multiplications to create "big integers" which represent larger values. /// - /// If you don't need either `carry`, then you can use [`Self::widening_mul`] instead, - /// and if you only need one `carry`, then you can use [`Self::carrying_mul`] instead. + /// If you don't need the `add` part, then you can use [`Self::carrying_mul`] instead. /// /// # Examples /// @@ -2799,7 +2834,6 @@ macro_rules! uint_impl { /// which explains why `u32` is used here. /// /// ``` - /// #![feature(bigint_helper_methods)] /// assert_eq!(5u32.carrying_mul_add(2, 0, 0), (10, 0)); /// assert_eq!(5u32.carrying_mul_add(2, 10, 10), (30, 0)); /// assert_eq!(1_000_000_000u32.carrying_mul_add(10, 0, 0), (1410065408, 2)); @@ -2816,8 +2850,6 @@ macro_rules! uint_impl { /// using `u8` for simplicity of the demonstration. /// /// ``` - /// #![feature(bigint_helper_methods)] - /// /// fn quadratic_mul<const N: usize>(a: [u8; N], b: [u8; N]) -> [u8; N] { /// let mut out = [0; N]; /// for j in 0..N { @@ -2832,13 +2864,13 @@ macro_rules! uint_impl { /// // -1 * -1 == 1 /// assert_eq!(quadratic_mul([0xFF; 3], [0xFF; 3]), [1, 0, 0]); /// - /// assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xCFFC982D); + /// assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xcffc982d); /// assert_eq!( /// quadratic_mul(u32::to_le_bytes(0x9e3779b9), u32::to_le_bytes(0x7f4a7c15)), - /// u32::to_le_bytes(0xCFFC982D) + /// u32::to_le_bytes(0xcffc982d) /// ); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 1a055a0a5ad..f1db385e212 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -396,7 +396,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(round_char_boundary)] /// let s = "❤️🧡💛💚💙💜"; /// assert_eq!(s.len(), 26); /// assert!(!s.is_char_boundary(13)); @@ -405,7 +404,8 @@ impl str { /// assert_eq!(closest, 10); /// assert_eq!(&s[..closest], "❤️🧡"); /// ``` - #[unstable(feature = "round_char_boundary", issue = "93743")] + #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn floor_char_boundary(&self, index: usize) -> usize { if index >= self.len() { @@ -439,7 +439,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(round_char_boundary)] /// let s = "❤️🧡💛💚💙💜"; /// assert_eq!(s.len(), 26); /// assert!(!s.is_char_boundary(13)); @@ -448,7 +447,8 @@ impl str { /// assert_eq!(closest, 14); /// assert_eq!(&s[..closest], "❤️🧡💛"); /// ``` - #[unstable(feature = "round_char_boundary", issue = "93743")] + #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn ceil_char_boundary(&self, index: usize) -> usize { if index >= self.len() { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 44a6895f90a..7bd68bcd0bc 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2199,7 +2199,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); @@ -2209,7 +2208,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_add(val.wrapping_mul(size_of::<T>()), order) @@ -2240,7 +2239,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let array = [1i32, 2i32]; @@ -2254,7 +2252,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_sub(val.wrapping_mul(size_of::<T>()), order) @@ -2279,7 +2277,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); @@ -2289,7 +2286,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2315,7 +2312,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let mut arr = [0i64, 1]; @@ -2325,7 +2321,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2361,7 +2357,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2376,7 +2371,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2412,7 +2407,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2426,7 +2420,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2462,7 +2456,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2474,7 +2467,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. diff --git a/library/core/src/time.rs b/library/core/src/time.rs index f37e47f132d..d205bc376f1 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -308,6 +308,42 @@ impl Duration { Duration { secs, nanos: subsec_nanos } } + /// Creates a new `Duration` from the specified number of nanoseconds. + /// + /// # Panics + /// + /// Panics if the given number of nanoseconds is greater than [`Duration::MAX`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_from_nanos_u128)] + /// use std::time::Duration; + /// + /// let nanos = 10_u128.pow(24) + 321; + /// let duration = Duration::from_nanos_u128(nanos); + /// + /// assert_eq!(10_u64.pow(15), duration.as_secs()); + /// assert_eq!(321, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_from_nanos_u128", issue = "139201")] + // This is necessary because of const `try_from`, but can be removed if a trait-free impl is used instead + #[rustc_const_unstable(feature = "duration_from_nanos_u128", issue = "139201")] + #[must_use] + #[inline] + #[track_caller] + pub const fn from_nanos_u128(nanos: u128) -> Duration { + const NANOS_PER_SEC: u128 = self::NANOS_PER_SEC as u128; + let Ok(secs) = u64::try_from(nanos / NANOS_PER_SEC) else { + panic!("overflow in `Duration::from_nanos_u128`"); + }; + let subsec_nanos = (nanos % NANOS_PER_SEC) as u32; + // SAFETY: x % 1_000_000_000 < 1_000_000_000 also, subsec_nanos >= 0 since u128 >=0 and u32 >=0 + let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_nanos) }; + + Duration { secs: secs as u64, nanos: subsec_nanos } + } + /// Creates a new `Duration` from the specified number of weeks. /// /// # Panics diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 191fe7711f9..c71fa754e68 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -10,7 +10,6 @@ pub use unicode_data::conversions; #[rustfmt::skip] pub(crate) use unicode_data::alphabetic::lookup as Alphabetic; -pub(crate) use unicode_data::cc::lookup as Cc; pub(crate) use unicode_data::grapheme_extend::lookup as Grapheme_Extend; pub(crate) use unicode_data::lowercase::lookup as Lowercase; pub(crate) use unicode_data::n::lookup as N; diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index b57234bbee9..55f64f1e96e 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -359,31 +359,6 @@ pub mod cased { } #[rustfmt::skip] -pub mod cc { - use super::ShortOffsetRunHeader; - - static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 1] = [ - ShortOffsetRunHeader::new(0, 1114272), - ]; - static OFFSETS: [u8; 5] = [ - 0, 32, 95, 33, 0, - ]; - pub fn lookup(c: char) -> bool { - const { - assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); - let mut i = 0; - while i < SHORT_OFFSET_RUNS.len() { - assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); - i += 1; - } - } - // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` - // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. - unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } - } -} - -#[rustfmt::skip] pub mod grapheme_extend { use super::ShortOffsetRunHeader; diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index b9b768f29d7..bf0a3ae7870 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -36,6 +36,7 @@ #![feature(drop_guard)] #![feature(duration_constants)] #![feature(duration_constructors)] +#![feature(duration_from_nanos_u128)] #![feature(error_generic_member_access)] #![feature(exact_div)] #![feature(exact_size_is_empty)] @@ -95,7 +96,6 @@ #![feature(std_internals)] #![feature(step_trait)] #![feature(str_internals)] -#![feature(strict_provenance_atomic_ptr)] #![feature(strict_provenance_lints)] #![feature(test)] #![feature(trusted_len)] diff --git a/library/coretests/tests/time.rs b/library/coretests/tests/time.rs index bb98e59bf5a..fb3c50f9bde 100644 --- a/library/coretests/tests/time.rs +++ b/library/coretests/tests/time.rs @@ -46,6 +46,14 @@ fn from_weeks_overflow() { } #[test] +#[should_panic] +fn from_nanos_u128_overflow() { + let nanos_per_sec: u128 = 1_000_000_000; + let overflow = (u64::MAX as u128 * nanos_per_sec) + (nanos_per_sec - 1) + 1; + let _ = Duration::from_nanos_u128(overflow); +} + +#[test] fn constructor_weeks() { assert_eq!(Duration::from_weeks(1), Duration::from_secs(7 * 24 * 60 * 60)); assert_eq!(Duration::from_weeks(0), Duration::ZERO); @@ -81,6 +89,8 @@ fn secs() { assert_eq!(Duration::from_micros(1_000_001).as_secs(), 1); assert_eq!(Duration::from_nanos(999_999_999).as_secs(), 0); assert_eq!(Duration::from_nanos(1_000_000_001).as_secs(), 1); + assert_eq!(Duration::from_nanos_u128(999_999_999).as_secs(), 0); + assert_eq!(Duration::from_nanos_u128(1_000_000_001).as_secs(), 1); } #[test] @@ -95,6 +105,8 @@ fn millis() { assert_eq!(Duration::from_micros(1_001_000).subsec_millis(), 1); assert_eq!(Duration::from_nanos(999_999_999).subsec_millis(), 999); assert_eq!(Duration::from_nanos(1_001_000_000).subsec_millis(), 1); + assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_millis(), 999); + assert_eq!(Duration::from_nanos_u128(1_001_000_001).subsec_millis(), 1); } #[test] @@ -109,6 +121,8 @@ fn micros() { assert_eq!(Duration::from_micros(1_000_001).subsec_micros(), 1); assert_eq!(Duration::from_nanos(999_999_999).subsec_micros(), 999_999); assert_eq!(Duration::from_nanos(1_000_001_000).subsec_micros(), 1); + assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_micros(), 999_999); + assert_eq!(Duration::from_nanos_u128(1_000_001_000).subsec_micros(), 1); } #[test] @@ -123,6 +137,8 @@ fn nanos() { assert_eq!(Duration::from_micros(1_000_001).subsec_nanos(), 1000); assert_eq!(Duration::from_nanos(999_999_999).subsec_nanos(), 999_999_999); assert_eq!(Duration::from_nanos(1_000_000_001).subsec_nanos(), 1); + assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_nanos(), 999_999_999); + assert_eq!(Duration::from_nanos_u128(1_000_000_001).subsec_nanos(), 1); } #[test] @@ -520,6 +536,9 @@ fn duration_const() { const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000); assert_eq!(FROM_NANOS, Duration::SECOND); + const FROM_NANOS_U128: Duration = Duration::from_nanos_u128(NANOS); + assert_eq!(FROM_NANOS_U128, Duration::SECOND); + const MAX: Duration = Duration::new(u64::MAX, 999_999_999); const CHECKED_ADD: Option<Duration> = MAX.checked_add(Duration::SECOND); diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index d9c9606fc1c..28b2c7173d3 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -304,7 +304,7 @@ pub struct DirBuilder { pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> { fn inner(path: &Path) -> io::Result<Vec<u8>> { let mut file = File::open(path)?; - let size = file.metadata().map(|m| m.len() as usize).ok(); + let size = file.metadata().map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX)).ok(); let mut bytes = Vec::try_with_capacity(size.unwrap_or(0))?; io::default_read_to_end(&mut file, &mut bytes, size)?; Ok(bytes) @@ -346,7 +346,7 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> { pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> { fn inner(path: &Path) -> io::Result<String> { let mut file = File::open(path)?; - let size = file.metadata().map(|m| m.len() as usize).ok(); + let size = file.metadata().map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX)).ok(); let mut string = String::new(); string.try_reserve_exact(size.unwrap_or(0))?; io::default_read_to_string(&mut file, &mut string, size)?; @@ -1614,6 +1614,10 @@ impl OpenOptions { /// See also [`std::fs::write()`][self::write] for a simple function to /// create a file with some given data. /// + /// # Errors + /// + /// If `.create(true)` is set without `.write(true)` or `.append(true)`, + /// calling [`open`](Self::open) will fail with [`InvalidInput`](io::ErrorKind::InvalidInput) error. /// # Examples /// /// ```no_run @@ -1685,7 +1689,8 @@ impl OpenOptions { /// * [`AlreadyExists`]: `create_new` was specified and the file already /// exists. /// * [`InvalidInput`]: Invalid combinations of open options (truncate - /// without write access, no access mode set, etc.). + /// without write access, create without write or append access, + /// no access mode set, etc.). /// /// The following errors don't match any existing [`io::ErrorKind`] at the moment: /// * One of the directory components of the specified file path diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index c81e3af2f0d..5e51d5e5211 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1265,12 +1265,7 @@ fn open_flavors() { let mut ra = OO::new(); ra.read(true).append(true); - #[cfg(windows)] - let invalid_options = 87; // ERROR_INVALID_PARAMETER - #[cfg(all(unix, not(target_os = "vxworks")))] - let invalid_options = "Invalid argument"; - #[cfg(target_os = "vxworks")] - let invalid_options = "invalid argument"; + let invalid_options = "creating or truncating a file requires write or append access"; // Test various combinations of creation modes and access modes. // @@ -1293,10 +1288,10 @@ fn open_flavors() { check!(c(&w).open(&tmpdir.join("a"))); // read-only - error!(c(&r).create_new(true).open(&tmpdir.join("b")), invalid_options); - error!(c(&r).create(true).truncate(true).open(&tmpdir.join("b")), invalid_options); - error!(c(&r).truncate(true).open(&tmpdir.join("b")), invalid_options); - error!(c(&r).create(true).open(&tmpdir.join("b")), invalid_options); + error_contains!(c(&r).create_new(true).open(&tmpdir.join("b")), invalid_options); + error_contains!(c(&r).create(true).truncate(true).open(&tmpdir.join("b")), invalid_options); + error_contains!(c(&r).truncate(true).open(&tmpdir.join("b")), invalid_options); + error_contains!(c(&r).create(true).open(&tmpdir.join("b")), invalid_options); check!(c(&r).open(&tmpdir.join("a"))); // try opening the file created with write_only // read-write @@ -1308,21 +1303,21 @@ fn open_flavors() { // append check!(c(&a).create_new(true).open(&tmpdir.join("d"))); - error!(c(&a).create(true).truncate(true).open(&tmpdir.join("d")), invalid_options); - error!(c(&a).truncate(true).open(&tmpdir.join("d")), invalid_options); + error_contains!(c(&a).create(true).truncate(true).open(&tmpdir.join("d")), invalid_options); + error_contains!(c(&a).truncate(true).open(&tmpdir.join("d")), invalid_options); check!(c(&a).create(true).open(&tmpdir.join("d"))); check!(c(&a).open(&tmpdir.join("d"))); // read-append check!(c(&ra).create_new(true).open(&tmpdir.join("e"))); - error!(c(&ra).create(true).truncate(true).open(&tmpdir.join("e")), invalid_options); - error!(c(&ra).truncate(true).open(&tmpdir.join("e")), invalid_options); + error_contains!(c(&ra).create(true).truncate(true).open(&tmpdir.join("e")), invalid_options); + error_contains!(c(&ra).truncate(true).open(&tmpdir.join("e")), invalid_options); check!(c(&ra).create(true).open(&tmpdir.join("e"))); check!(c(&ra).open(&tmpdir.join("e"))); // Test opening a file without setting an access mode let mut blank = OO::new(); - error!(blank.create(true).open(&tmpdir.join("f")), invalid_options); + error_contains!(blank.create(true).open(&tmpdir.join("f")), invalid_options); // Test write works check!(check!(File::create(&tmpdir.join("h"))).write("foobar".as_bytes())); @@ -2084,3 +2079,34 @@ fn test_rename_junction() { // Junction links are always absolute so we just check the file name is correct. assert_eq!(fs::read_link(&dest).unwrap().file_name(), Some(not_exist.as_os_str())); } + +#[test] +fn test_open_options_invalid_combinations() { + use crate::fs::OpenOptions as OO; + + let test_cases: &[(fn() -> OO, &str)] = &[ + (|| OO::new().create(true).read(true).clone(), "create without write"), + (|| OO::new().create_new(true).read(true).clone(), "create_new without write"), + (|| OO::new().truncate(true).read(true).clone(), "truncate without write"), + (|| OO::new().truncate(true).append(true).clone(), "truncate with append"), + ]; + + for (make_opts, desc) in test_cases { + let opts = make_opts(); + let result = opts.open("nonexistent.txt"); + assert!(result.is_err(), "{desc} should fail"); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput, "{desc} - wrong error kind"); + assert_eq!( + err.to_string(), + "creating or truncating a file requires write or append access", + "{desc} - wrong error message" + ); + } + + let result = OO::new().open("nonexistent.txt"); + assert!(result.is_err(), "no access mode should fail"); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + assert_eq!(err.to_string(), "must specify at least one of read, write, or append access"); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 30a1b108817..3771699c59f 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -263,7 +263,6 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) )] -#![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] #![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] // @@ -371,7 +370,6 @@ #![feature(slice_range)] #![feature(std_internals)] #![feature(str_internals)] -#![feature(strict_provenance_atomic_ptr)] #![feature(sync_unsafe_cell)] #![feature(temporary_niche_types)] #![feature(ub_checks)] diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index 067ff66d9af..712ce03f90b 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -1,6 +1,5 @@ use crate::fmt; -// FIXME(nonpoison_mutex,nonpoison_condvar): switch to nonpoison versions once they are available -use crate::sync::{Condvar, Mutex}; +use crate::sync::nonpoison::{Condvar, Mutex}; /// A barrier enables multiple threads to synchronize the beginning /// of some computation. @@ -118,12 +117,11 @@ impl Barrier { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn wait(&self) -> BarrierWaitResult { - let mut lock = self.lock.lock().unwrap(); + let mut lock = self.lock.lock(); let local_gen = lock.generation_id; lock.count += 1; if lock.count < self.num_threads { - let _guard = - self.cvar.wait_while(lock, |state| local_gen == state.generation_id).unwrap(); + let _guard = self.cvar.wait_while(lock, |state| local_gen == state.generation_id); BarrierWaitResult(false) } else { lock.count = 0; diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 6ef3bf25cf6..97c04d07eaf 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -209,7 +209,7 @@ pub use self::poison::{LockResult, PoisonError}; #[doc(inline)] pub use self::poison::{ Mutex, MutexGuard, TryLockError, TryLockResult, - Condvar, WaitTimeoutResult, + Condvar, Once, OnceState, RwLock, RwLockReadGuard, RwLockWriteGuard, }; @@ -234,3 +234,66 @@ mod barrier; mod lazy_lock; mod once_lock; mod reentrant_lock; + +/// A type indicating whether a timed wait on a condition variable returned +/// due to a time out or not. +/// +/// It is returned by the [`wait_timeout`] method. +/// +/// [`wait_timeout`]: Condvar::wait_timeout +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[stable(feature = "wait_timeout", since = "1.5.0")] +pub struct WaitTimeoutResult(bool); + +impl WaitTimeoutResult { + /// Returns `true` if the wait was known to have timed out. + /// + /// # Examples + /// + /// This example spawns a thread which will sleep 20 milliseconds before + /// updating a boolean value and then notifying the condvar. + /// + /// The main thread will wait with a 10 millisecond timeout on the condvar + /// and will leave the loop upon timeout. + /// + /// ``` + /// use std::sync::{Arc, Condvar, Mutex}; + /// use std::thread; + /// use std::time::Duration; + /// + /// let pair = Arc::new((Mutex::new(false), Condvar::new())); + /// let pair2 = Arc::clone(&pair); + /// + /// # let handle = + /// thread::spawn(move || { + /// let (lock, cvar) = &*pair2; + /// + /// // Let's wait 20 milliseconds before notifying the condvar. + /// thread::sleep(Duration::from_millis(20)); + /// + /// let mut started = lock.lock().unwrap(); + /// // We update the boolean value. + /// *started = true; + /// cvar.notify_one(); + /// }); + /// + /// // Wait for the thread to start up. + /// let (lock, cvar) = &*pair; + /// loop { + /// // Let's put a timeout on the condvar's wait. + /// let result = cvar.wait_timeout(lock.lock().unwrap(), Duration::from_millis(10)).unwrap(); + /// // 10 milliseconds have passed. + /// if result.1.timed_out() { + /// // timed out now and we can leave. + /// break + /// } + /// } + /// # // Prevent leaks for Miri. + /// # let _ = handle.join(); + /// ``` + #[must_use] + #[stable(feature = "wait_timeout", since = "1.5.0")] + pub fn timed_out(&self) -> bool { + self.0 + } +} diff --git a/library/std/src/sync/nonpoison.rs b/library/std/src/sync/nonpoison.rs index b3ae376e70d..ec3587263f4 100644 --- a/library/std/src/sync/nonpoison.rs +++ b/library/std/src/sync/nonpoison.rs @@ -29,6 +29,8 @@ impl fmt::Display for WouldBlock { } } +#[unstable(feature = "nonpoison_condvar", issue = "134645")] +pub use self::condvar::Condvar; #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub use self::mutex::MappedMutexGuard; #[unstable(feature = "nonpoison_mutex", issue = "134645")] @@ -38,5 +40,6 @@ pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard}; #[unstable(feature = "nonpoison_rwlock", issue = "134645")] pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; +mod condvar; mod mutex; mod rwlock; diff --git a/library/std/src/sync/nonpoison/condvar.rs b/library/std/src/sync/nonpoison/condvar.rs new file mode 100644 index 00000000000..49afdd87818 --- /dev/null +++ b/library/std/src/sync/nonpoison/condvar.rs @@ -0,0 +1,448 @@ +use crate::fmt; +use crate::sync::WaitTimeoutResult; +use crate::sync::nonpoison::{MutexGuard, mutex}; +use crate::sys::sync as sys; +use crate::time::{Duration, Instant}; + +/// A Condition Variable +/// +/// For more information about condition variables, check out the documentation for the poisoning +/// variant of this type at [`poison::Condvar`]. +/// +/// # Examples +/// +/// Note that this `Condvar` does **not** propagate information about threads that panic while +/// holding a lock. If you need this functionality, see [`poison::Mutex`] and [`poison::Condvar`]. +/// +/// ``` +/// #![feature(nonpoison_mutex)] +/// #![feature(nonpoison_condvar)] +/// +/// use std::sync::nonpoison::{Mutex, Condvar}; +/// use std::sync::Arc; +/// use std::thread; +/// +/// let pair = Arc::new((Mutex::new(false), Condvar::new())); +/// let pair2 = Arc::clone(&pair); +/// +/// // Inside of our lock, spawn a new thread, and then wait for it to start. +/// thread::spawn(move || { +/// let (lock, cvar) = &*pair2; +/// let mut started = lock.lock(); +/// *started = true; +/// // We notify the condvar that the value has changed. +/// cvar.notify_one(); +/// }); +/// +/// // Wait for the thread to start up. +/// let (lock, cvar) = &*pair; +/// let mut started = lock.lock(); +/// while !*started { +/// started = cvar.wait(started); +/// } +/// ``` +/// +/// [`poison::Mutex`]: crate::sync::poison::Mutex +/// [`poison::Condvar`]: crate::sync::poison::Condvar +#[unstable(feature = "nonpoison_condvar", issue = "134645")] +pub struct Condvar { + inner: sys::Condvar, +} + +impl Condvar { + /// Creates a new condition variable which is ready to be waited on and + /// notified. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Condvar; + /// + /// let condvar = Condvar::new(); + /// ``` + #[unstable(feature = "nonpoison_condvar", issue = "134645")] + #[must_use] + #[inline] + pub const fn new() -> Condvar { + Condvar { inner: sys::Condvar::new() } + } + + /// Blocks the current thread until this condition variable receives a + /// notification. + /// + /// This function will atomically unlock the mutex specified (represented by + /// `guard`) and block the current thread. This means that any calls + /// to [`notify_one`] or [`notify_all`] which happen logically after the + /// mutex is unlocked are candidates to wake this thread up. When this + /// function call returns, the lock specified will have been re-acquired. + /// + /// Note that this function is susceptible to spurious wakeups. Condition + /// variables normally have a boolean predicate associated with them, and + /// the predicate must always be checked each time this function returns to + /// protect against spurious wakeups. + /// + /// # Panics + /// + /// This function may [`panic!`] if it is used with more than one mutex + /// over time. + /// + /// [`notify_one`]: Self::notify_one + /// [`notify_all`]: Self::notify_all + /// + /// # Examples + /// + /// ``` + /// #![feature(nonpoison_mutex)] + /// #![feature(nonpoison_condvar)] + /// + /// use std::sync::nonpoison::{Mutex, Condvar}; + /// use std::sync::Arc; + /// use std::thread; + /// + /// let pair = Arc::new((Mutex::new(false), Condvar::new())); + /// let pair2 = Arc::clone(&pair); + /// + /// thread::spawn(move || { + /// let (lock, cvar) = &*pair2; + /// let mut started = lock.lock(); + /// *started = true; + /// // We notify the condvar that the value has changed. + /// cvar.notify_one(); + /// }); + /// + /// // Wait for the thread to start up. + /// let (lock, cvar) = &*pair; + /// let mut started = lock.lock(); + /// // As long as the value inside the `Mutex<bool>` is `false`, we wait. + /// while !*started { + /// started = cvar.wait(started); + /// } + /// ``` + #[unstable(feature = "nonpoison_condvar", issue = "134645")] + pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> { + unsafe { + let lock = mutex::guard_lock(&guard); + self.inner.wait(lock); + } + guard + } + + /// Blocks the current thread until the provided condition becomes false. + /// + /// `condition` is checked immediately; if not met (returns `true`), this + /// will [`wait`] for the next notification then check again. This repeats + /// until `condition` returns `false`, in which case this function returns. + /// + /// This function will atomically unlock the mutex specified (represented by + /// `guard`) and block the current thread. This means that any calls + /// to [`notify_one`] or [`notify_all`] which happen logically after the + /// mutex is unlocked are candidates to wake this thread up. When this + /// function call returns, the lock specified will have been re-acquired. + /// + /// [`wait`]: Self::wait + /// [`notify_one`]: Self::notify_one + /// [`notify_all`]: Self::notify_all + /// + /// # Examples + /// + /// ``` + /// #![feature(nonpoison_mutex)] + /// #![feature(nonpoison_condvar)] + /// + /// use std::sync::nonpoison::{Mutex, Condvar}; + /// use std::sync::Arc; + /// use std::thread; + /// + /// let pair = Arc::new((Mutex::new(true), Condvar::new())); + /// let pair2 = Arc::clone(&pair); + /// + /// thread::spawn(move || { + /// let (lock, cvar) = &*pair2; + /// let mut pending = lock.lock(); + /// *pending = false; + /// // We notify the condvar that the value has changed. + /// cvar.notify_one(); + /// }); + /// + /// // Wait for the thread to start up. + /// let (lock, cvar) = &*pair; + /// // As long as the value inside the `Mutex<bool>` is `true`, we wait. + /// let _guard = cvar.wait_while(lock.lock(), |pending| { *pending }); + /// ``` + #[unstable(feature = "nonpoison_condvar", issue = "134645")] + pub fn wait_while<'a, T, F>( + &self, + mut guard: MutexGuard<'a, T>, + mut condition: F, + ) -> MutexGuard<'a, T> + where + F: FnMut(&mut T) -> bool, + { + while condition(&mut *guard) { + guard = self.wait(guard); + } + guard + } + + /// Waits on this condition variable for a notification, timing out after a + /// specified duration. + /// + /// The semantics of this function are equivalent to [`wait`] except that + /// the thread will be blocked for roughly no longer than `dur`. This + /// method should not be used for precise timing due to anomalies such as + /// preemption or platform differences that might not cause the maximum + /// amount of time waited to be precisely `dur`. + /// + /// Note that the best effort is made to ensure that the time waited is + /// measured with a monotonic clock, and not affected by the changes made to + /// the system time. This function is susceptible to spurious wakeups. + /// Condition variables normally have a boolean predicate associated with + /// them, and the predicate must always be checked each time this function + /// returns to protect against spurious wakeups. Additionally, it is + /// typically desirable for the timeout to not exceed some duration in + /// spite of spurious wakes, thus the sleep-duration is decremented by the + /// amount slept. Alternatively, use the `wait_timeout_while` method + /// to wait with a timeout while a predicate is true. + /// + /// The returned [`WaitTimeoutResult`] value indicates if the timeout is + /// known to have elapsed. + /// + /// Like [`wait`], the lock specified will be re-acquired when this function + /// returns, regardless of whether the timeout elapsed or not. + /// + /// [`wait`]: Self::wait + /// [`wait_timeout_while`]: Self::wait_timeout_while + /// + /// # Examples + /// + /// ``` + /// #![feature(nonpoison_mutex)] + /// #![feature(nonpoison_condvar)] + /// + /// use std::sync::nonpoison::{Mutex, Condvar}; + /// use std::sync::Arc; + /// use std::thread; + /// use std::time::Duration; + /// + /// let pair = Arc::new((Mutex::new(false), Condvar::new())); + /// let pair2 = Arc::clone(&pair); + /// + /// thread::spawn(move || { + /// let (lock, cvar) = &*pair2; + /// let mut started = lock.lock(); + /// *started = true; + /// // We notify the condvar that the value has changed. + /// cvar.notify_one(); + /// }); + /// + /// // wait for the thread to start up + /// let (lock, cvar) = &*pair; + /// let mut started = lock.lock(); + /// // as long as the value inside the `Mutex<bool>` is `false`, we wait + /// loop { + /// let result = cvar.wait_timeout(started, Duration::from_millis(10)); + /// // 10 milliseconds have passed, or maybe the value changed! + /// started = result.0; + /// if *started == true { + /// // We received the notification and the value has been updated, we can leave. + /// break + /// } + /// } + /// ``` + #[unstable(feature = "nonpoison_condvar", issue = "134645")] + pub fn wait_timeout<'a, T>( + &self, + guard: MutexGuard<'a, T>, + dur: Duration, + ) -> (MutexGuard<'a, T>, WaitTimeoutResult) { + let success = unsafe { + let lock = mutex::guard_lock(&guard); + self.inner.wait_timeout(lock, dur) + }; + (guard, WaitTimeoutResult(!success)) + } + + /// Waits on this condition variable for a notification, timing out after a + /// specified duration. + /// + /// The semantics of this function are equivalent to [`wait_while`] except + /// that the thread will be blocked for roughly no longer than `dur`. This + /// method should not be used for precise timing due to anomalies such as + /// preemption or platform differences that might not cause the maximum + /// amount of time waited to be precisely `dur`. + /// + /// Note that the best effort is made to ensure that the time waited is + /// measured with a monotonic clock, and not affected by the changes made to + /// the system time. + /// + /// The returned [`WaitTimeoutResult`] value indicates if the timeout is + /// known to have elapsed without the condition being met. + /// + /// Like [`wait_while`], the lock specified will be re-acquired when this + /// function returns, regardless of whether the timeout elapsed or not. + /// + /// [`wait_while`]: Self::wait_while + /// [`wait_timeout`]: Self::wait_timeout + /// + /// # Examples + /// + /// ``` + /// #![feature(nonpoison_mutex)] + /// #![feature(nonpoison_condvar)] + /// + /// use std::sync::nonpoison::{Mutex, Condvar}; + /// use std::sync::Arc; + /// use std::thread; + /// use std::time::Duration; + /// + /// let pair = Arc::new((Mutex::new(true), Condvar::new())); + /// let pair2 = Arc::clone(&pair); + /// + /// thread::spawn(move || { + /// let (lock, cvar) = &*pair2; + /// let mut pending = lock.lock(); + /// *pending = false; + /// // We notify the condvar that the value has changed. + /// cvar.notify_one(); + /// }); + /// + /// // wait for the thread to start up + /// let (lock, cvar) = &*pair; + /// let result = cvar.wait_timeout_while( + /// lock.lock(), + /// Duration::from_millis(100), + /// |&mut pending| pending, + /// ); + /// if result.1.timed_out() { + /// // timed-out without the condition ever evaluating to false. + /// } + /// // access the locked mutex via result.0 + /// ``` + #[unstable(feature = "nonpoison_condvar", issue = "134645")] + pub fn wait_timeout_while<'a, T, F>( + &self, + mut guard: MutexGuard<'a, T>, + dur: Duration, + mut condition: F, + ) -> (MutexGuard<'a, T>, WaitTimeoutResult) + where + F: FnMut(&mut T) -> bool, + { + let start = Instant::now(); + loop { + if !condition(&mut *guard) { + return (guard, WaitTimeoutResult(false)); + } + let timeout = match dur.checked_sub(start.elapsed()) { + Some(timeout) => timeout, + None => return (guard, WaitTimeoutResult(true)), + }; + guard = self.wait_timeout(guard, timeout).0; + } + } + + /// Wakes up one blocked thread on this condvar. + /// + /// If there is a blocked thread on this condition variable, then it will + /// be woken up from its call to [`wait`] or [`wait_timeout`]. Calls to + /// `notify_one` are not buffered in any way. + /// + /// To wake up all threads, see [`notify_all`]. + /// + /// [`wait`]: Self::wait + /// [`wait_timeout`]: Self::wait_timeout + /// [`notify_all`]: Self::notify_all + /// + /// # Examples + /// + /// ``` + /// #![feature(nonpoison_mutex)] + /// #![feature(nonpoison_condvar)] + /// + /// use std::sync::nonpoison::{Mutex, Condvar}; + /// use std::sync::Arc; + /// use std::thread; + /// + /// let pair = Arc::new((Mutex::new(false), Condvar::new())); + /// let pair2 = Arc::clone(&pair); + /// + /// thread::spawn(move || { + /// let (lock, cvar) = &*pair2; + /// let mut started = lock.lock(); + /// *started = true; + /// // We notify the condvar that the value has changed. + /// cvar.notify_one(); + /// }); + /// + /// // Wait for the thread to start up. + /// let (lock, cvar) = &*pair; + /// let mut started = lock.lock(); + /// // As long as the value inside the `Mutex<bool>` is `false`, we wait. + /// while !*started { + /// started = cvar.wait(started); + /// } + /// ``` + #[unstable(feature = "nonpoison_condvar", issue = "134645")] + pub fn notify_one(&self) { + self.inner.notify_one() + } + + /// Wakes up all blocked threads on this condvar. + /// + /// This method will ensure that any current waiters on the condition + /// variable are awoken. Calls to `notify_all()` are not buffered in any + /// way. + /// + /// To wake up only one thread, see [`notify_one`]. + /// + /// [`notify_one`]: Self::notify_one + /// + /// # Examples + /// + /// ``` + /// #![feature(nonpoison_mutex)] + /// #![feature(nonpoison_condvar)] + /// + /// use std::sync::nonpoison::{Mutex, Condvar}; + /// use std::sync::Arc; + /// use std::thread; + /// + /// let pair = Arc::new((Mutex::new(false), Condvar::new())); + /// let pair2 = Arc::clone(&pair); + /// + /// thread::spawn(move || { + /// let (lock, cvar) = &*pair2; + /// let mut started = lock.lock(); + /// *started = true; + /// // We notify the condvar that the value has changed. + /// cvar.notify_all(); + /// }); + /// + /// // Wait for the thread to start up. + /// let (lock, cvar) = &*pair; + /// let mut started = lock.lock(); + /// // As long as the value inside the `Mutex<bool>` is `false`, we wait. + /// while !*started { + /// started = cvar.wait(started); + /// } + /// ``` + #[unstable(feature = "nonpoison_condvar", issue = "134645")] + pub fn notify_all(&self) { + self.inner.notify_all() + } +} + +#[unstable(feature = "nonpoison_condvar", issue = "134645")] +impl fmt::Debug for Condvar { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Condvar").finish_non_exhaustive() + } +} + +#[unstable(feature = "nonpoison_condvar", issue = "134645")] +impl Default for Condvar { + /// Creates a `Condvar` which is ready to be waited on and notified. + fn default() -> Condvar { + Condvar::new() + } +} diff --git a/library/std/src/sync/nonpoison/mutex.rs b/library/std/src/sync/nonpoison/mutex.rs index fd1e671d7a3..07430ce3a13 100644 --- a/library/std/src/sync/nonpoison/mutex.rs +++ b/library/std/src/sync/nonpoison/mutex.rs @@ -114,7 +114,6 @@ impl<T: ?Sized> !Send for MutexGuard<'_, T> {} #[unstable(feature = "nonpoison_mutex", issue = "134645")] unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {} -// FIXME(nonpoison_condvar): Use this link instead: [`Condvar`]: crate::sync::nonpoison::Condvar /// An RAII mutex guard returned by `MutexGuard::map`, which can point to a /// subfield of the protected data. When this structure is dropped (falls out /// of scope), the lock will be unlocked. @@ -131,7 +130,7 @@ unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {} /// /// [`map`]: MutexGuard::map /// [`filter_map`]: MutexGuard::filter_map -/// [`Condvar`]: crate::sync::Condvar +/// [`Condvar`]: crate::sync::nonpoison::Condvar #[must_use = "if unused the Mutex will immediately unlock"] #[must_not_suspend = "holding a MappedMutexGuard across suspend \ points can cause deadlocks, delays, \ @@ -458,6 +457,11 @@ impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> { } } +/// For use in [`nonpoison::condvar`](super::condvar). +pub(super) fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { + &guard.lock.inner +} + impl<'a, T: ?Sized> MutexGuard<'a, T> { /// Makes a [`MappedMutexGuard`] for a component of the borrowed data, e.g. /// an enum variant. diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs index 49a71b9ad10..17abdb9819b 100644 --- a/library/std/src/sync/poison.rs +++ b/library/std/src/sync/poison.rs @@ -61,7 +61,7 @@ //! then the lock will not be poisoned. #[stable(feature = "rust1", since = "1.0.0")] -pub use self::condvar::{Condvar, WaitTimeoutResult}; +pub use self::condvar::Condvar; #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub use self::mutex::MappedMutexGuard; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/sync/poison/condvar.rs b/library/std/src/sync/poison/condvar.rs index 0e9d4233c65..5dc2b510f3a 100644 --- a/library/std/src/sync/poison/condvar.rs +++ b/library/std/src/sync/poison/condvar.rs @@ -1,73 +1,9 @@ use crate::fmt; +use crate::sync::WaitTimeoutResult; use crate::sync::poison::{self, LockResult, MutexGuard, PoisonError, mutex}; use crate::sys::sync as sys; use crate::time::{Duration, Instant}; -/// A type indicating whether a timed wait on a condition variable returned -/// due to a time out or not. -/// -/// It is returned by the [`wait_timeout`] method. -/// -/// [`wait_timeout`]: Condvar::wait_timeout -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -#[stable(feature = "wait_timeout", since = "1.5.0")] -pub struct WaitTimeoutResult(bool); - -// FIXME(nonpoison_condvar): `WaitTimeoutResult` is actually poisoning-agnostic, it seems. -// Should we take advantage of this fact? -impl WaitTimeoutResult { - /// Returns `true` if the wait was known to have timed out. - /// - /// # Examples - /// - /// This example spawns a thread which will sleep 20 milliseconds before - /// updating a boolean value and then notifying the condvar. - /// - /// The main thread will wait with a 10 millisecond timeout on the condvar - /// and will leave the loop upon timeout. - /// - /// ``` - /// use std::sync::{Arc, Condvar, Mutex}; - /// use std::thread; - /// use std::time::Duration; - /// - /// let pair = Arc::new((Mutex::new(false), Condvar::new())); - /// let pair2 = Arc::clone(&pair); - /// - /// # let handle = - /// thread::spawn(move || { - /// let (lock, cvar) = &*pair2; - /// - /// // Let's wait 20 milliseconds before notifying the condvar. - /// thread::sleep(Duration::from_millis(20)); - /// - /// let mut started = lock.lock().unwrap(); - /// // We update the boolean value. - /// *started = true; - /// cvar.notify_one(); - /// }); - /// - /// // Wait for the thread to start up. - /// let (lock, cvar) = &*pair; - /// loop { - /// // Let's put a timeout on the condvar's wait. - /// let result = cvar.wait_timeout(lock.lock().unwrap(), Duration::from_millis(10)).unwrap(); - /// // 10 milliseconds have passed. - /// if result.1.timed_out() { - /// // timed out now and we can leave. - /// break - /// } - /// } - /// # // Prevent leaks for Miri. - /// # let _ = handle.join(); - /// ``` - #[must_use] - #[stable(feature = "wait_timeout", since = "1.5.0")] - pub fn timed_out(&self) -> bool { - self.0 - } -} - /// A Condition Variable /// /// Condition variables represent the ability to block a thread such that it diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 720c212c65c..7e9d920d92f 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -757,11 +757,13 @@ impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> { } } -pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { +/// For use in [`nonpoison::condvar`](super::condvar). +pub(super) fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { &guard.lock.inner } -pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { +/// For use in [`nonpoison::condvar`](super::condvar). +pub(super) fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { &guard.lock.poison } diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 0d710a4b2a6..a89c3bbacfb 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1123,7 +1123,21 @@ impl OpenOptions { (true, true, false) => Ok(libc::O_RDWR), (false, _, true) => Ok(libc::O_WRONLY | libc::O_APPEND), (true, _, true) => Ok(libc::O_RDWR | libc::O_APPEND), - (false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)), + (false, false, false) => { + // If no access mode is set, check if any creation flags are set + // to provide a more descriptive error message + if self.create || self.create_new || self.truncate { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "creating or truncating a file requires write or append access", + )) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "must specify at least one of read, write, or append access", + )) + } + } } } @@ -1132,12 +1146,18 @@ impl OpenOptions { (true, false) => {} (false, false) => { if self.truncate || self.create || self.create_new { - return Err(Error::from_raw_os_error(libc::EINVAL)); + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "creating or truncating a file requires write or append access", + )); } } (_, true) => { if self.truncate && !self.create_new { - return Err(Error::from_raw_os_error(libc::EINVAL)); + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "creating or truncating a file requires write or append access", + )); } } } diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index bb3e4bc30ca..bac278f7c8f 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -258,7 +258,19 @@ impl OpenOptions { Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA)) } (false, false, false, None) => { - Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32)) + // If no access mode is set, check if any creation flags are set + // to provide a more descriptive error message + if self.create || self.create_new || self.truncate { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "creating or truncating a file requires write or append access", + )) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "must specify at least one of read, write, or append access", + )) + } } } } @@ -268,12 +280,18 @@ impl OpenOptions { (true, false) => {} (false, false) => { if self.truncate || self.create || self.create_new { - return Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32)); + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "creating or truncating a file requires write or append access", + )); } } (_, true) => { if self.truncate && !self.create_new { - return Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32)); + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "creating or truncating a file requires write or append access", + )); } } } diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 81275afa707..aec089f7e5c 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -16,10 +16,7 @@ use crate::{fmt, io, iter, mem, ptr, slice, str}; const TMPBUF_SZ: usize = 128; -const PATH_SEPARATOR: u8 = cfg_select! { - target_os = "redox" => b';', - _ => b':', -}; +const PATH_SEPARATOR: u8 = if cfg!(target_os = "redox") { b';' } else { b':' }; unsafe extern "C" { #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] @@ -189,33 +186,14 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { if result == 0 { Ok(()) } else { Err(io::Error::last_os_error()) } } -pub struct SplitPaths<'a> { - iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>, fn(&'a [u8]) -> PathBuf>, -} +pub type SplitPaths<'a> = impl Iterator<Item = PathBuf>; +#[define_opaque(SplitPaths)] pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { - fn bytes_to_path(b: &[u8]) -> PathBuf { - PathBuf::from(<OsStr as OsStrExt>::from_bytes(b)) - } - fn is_separator(b: &u8) -> bool { - *b == PATH_SEPARATOR - } - let unparsed = unparsed.as_bytes(); - SplitPaths { - iter: unparsed - .split(is_separator as fn(&u8) -> bool) - .map(bytes_to_path as fn(&[u8]) -> PathBuf), - } -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option<PathBuf> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } + unparsed + .as_bytes() + .split(|&b| b == PATH_SEPARATOR) + .map(|part| PathBuf::from(OsStr::from_bytes(part))) } #[derive(Debug)] @@ -469,7 +447,7 @@ pub fn current_exe() -> io::Result<PathBuf> { unsafe { let result = libc::find_path( crate::ptr::null_mut(), - libc::path_base_directory::B_FIND_PATH_IMAGE_PATH, + libc::B_FIND_PATH_IMAGE_PATH, crate::ptr::null_mut(), name.as_mut_ptr(), name.len(), diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index 6b0cd14da4f..4798acf9dad 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -20,6 +20,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { // and musl 0.9.3, and some other targets also have it. cfg_select! { any( + target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "hurd", diff --git a/library/std/src/sys/process/windows/tests.rs b/library/std/src/sys/process/windows/tests.rs index 1377e12162f..a21afe3363c 100644 --- a/library/std/src/sys/process/windows/tests.rs +++ b/library/std/src/sys/process/windows/tests.rs @@ -1,7 +1,8 @@ use super::{Arg, make_command_line}; use crate::env; use crate::ffi::{OsStr, OsString}; -use crate::process::Command; +use crate::os::windows::io::AsHandle; +use crate::process::{Command, Stdio}; #[test] fn test_raw_args() { @@ -29,19 +30,30 @@ fn test_thread_handle() { use crate::os::windows::process::{ChildExt, CommandExt}; const CREATE_SUSPENDED: u32 = 0x00000004; - let p = Command::new("cmd").args(&["/C", "exit 0"]).creation_flags(CREATE_SUSPENDED).spawn(); + let p = Command::new("whoami").stdout(Stdio::null()).creation_flags(CREATE_SUSPENDED).spawn(); assert!(p.is_ok()); - let mut p = p.unwrap(); + + // Ensure the process is killed in the event something goes wrong. + struct DropGuard(crate::process::Child); + impl Drop for DropGuard { + fn drop(&mut self) { + let _ = self.0.kill(); + } + } + let mut p = DropGuard(p.unwrap()); + let p = &mut p.0; unsafe extern "system" { - fn ResumeThread(_: BorrowedHandle<'_>) -> u32; + unsafe fn ResumeThread(hHandle: BorrowedHandle<'_>) -> u32; + unsafe fn WaitForSingleObject(hHandle: BorrowedHandle<'_>, dwMilliseconds: u32) -> u32; } unsafe { ResumeThread(p.main_thread_handle()); + // Wait until the process exits or 1 minute passes. + // We don't bother checking the result here as that's done below using `try_wait`. + WaitForSingleObject(p.as_handle(), 1000 * 60); } - crate::thread::sleep(crate::time::Duration::from_millis(100)); - let res = p.try_wait(); assert!(res.is_ok()); assert!(res.unwrap().is_some()); diff --git a/library/std/tests/sync/condvar.rs b/library/std/tests/sync/condvar.rs index 834de6bb1c2..1d712a64300 100644 --- a/library/std/tests/sync/condvar.rs +++ b/library/std/tests/sync/condvar.rs @@ -1,190 +1,269 @@ +use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::channel; -use std::sync::{Arc, Condvar, Mutex}; use std::thread; use std::time::Duration; -#[test] -fn smoke() { - let c = Condvar::new(); - c.notify_one(); - c.notify_all(); -} +use super::nonpoison_and_poison_unwrap_test; + +nonpoison_and_poison_unwrap_test!( + name: smoke, + test_body: { + use locks::Condvar; + + let c = Condvar::new(); + c.notify_one(); + c.notify_all(); + } +); -#[test] -#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads -fn notify_one() { - let m = Arc::new(Mutex::new(())); - let m2 = m.clone(); - let c = Arc::new(Condvar::new()); - let c2 = c.clone(); - - let g = m.lock().unwrap(); - let _t = thread::spawn(move || { - let _g = m2.lock().unwrap(); - c2.notify_one(); - }); - let g = c.wait(g).unwrap(); - drop(g); -} - -#[test] #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads -fn notify_all() { - const N: usize = 10; - - let data = Arc::new((Mutex::new(0), Condvar::new())); - let (tx, rx) = channel(); - for _ in 0..N { - let data = data.clone(); - let tx = tx.clone(); - thread::spawn(move || { - let &(ref lock, ref cond) = &*data; - let mut cnt = lock.lock().unwrap(); - *cnt += 1; - if *cnt == N { - tx.send(()).unwrap(); - } - while *cnt != 0 { - cnt = cond.wait(cnt).unwrap(); - } - tx.send(()).unwrap(); +nonpoison_and_poison_unwrap_test!( + name: notify_one, + test_body: { + use locks::{Condvar, Mutex}; + + let m = Arc::new(Mutex::new(())); + let m2 = m.clone(); + let c = Arc::new(Condvar::new()); + let c2 = c.clone(); + + let g = maybe_unwrap(m.lock()); + let _t = thread::spawn(move || { + let _g = maybe_unwrap(m2.lock()); + c2.notify_one(); }); + let g = maybe_unwrap(c.wait(g)); + drop(g); } - drop(tx); +); - let &(ref lock, ref cond) = &*data; - rx.recv().unwrap(); - let mut cnt = lock.lock().unwrap(); - *cnt = 0; - cond.notify_all(); - drop(cnt); +#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads +nonpoison_and_poison_unwrap_test!( + name: notify_all, + test_body: { + use locks::{Condvar, Mutex}; + + const N: usize = 10; - for _ in 0..N { + let data = Arc::new((Mutex::new(0), Condvar::new())); + let (tx, rx) = channel(); + for _ in 0..N { + let data = data.clone(); + let tx = tx.clone(); + thread::spawn(move || { + let &(ref lock, ref cond) = &*data; + let mut cnt = maybe_unwrap(lock.lock()); + *cnt += 1; + if *cnt == N { + tx.send(()).unwrap(); + } + while *cnt != 0 { + cnt = maybe_unwrap(cond.wait(cnt)); + } + tx.send(()).unwrap(); + }); + } + drop(tx); + + let &(ref lock, ref cond) = &*data; rx.recv().unwrap(); + let mut cnt = maybe_unwrap(lock.lock()); + *cnt = 0; + cond.notify_all(); + drop(cnt); + + for _ in 0..N { + rx.recv().unwrap(); + } } -} +); -#[test] #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads -fn wait_while() { - let pair = Arc::new((Mutex::new(false), Condvar::new())); - let pair2 = pair.clone(); - - // Inside of our lock, spawn a new thread, and then wait for it to start. - thread::spawn(move || { - let &(ref lock, ref cvar) = &*pair2; - let mut started = lock.lock().unwrap(); - *started = true; - // We notify the condvar that the value has changed. - cvar.notify_one(); - }); - - // Wait for the thread to start up. - let &(ref lock, ref cvar) = &*pair; - let guard = cvar.wait_while(lock.lock().unwrap(), |started| !*started); - assert!(*guard.unwrap()); -} - -#[test] -#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported -fn wait_timeout_wait() { - let m = Arc::new(Mutex::new(())); - let c = Arc::new(Condvar::new()); - - loop { - let g = m.lock().unwrap(); - let (_g, no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap(); - // spurious wakeups mean this isn't necessarily true - // so execute test again, if not timeout - if !no_timeout.timed_out() { - continue; +nonpoison_and_poison_unwrap_test!( + name: test_mutex_arc_condvar, + test_body: { + use locks::{Condvar, Mutex}; + + struct Packet<T>(Arc<(Mutex<T>, Condvar)>); + + let packet = Packet(Arc::new((Mutex::new(false), Condvar::new()))); + let packet2 = Packet(packet.0.clone()); + + let (tx, rx) = channel(); + + let _t = thread::spawn(move || { + // Wait until our parent has taken the lock. + rx.recv().unwrap(); + let &(ref lock, ref cvar) = &*packet2.0; + + // Set the data to `true` and wake up our parent. + let mut guard = maybe_unwrap(lock.lock()); + *guard = true; + cvar.notify_one(); + }); + + let &(ref lock, ref cvar) = &*packet.0; + let mut guard = maybe_unwrap(lock.lock()); + // Wake up our child. + tx.send(()).unwrap(); + + // Wait until our child has set the data to `true`. + assert!(!*guard); + while !*guard { + guard = maybe_unwrap(cvar.wait(guard)); } + } +); + +#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads +nonpoison_and_poison_unwrap_test!( + name: wait_while, + test_body: { + use locks::{Condvar, Mutex}; + + let pair = Arc::new((Mutex::new(false), Condvar::new())); + let pair2 = pair.clone(); - break; + // Inside of our lock, spawn a new thread, and then wait for it to start. + thread::spawn(move || { + let &(ref lock, ref cvar) = &*pair2; + let mut started = maybe_unwrap(lock.lock()); + *started = true; + // We notify the condvar that the value has changed. + cvar.notify_one(); + }); + + // Wait for the thread to start up. + let &(ref lock, ref cvar) = &*pair; + let guard = cvar.wait_while(maybe_unwrap(lock.lock()), |started| !*started); + assert!(*maybe_unwrap(guard)); } -} - -#[test] -#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported -fn wait_timeout_while_wait() { - let m = Arc::new(Mutex::new(())); - let c = Arc::new(Condvar::new()); - - let g = m.lock().unwrap(); - let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(1), |_| true).unwrap(); - // no spurious wakeups. ensure it timed-out - assert!(wait.timed_out()); -} - -#[test] -#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported -fn wait_timeout_while_instant_satisfy() { - let m = Arc::new(Mutex::new(())); - let c = Arc::new(Condvar::new()); - - let g = m.lock().unwrap(); - let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(0), |_| false).unwrap(); - // ensure it didn't time-out even if we were not given any time. - assert!(!wait.timed_out()); -} - -#[test] +); + #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads -fn wait_timeout_while_wake() { - let pair = Arc::new((Mutex::new(false), Condvar::new())); - let pair_copy = pair.clone(); - - let &(ref m, ref c) = &*pair; - let g = m.lock().unwrap(); - let _t = thread::spawn(move || { - let &(ref lock, ref cvar) = &*pair_copy; - let mut started = lock.lock().unwrap(); - thread::sleep(Duration::from_millis(1)); - *started = true; - cvar.notify_one(); - }); - let (g2, wait) = c - .wait_timeout_while(g, Duration::from_millis(u64::MAX), |&mut notified| !notified) - .unwrap(); - // ensure it didn't time-out even if we were not given any time. - assert!(!wait.timed_out()); - assert!(*g2); -} - -#[test] +nonpoison_and_poison_unwrap_test!( + name: wait_timeout_wait, + test_body: { + use locks::{Condvar, Mutex}; + + let m = Arc::new(Mutex::new(())); + let c = Arc::new(Condvar::new()); + + loop { + let g = maybe_unwrap(m.lock()); + let (_g, no_timeout) = maybe_unwrap(c.wait_timeout(g, Duration::from_millis(1))); + // spurious wakeups mean this isn't necessarily true + // so execute test again, if not timeout + if !no_timeout.timed_out() { + continue; + } + + break; + } + } +); + #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads -fn wait_timeout_wake() { - let m = Arc::new(Mutex::new(())); - let c = Arc::new(Condvar::new()); +nonpoison_and_poison_unwrap_test!( + name: wait_timeout_while_wait, + test_body: { + use locks::{Condvar, Mutex}; - loop { - let g = m.lock().unwrap(); + let m = Arc::new(Mutex::new(())); + let c = Arc::new(Condvar::new()); - let c2 = c.clone(); - let m2 = m.clone(); + let g = maybe_unwrap(m.lock()); + let (_g, wait) = maybe_unwrap(c.wait_timeout_while(g, Duration::from_millis(1), |_| true)); + // no spurious wakeups. ensure it timed-out + assert!(wait.timed_out()); + } +); + +#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads +nonpoison_and_poison_unwrap_test!( + name: wait_timeout_while_instant_satisfy, + test_body: { + use locks::{Condvar, Mutex}; + + let m = Arc::new(Mutex::new(())); + let c = Arc::new(Condvar::new()); + + let g = maybe_unwrap(m.lock()); + let (_g, wait) = + maybe_unwrap(c.wait_timeout_while(g, Duration::from_millis(0), |_| false)); + // ensure it didn't time-out even if we were not given any time. + assert!(!wait.timed_out()); + } +); - let notified = Arc::new(AtomicBool::new(false)); - let notified_copy = notified.clone(); +#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads +nonpoison_and_poison_unwrap_test!( + name: wait_timeout_while_wake, + test_body: { + use locks::{Condvar, Mutex}; + + let pair = Arc::new((Mutex::new(false), Condvar::new())); + let pair_copy = pair.clone(); - let t = thread::spawn(move || { - let _g = m2.lock().unwrap(); + let &(ref m, ref c) = &*pair; + let g = maybe_unwrap(m.lock()); + let _t = thread::spawn(move || { + let &(ref lock, ref cvar) = &*pair_copy; + let mut started = maybe_unwrap(lock.lock()); thread::sleep(Duration::from_millis(1)); - notified_copy.store(true, Ordering::Relaxed); - c2.notify_one(); + *started = true; + cvar.notify_one(); }); - let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u64::MAX)).unwrap(); - assert!(!timeout_res.timed_out()); - // spurious wakeups mean this isn't necessarily true - // so execute test again, if not notified - if !notified.load(Ordering::Relaxed) { - t.join().unwrap(); - continue; - } - drop(g); + let (g2, wait) = maybe_unwrap(c.wait_timeout_while( + g, + Duration::from_millis(u64::MAX), + |&mut notified| !notified + )); + // ensure it didn't time-out even if we were not given any time. + assert!(!wait.timed_out()); + assert!(*g2); + } +); + +#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads +nonpoison_and_poison_unwrap_test!( + name: wait_timeout_wake, + test_body: { + use locks::{Condvar, Mutex}; - t.join().unwrap(); + let m = Arc::new(Mutex::new(())); + let c = Arc::new(Condvar::new()); - break; + loop { + let g = maybe_unwrap(m.lock()); + + let c2 = c.clone(); + let m2 = m.clone(); + + let notified = Arc::new(AtomicBool::new(false)); + let notified_copy = notified.clone(); + + let t = thread::spawn(move || { + let _g = maybe_unwrap(m2.lock()); + thread::sleep(Duration::from_millis(1)); + notified_copy.store(true, Ordering::Relaxed); + c2.notify_one(); + }); + let (g, timeout_res) = + maybe_unwrap(c.wait_timeout(g, Duration::from_millis(u64::MAX))); + assert!(!timeout_res.timed_out()); + // spurious wakeups mean this isn't necessarily true + // so execute test again, if not notified + if !notified.load(Ordering::Relaxed) { + t.join().unwrap(); + continue; + } + drop(g); + + t.join().unwrap(); + + break; + } } -} +); diff --git a/library/std/tests/sync/lib.rs b/library/std/tests/sync/lib.rs index f874c2ba389..ac1dbebcc5c 100644 --- a/library/std/tests/sync/lib.rs +++ b/library/std/tests/sync/lib.rs @@ -7,6 +7,7 @@ #![feature(rwlock_downgrade)] #![feature(std_internals)] #![feature(sync_nonpoison)] +#![feature(nonpoison_condvar)] #![feature(nonpoison_mutex)] #![feature(nonpoison_rwlock)] #![allow(internal_features)] diff --git a/library/std/tests/sync/mutex.rs b/library/std/tests/sync/mutex.rs index 90cefc0d594..612c75c7aef 100644 --- a/library/std/tests/sync/mutex.rs +++ b/library/std/tests/sync/mutex.rs @@ -213,40 +213,6 @@ nonpoison_and_poison_unwrap_test!( } ); -// FIXME(nonpoison_condvar): Move this to the `condvar.rs` test file once `nonpoison::condvar` gets -// implemented. -#[test] -fn test_mutex_arc_condvar() { - struct Packet<T>(Arc<(Mutex<T>, Condvar)>); - - let packet = Packet(Arc::new((Mutex::new(false), Condvar::new()))); - let packet2 = Packet(packet.0.clone()); - - let (tx, rx) = channel(); - - let _t = thread::spawn(move || { - // Wait until our parent has taken the lock. - rx.recv().unwrap(); - let &(ref lock, ref cvar) = &*packet2.0; - - // Set the data to `true` and wake up our parent. - let mut guard = lock.lock().unwrap(); - *guard = true; - cvar.notify_one(); - }); - - let &(ref lock, ref cvar) = &*packet.0; - let mut guard = lock.lock().unwrap(); - // Wake up our child. - tx.send(()).unwrap(); - - // Wait until our child has set the data to `true`. - assert!(!*guard); - while !*guard { - guard = cvar.wait(guard).unwrap(); - } -} - nonpoison_and_poison_unwrap_test!( name: test_mutex_arc_nested, test_body: { diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index be29e77e572..1535d087033 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -95,9 +95,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.23" +version = "1.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" +checksum = "4ad45f4f74e4e20eaa392913b7b33a7091c87e59628f4dd27888205ad888843c" dependencies = [ "shlex", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index cd5a60187e5..c7175584465 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -32,7 +32,7 @@ test = false # Most of the time updating these dependencies requires modifications to the # bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565); # otherwise, some targets will fail. That's why these dependencies are explicitly pinned. -cc = "=1.2.23" +cc = "=1.2.28" cmake = "=0.1.54" build_helper = { path = "../build_helper" } diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index d30005c8d51..0b75e85772f 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -99,28 +99,12 @@ impl Std { deps } - /// Returns true if the standard library will be uplifted from stage 1 for the given - /// `build_compiler` (which determines the stdlib stage) and `target`. + /// Returns true if the standard library should be uplifted from stage 1. /// - /// Uplifting is enabled if we're building a stage2+ libstd, full bootstrap is - /// disabled and we have a stage1 libstd already compiled for the given target. - pub fn should_be_uplifted_from_stage_1( - builder: &Builder<'_>, - stage: u32, - target: TargetSelection, - ) -> bool { - stage > 1 - && !builder.config.full_bootstrap - // This estimates if a stage1 libstd exists for the given target. If we're not - // cross-compiling, it should definitely exist by the time we're building a stage2 - // libstd. - // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that - // rustc needs to link to a cross-compiled libstd, so again we should have a stage1 - // libstd for the given target prepared. - // Even if we guess wrong in the cross-compiled case, the worst that should happen is - // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we - // don't pay the libstd build cost twice. - && (target == builder.host_target || builder.config.hosts.contains(&target)) + /// Uplifting is enabled if we're building a stage2+ libstd and full bootstrap is + /// disabled. + pub fn should_be_uplifted_from_stage_1(builder: &Builder<'_>, stage: u32) -> bool { + stage > 1 && !builder.config.full_bootstrap } } @@ -150,7 +134,9 @@ impl Step for Std { trace!(force_recompile); run.builder.ensure(Std { - build_compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), + // Note: we don't use compiler_for_std here, so that `x build library --stage 2` + // builds a stage2 rustc. + build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target), target: run.target, crates, force_recompile, @@ -226,7 +212,7 @@ impl Step for Std { // Stage of the stdlib that we're building let stage = build_compiler.stage; - if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage, target) { + if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) { let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target); let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target); diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 778c3beb50f..f113dd7683d 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -96,6 +96,8 @@ impl Step for Docs { } } +/// Builds the `rust-docs-json` installer component. +/// It contains the documentation of the standard library in JSON format. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct JsonDocs { build_compiler: Compiler, @@ -113,12 +115,11 @@ impl Step for JsonDocs { fn make_run(run: RunConfig<'_>) { run.builder.ensure(JsonDocs { - build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target), + build_compiler: run.builder.compiler_for_std(run.builder.top_stage), target: run.target, }); } - /// Builds the `rust-docs-json` installer component. fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> { let target = self.target; let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler( @@ -135,6 +136,10 @@ impl Step for JsonDocs { tarball.add_bulk_dir(directory, dest); Some(tarball.generate()) } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler)) + } } /// Builds the `rustc-docs` installer component. @@ -764,22 +769,7 @@ pub struct Std { impl Std { pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self { - // This is an important optimization mainly for CI. - // Normally, to build stage N libstd, we need stage N rustc. - // However, if we know that we will uplift libstd from stage 1 anyway, building the stage N - // rustc can be wasteful. - // In particular, if we do a cross-compiling dist stage 2 build from T1 to T2, we need: - // - stage 2 libstd for T2 (uplifted from stage 1, where it was built by T1 rustc) - // - stage 2 rustc for T2 - // However, without this optimization, we would also build stage 2 rustc for **T1**, which - // is completely wasteful. - let build_compiler = - if compile::Std::should_be_uplifted_from_stage_1(builder, builder.top_stage, target) { - builder.compiler(1, builder.host_target) - } else { - builder.compiler(builder.top_stage, builder.host_target) - }; - Std { build_compiler, target } + Std { build_compiler: builder.compiler_for_std(builder.top_stage), target } } } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 8c20c8c479a..9ef1fee1fec 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -616,7 +616,7 @@ impl Step for Std { return; } run.builder.ensure(Std { - build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target), + build_compiler: run.builder.compiler_for_std(run.builder.top_stage), target: run.target, format: if run.builder.config.cmd.json() { DocumentationFormat::Json diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index f794f4e079a..b224a7e7322 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1360,6 +1360,30 @@ impl<'a> Builder<'a> { self.ensure(compile::Assemble { target_compiler: Compiler::new(stage, host) }) } + /// This function can be used to provide a build compiler for building + /// the standard library, in order to avoid unnecessary rustc builds in case where std uplifting + /// would happen anyway. + /// + /// This is an important optimization mainly for CI. + /// + /// Normally, to build stage N libstd, we need stage N rustc. + /// However, if we know that we will uplift libstd from stage 1 anyway, building the stage N + /// rustc can be wasteful. + /// In particular, if we do a cross-compiling dist stage 2 build from target1 to target2, + /// we need: + /// - stage 2 libstd for target2 (uplifted from stage 1, where it was built by target1 rustc) + /// - stage 2 rustc for target2 + /// + /// However, without this optimization, we would also build stage 2 rustc for **target1**, + /// which is completely wasteful. + pub fn compiler_for_std(&self, stage: u32) -> Compiler { + if compile::Std::should_be_uplifted_from_stage_1(self, stage) { + self.compiler(1, self.host_target) + } else { + self.compiler(stage, self.host_target) + } + } + /// Similar to `compiler`, except handles the full-bootstrap option to /// silently use the stage1 compiler instead of a stage2 compiler if one is /// requested. diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 3c2cb782850..b079117c5a7 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1066,6 +1066,7 @@ mod snapshot { [build] rustc 1 <host> -> rustc 2 <target1> [build] rustc 2 <host> -> std 2 <host> [build] rustc 2 <host> -> std 2 <target1> + [build] rustc 1 <host> -> std 1 <target2> [build] rustc 2 <host> -> std 2 <target2> "); } @@ -1122,9 +1123,8 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -1141,8 +1141,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <host> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> [dist] mingw <host> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [dist] rustc 1 <host> -> std 1 <host> @@ -1182,12 +1184,11 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> [build] rustc 1 <host> -> LldWrapper 2 <host> [build] rustc 1 <host> -> WasmComponentLd 2 <host> [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -1204,8 +1205,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <host> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> [dist] mingw <host> + [build] rustdoc 2 <host> [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> @@ -1226,6 +1229,8 @@ mod snapshot { [build] rustc 1 <host> -> miri 2 <host> [build] rustc 1 <host> -> cargo-miri 2 <host> [dist] rustc 1 <host> -> miri 2 <host> + [doc] rustc 2 <host> -> std 2 <host> crates=[] + [dist] rustc 2 <host> -> json-docs 3 <host> [dist] rustc 1 <host> -> extended 2 <host> [dist] reproducible-artifacts <host> "); @@ -1259,10 +1264,9 @@ mod snapshot { [doc] book/2018-edition (book) <target1> [doc] rustc 1 <host> -> standalone 2 <host> [doc] rustc 1 <host> -> standalone 2 <target1> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -1290,15 +1294,17 @@ mod snapshot { [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [dist] docs <target1> - [doc] rustc 2 <host> -> std 2 <host> crates=[] - [doc] rustc 2 <host> -> std 2 <target1> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> + [doc] rustc 1 <host> -> std 1 <target1> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <target1> [dist] mingw <host> [dist] mingw <target1> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [dist] rustc 1 <host> -> std 1 <host> - [build] rustc 2 <host> -> std 2 <target1> - [dist] rustc 2 <host> -> std 2 <target1> + [dist] rustc 1 <host> -> std 1 <target1> [dist] rustc 1 <host> -> rustc-dev 2 <host> [dist] src <> [dist] reproducible-artifacts <host> @@ -1327,9 +1333,8 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [build] llvm <target1> @@ -1352,8 +1357,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <host> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> [dist] mingw <host> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [build] rustdoc 2 <target1> @@ -1396,10 +1403,9 @@ mod snapshot { [doc] book/2018-edition (book) <target1> [doc] rustc 1 <host> -> standalone 2 <host> [doc] rustc 1 <host> -> standalone 2 <target1> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [build] llvm <target1> @@ -1432,10 +1438,13 @@ mod snapshot { [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [dist] docs <target1> - [doc] rustc 2 <host> -> std 2 <host> crates=[] - [doc] rustc 2 <host> -> std 2 <target1> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> + [doc] rustc 1 <host> -> std 1 <target1> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <target1> [dist] mingw <host> [dist] mingw <target1> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [build] rustdoc 2 <target1> @@ -1473,9 +1482,7 @@ mod snapshot { [build] rustdoc 1 <host> [build] rustc 1 <host> -> std 1 <host> [doc] rustc 1 <host> -> standalone 2 <target1> - [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [doc] nomicon (book) <target1> [doc] rustc 1 <host> -> reference (book) 2 <target1> [doc] rustdoc (book) <target1> @@ -1488,10 +1495,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <target1> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <target1> - [doc] rustc 2 <host> -> std 2 <target1> crates=[] + [doc] rustc 1 <host> -> std 1 <target1> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <target1> [dist] mingw <target1> - [build] rustc 2 <host> -> std 2 <target1> - [dist] rustc 2 <host> -> std 2 <target1> + [dist] rustc 1 <host> -> std 1 <target1> "); } @@ -1519,10 +1526,7 @@ mod snapshot { [build] rustdoc 1 <host> [build] rustc 1 <host> -> std 1 <host> [doc] rustc 1 <host> -> standalone 2 <target1> - [build] rustc 1 <host> -> rustc 2 <host> - [build] rustc 1 <host> -> WasmComponentLd 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] llvm <target1> [build] rustc 1 <host> -> rustc 2 <target1> [build] rustc 1 <host> -> WasmComponentLd 2 <target1> @@ -1542,7 +1546,8 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <target1> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <target1> - [doc] rustc 2 <host> -> std 2 <target1> crates=[] + [doc] rustc 1 <host> -> std 1 <target1> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <target1> [dist] mingw <target1> [build] rustdoc 2 <target1> [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <target1> @@ -1567,13 +1572,14 @@ mod snapshot { [dist] rustc 1 <host> -> miri 2 <target1> [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1> [doc] rustc 2 <target1> -> std 2 <target1> crates=[] + [dist] rustc 2 <target1> -> json-docs 3 <target1> [dist] rustc 1 <host> -> extended 2 <target1> [dist] reproducible-artifacts <target1> "); } /// Simulates e.g. the powerpc64 builder, which is fully cross-compiled from x64, but it does - /// not build docs. Crutically, it shouldn't build host stage 2 rustc. + /// not build docs. Crucially, it shouldn't build host stage 2 rustc. /// /// This is a regression test for <https://github.com/rust-lang/rust/issues/138123> /// and <https://github.com/rust-lang/rust/issues/138004>. @@ -1663,10 +1669,9 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> [build] rustc 1 <host> -> rustc_codegen_cranelift 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -1683,8 +1688,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <host> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> [dist] mingw <host> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [dist] rustc 1 <host> -> rustc_codegen_cranelift 2 <host> @@ -1725,6 +1732,46 @@ mod snapshot { } #[test] + fn dist_rustc_docs() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .path("rustc-docs") + .render_steps(), @r" + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> + [doc] unstable-book (book) <host> + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [doc] book (book) <host> + [doc] book/first-edition (book) <host> + [doc] book/second-edition (book) <host> + [doc] book/2018-edition (book) <host> + [build] rustdoc 1 <host> + [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 1 <host> -> error-index 2 <host> + [doc] rustc 1 <host> -> error-index 2 <host> + [doc] nomicon (book) <host> + [doc] rustc 1 <host> -> reference (book) 2 <host> + [doc] rustdoc (book) <host> + [doc] rust-by-example (book) <host> + [build] rustc 0 <host> -> LintDocs 1 <host> + [doc] rustc (book) <host> + [doc] cargo (book) <host> + [doc] clippy (book) <host> + [doc] embedded-book (book) <host> + [doc] edition-guide (book) <host> + [doc] style-guide (book) <host> + [doc] rustc 1 <host> -> releases 2 <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> + "); + } + + #[test] fn check_compiler_no_explicit_stage() { let ctx = TestCtx::new(); insta::assert_snapshot!( @@ -2415,10 +2462,9 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> [build] rustc 1 <host> -> WasmComponentLd 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -2436,6 +2482,7 @@ mod snapshot { [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [dist] rustc 1 <host> -> std 1 <host> + [build] rustdoc 2 <host> [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index e0d637a2a67..8e378e53e51 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -116,6 +116,7 @@ - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) - [\*-unknown-hermit](platform-support/hermit.md) - [\*-unknown-freebsd](platform-support/freebsd.md) + - [\*-unknown-managarm-mlibc](platform-support/managarm.md) - [\*-unknown-netbsd\*](platform-support/netbsd.md) - [\*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-redox](platform-support/redox.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index edfc2db7d6f..dfe193e6e8a 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -258,6 +258,7 @@ target | std | host | notes [`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit [`aarch64-unknown-illumos`](platform-support/illumos.md) | ✓ | ✓ | ARM64 illumos `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) +[`aarch64-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | ARM64 Managarm [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | @@ -388,6 +389,7 @@ target | std | host | notes `riscv64gc-unknown-freebsd` | ? | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | ? | | RISC-V Fuchsia [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit +[`riscv64gc-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | RISC-V Managarm [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 @@ -428,6 +430,7 @@ target | std | host | notes [`x86_64-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 64-bit GNU/Hurd `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * | | 64-bit Linux with no libc +[`x86_64-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | x86_64 Managarm [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD [`x86_64-unknown-trusty`](platform-support/trusty.md) | ✓ | | `x86_64-uwp-windows-gnu` | ✓ | | diff --git a/src/doc/rustc/src/platform-support/managarm.md b/src/doc/rustc/src/platform-support/managarm.md new file mode 100644 index 00000000000..aa2d5a7ac23 --- /dev/null +++ b/src/doc/rustc/src/platform-support/managarm.md @@ -0,0 +1,53 @@ +# `*-unknown-managarm-mlibc` + +**Tier: 3** + +## Target Maintainers + +- [@no92](https://github.com/no92) +- [@64](https://github.com/64) +- [@Dennisbonke](https://github.com/Dennisbonke) + +## Requirements + +This target is cross-compiled. There is currently no support for `std` yet. It generates binaries in the ELF format. Currently, we support the `x86_64`, `aarch64` and `riscv64gc` architectures. The examples below `$ARCH` should be substituted for one of the supported architectures. + +## Building the target + +Managarm has upstream support in LLVM since the release of 21.1.0. + +Set up your `bootstrap.toml` like this: + +```toml +change-id = 142379 + +[llvm] +targets = "X86;AArch64;RISCV" +download-ci-llvm = false + +[build] +target = ["$ARCH-unknown-managarm-mlibc", "x86_64-unknown-linux-gnu"] + +[target.x86_64-unknown-linux-gnu] +llvm-config = "/path/to/your/llvm/bin/llvm-config" + +[target.$ARCH-unknown-managarm-mlibc] +llvm-config = "/path/to/your/llvm/bin/llvm-config" +``` + +## Building Rust programs + +Build a `$ARCH-managarm-gcc` using our [gcc fork](https://github.com/managarm/gcc). + +```toml +[build] +rustc = "/path/to/the/rust-prefix/bin/rustc" +target = "$ARCH-unknown-managarm-mlibc" + +[target.$ARCH-unknown-managarm-mlibc] +linker = "/path/to/the/managarm-gcc/bin/$ARCH-managarm-gcc" +``` + +## Testing + +This target does not support running the Rust testsuite yet. diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 058d9cc7c90..f62eba4b3c1 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1,4 +1,5 @@ // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![doc( html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/" @@ -13,7 +14,6 @@ #![feature(if_let_guard)] #![feature(iter_advance_by)] #![feature(iter_intersperse)] -#![feature(round_char_boundary)] #![feature(rustc_private)] #![feature(test)] #![warn(rustc::internal)] diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8f88ab10bf7..2890d26d3f4 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -71,6 +71,7 @@ static TARGETS: &[&str] = &[ "aarch64-unknown-none-softfloat", "aarch64-unknown-redox", "aarch64-unknown-uefi", + "aarch64-unknown-managarm-mlibc", "amdgcn-amd-amdhsa", "arm64e-apple-darwin", "arm64e-apple-ios", @@ -155,6 +156,7 @@ static TARGETS: &[&str] = &[ "riscv64gc-unknown-none-elf", "riscv64gc-unknown-linux-gnu", "riscv64gc-unknown-linux-musl", + "riscv64gc-unknown-managarm-mlibc", "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", @@ -194,6 +196,7 @@ static TARGETS: &[&str] = &[ "x86_64-unknown-redox", "x86_64-unknown-hermit", "x86_64-unknown-uefi", + "x86_64-unknown-managarm-mlibc", ]; /// This allows the manifest to contain rust-docs for hosts that don't build diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index d468993e744..c8594cf35e2 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -7,7 +7,7 @@ #![feature(iter_intersperse)] #![feature(iter_partition_in_place)] #![feature(never_type)] -#![feature(round_char_boundary)] +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] #![feature(unwrap_infallible)] diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed index 04c8f6782c5..375a101c2e3 100644 --- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed +++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed @@ -1,4 +1,3 @@ -#![feature(round_char_boundary)] #![warn(clippy::char_indices_as_byte_indices)] trait StrExt { diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs index 773a4fc65f1..eebc39962a2 100644 --- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs +++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs @@ -1,4 +1,3 @@ -#![feature(round_char_boundary)] #![warn(clippy::char_indices_as_byte_indices)] trait StrExt { diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr index e2b4c1db78c..fae81fd772d 100644 --- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr +++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr @@ -1,12 +1,12 @@ error: indexing into a string with a character position where a byte index is expected - --> tests/ui/char_indices_as_byte_indices.rs:13:24 + --> tests/ui/char_indices_as_byte_indices.rs:12:24 | LL | let _ = prim[..idx]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:11:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -19,14 +19,14 @@ LL + for (idx, _) in prim.char_indices() { | error: passing a character position to a method that expects a byte index - --> tests/ui/char_indices_as_byte_indices.rs:15:23 + --> tests/ui/char_indices_as_byte_indices.rs:14:23 | LL | prim.split_at(idx); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:11:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -37,14 +37,14 @@ LL + for (idx, _) in prim.char_indices() { | error: passing a character position to a method that expects a byte index - --> tests/ui/char_indices_as_byte_indices.rs:19:49 + --> tests/ui/char_indices_as_byte_indices.rs:18:49 | LL | let _ = prim[..prim.floor_char_boundary(idx)]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:11:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -55,14 +55,14 @@ LL + for (idx, _) in prim.char_indices() { | error: indexing into a string with a character position where a byte index is expected - --> tests/ui/char_indices_as_byte_indices.rs:29:24 + --> tests/ui/char_indices_as_byte_indices.rs:28:24 | LL | let _ = prim[..c.0]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:28:9 + --> tests/ui/char_indices_as_byte_indices.rs:27:9 | LL | for c in prim.chars().enumerate() { | ^ ^^^^^^^^^^^ @@ -73,14 +73,14 @@ LL + for c in prim.char_indices() { | error: passing a character position to a method that expects a byte index - --> tests/ui/char_indices_as_byte_indices.rs:31:23 + --> tests/ui/char_indices_as_byte_indices.rs:30:23 | LL | prim.split_at(c.0); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:28:9 + --> tests/ui/char_indices_as_byte_indices.rs:27:9 | LL | for c in prim.chars().enumerate() { | ^ ^^^^^^^^^^^ @@ -91,14 +91,14 @@ LL + for c in prim.char_indices() { | error: indexing into a string with a character position where a byte index is expected - --> tests/ui/char_indices_as_byte_indices.rs:36:26 + --> tests/ui/char_indices_as_byte_indices.rs:35:26 | LL | let _ = string[..idx]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:35:10 + --> tests/ui/char_indices_as_byte_indices.rs:34:10 | LL | for (idx, _) in string.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -109,14 +109,14 @@ LL + for (idx, _) in string.char_indices() { | error: passing a character position to a method that expects a byte index - --> tests/ui/char_indices_as_byte_indices.rs:38:25 + --> tests/ui/char_indices_as_byte_indices.rs:37:25 | LL | string.split_at(idx); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:35:10 + --> tests/ui/char_indices_as_byte_indices.rs:34:10 | LL | for (idx, _) in string.chars().enumerate() { | ^^^ ^^^^^^^^^^^ diff --git a/src/tools/compiletest/src/bin/main.rs b/src/tools/compiletest/src/bin/main.rs index 1f777e71cf9..8fac6ccdc58 100644 --- a/src/tools/compiletest/src/bin/main.rs +++ b/src/tools/compiletest/src/bin/main.rs @@ -2,7 +2,7 @@ use std::env; use std::io::IsTerminal; use std::sync::Arc; -use compiletest::{early_config_check, log_config, parse_config, run_tests}; +use compiletest::{early_config_check, parse_config, run_tests}; fn main() { tracing_subscriber::fmt::init(); @@ -19,6 +19,5 @@ fn main() { early_config_check(&config); - log_config(&config); run_tests(config); } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 58f7c6b5071..8737fec80bb 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -9,7 +9,6 @@ mod tests; pub mod common; -pub mod compute_diff; mod debuggers; pub mod diagnostics; pub mod directives; @@ -44,7 +43,6 @@ use crate::common::{ }; use crate::directives::DirectivesCache; use crate::executor::{CollectedTest, ColorConfig}; -use crate::util::logv; /// Creates the `Config` instance for this invocation of compiletest. /// @@ -477,51 +475,6 @@ pub fn parse_config(args: Vec<String>) -> Config { } } -pub fn log_config(config: &Config) { - let c = config; - logv(c, "configuration:".to_string()); - logv(c, format!("compile_lib_path: {}", config.compile_lib_path)); - logv(c, format!("run_lib_path: {}", config.run_lib_path)); - logv(c, format!("rustc_path: {}", config.rustc_path)); - logv(c, format!("cargo_path: {:?}", config.cargo_path)); - logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); - - logv(c, format!("src_root: {}", config.src_root)); - logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root)); - - logv(c, format!("build_root: {}", config.build_root)); - logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root)); - - logv(c, format!("sysroot_base: {}", config.sysroot_base)); - - logv(c, format!("stage: {}", config.stage)); - logv(c, format!("stage_id: {}", config.stage_id)); - logv(c, format!("mode: {}", config.mode)); - logv(c, format!("run_ignored: {}", config.run_ignored)); - logv(c, format!("filters: {:?}", config.filters)); - logv(c, format!("skip: {:?}", config.skip)); - logv(c, format!("filter_exact: {}", config.filter_exact)); - logv( - c, - format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),), - ); - logv(c, format!("runner: {}", opt_str(&config.runner))); - logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags)); - logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags)); - logv(c, format!("target: {}", config.target)); - logv(c, format!("host: {}", config.host)); - logv(c, format!("android-cross-path: {}", config.android_cross_path)); - logv(c, format!("adb_path: {}", config.adb_path)); - logv(c, format!("adb_test_dir: {}", config.adb_test_dir)); - logv(c, format!("adb_device_status: {}", config.adb_device_status)); - logv(c, format!("ar: {}", config.ar)); - logv(c, format!("target-linker: {:?}", config.target_linker)); - logv(c, format!("host-linker: {:?}", config.host_linker)); - logv(c, format!("verbose: {}", config.verbose)); - logv(c, format!("minicore_path: {}", config.minicore_path)); - logv(c, "\n".to_string()); -} - pub fn opt_str(maybestr: &Option<String>) -> &str { match *maybestr { None => "(none)", @@ -538,6 +491,8 @@ pub fn opt_str2(maybestr: Option<String>) -> String { /// Called by `main` after the config has been parsed. pub fn run_tests(config: Arc<Config>) { + debug!(?config, "run_tests"); + // If we want to collect rustfix coverage information, // we first make sure that the coverage file does not exist. // It will be created later on. diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3a05b242519..867624cc8fa 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -7,7 +7,7 @@ use std::io::prelude::*; use std::io::{self, BufReader}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::sync::Arc; -use std::{env, iter, str}; +use std::{env, fmt, iter, str}; use build_helper::fs::remove_and_create_dir_all; use camino::{Utf8Path, Utf8PathBuf}; @@ -21,15 +21,13 @@ use crate::common::{ UI_WINDOWS_SVG, expected_output_path, incremental_dir, output_base_dir, output_base_name, output_testname_unique, }; -use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; use crate::directives::TestProps; use crate::errors::{Error, ErrorKind, load_errors}; use crate::read2::{Truncated, read2_abbreviated}; -use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex}; +use crate::runtest::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; +use crate::util::{Utf8PathBufExt, add_dylib_path, static_regex}; use crate::{ColorConfig, help, json, stamp_file_path, warning}; -mod debugger; - // Helper modules that implement test running logic for each test suite. // tidy-alphabetical-start mod assembly; @@ -48,6 +46,8 @@ mod rustdoc_json; mod ui; // tidy-alphabetical-end +mod compute_diff; +mod debugger; #[cfg(test)] mod tests; @@ -1459,7 +1459,7 @@ impl<'test> TestCx<'test> { ) -> ProcRes { let cmdline = { let cmdline = self.make_cmdline(&command, lib_path); - logv(self.config, format!("executing {}", cmdline)); + self.logv(format_args!("executing {cmdline}")); cmdline }; @@ -2006,6 +2006,18 @@ impl<'test> TestCx<'test> { output_base_name(self.config, self.testpaths, self.safe_revision()) } + /// Prints a message to (captured) stdout if `config.verbose` is true. + /// The message is also logged to `tracing::debug!` regardles of verbosity. + /// + /// Use `format_args!` as the argument to perform formatting if required. + fn logv(&self, message: impl fmt::Display) { + debug!("{message}"); + if self.config.verbose { + // Note: `./x test ... --verbose --no-capture` is needed to see this print. + println!("{message}"); + } + } + /// Prefix to print before error messages. Normally just `error`, but also /// includes the revision name for tests that use revisions. #[must_use] @@ -2666,8 +2678,8 @@ impl<'test> TestCx<'test> { // // It's not possible to detect paths in the error messages generally, but this is a // decent enough heuristic. - static_regex!( - r#"(?x) + let re = static_regex!( + r#"(?x) (?: # Match paths that don't include spaces. (?:\\[\pL\pN\.\-_']+)+\.\pL+ @@ -2675,11 +2687,8 @@ impl<'test> TestCx<'test> { # If the path starts with a well-known root, then allow spaces and no file extension. \$(?:DIR|SRC_DIR|TEST_BUILD_DIR|BUILD_DIR|LIB_DIR)(?:\\[\pL\pN\.\-_'\ ]+)+ )"# - ) - .replace_all(&output, |caps: &Captures<'_>| { - println!("{}", &caps[0]); - caps[0].replace(r"\", "/") - }) + ); + re.replace_all(&output, |caps: &Captures<'_>| caps[0].replace(r"\", "/")) .replace("\r\n", "\n") } diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/runtest/compute_diff.rs index 509e7e11703..509e7e11703 100644 --- a/src/tools/compiletest/src/compute_diff.rs +++ b/src/tools/compiletest/src/runtest/compute_diff.rs diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 24fdbab3aec..88d022b8bba 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -10,7 +10,6 @@ use super::debugger::DebuggerCommands; use super::{Debugger, Emit, ProcRes, TestCx, Truncated, WillExecute}; use crate::common::Config; use crate::debuggers::{extract_gdb_version, is_android_gdb_target}; -use crate::util::logv; impl TestCx<'_> { pub(super) fn run_debuginfo_test(&self) { @@ -234,7 +233,7 @@ impl TestCx<'_> { gdb.args(debugger_opts); // FIXME(jieyouxu): don't pass an empty Path let cmdline = self.make_cmdline(&gdb, Utf8Path::new("")); - logv(self.config, format!("executing {}", cmdline)); + self.logv(format_args!("executing {cmdline}")); cmdline }; diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs index efdb131bf14..55043bf4bc2 100644 --- a/src/tools/compiletest/src/runtest/mir_opt.rs +++ b/src/tools/compiletest/src/runtest/mir_opt.rs @@ -6,7 +6,7 @@ use miropt_test_tools::{MiroptTest, MiroptTestFile, files_for_miropt_test}; use tracing::debug; use super::{Emit, TestCx, WillExecute}; -use crate::compute_diff::write_diff; +use crate::runtest::compute_diff::write_diff; impl TestCx<'_> { pub(super) fn run_mir_opt_test(&self) { diff --git a/src/tools/compiletest/src/runtest/pretty.rs b/src/tools/compiletest/src/runtest/pretty.rs index e3b07f1d63d..26557727233 100644 --- a/src/tools/compiletest/src/runtest/pretty.rs +++ b/src/tools/compiletest/src/runtest/pretty.rs @@ -1,14 +1,13 @@ use std::fs; use super::{ProcRes, ReadFrom, TestCx}; -use crate::util::logv; impl TestCx<'_> { pub(super) fn run_pretty_test(&self) { if self.props.pp_exact.is_some() { - logv(self.config, "testing for exact pretty-printing".to_owned()); + self.logv("testing for exact pretty-printing"); } else { - logv(self.config, "testing for converging pretty-printing".to_owned()); + self.logv("testing for converging pretty-printing"); } let rounds = match self.props.pp_exact { @@ -21,10 +20,7 @@ impl TestCx<'_> { let mut round = 0; while round < rounds { - logv( - self.config, - format!("pretty-printing round {} revision {:?}", round, self.revision), - ); + self.logv(format_args!("pretty-printing round {round} revision {:?}", self.revision)); let read_from = if round == 0 { ReadFrom::Path } else { ReadFrom::Stdin(srcs[round].to_owned()) }; diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index fb047548c45..1f16a672a98 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -2,9 +2,6 @@ use std::env; use std::process::Command; use camino::{Utf8Path, Utf8PathBuf}; -use tracing::*; - -use crate::common::Config; #[cfg(test)] mod tests; @@ -26,14 +23,6 @@ fn path_div() -> &'static str { ";" } -pub fn logv(config: &Config, s: String) { - debug!("{}", s); - if config.verbose { - // Note: `./x test ... --verbose --no-capture` is needed to see this print. - println!("{}", s); - } -} - pub trait Utf8PathBufExt { /// Append an extension to the path, even if it already has one. fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf; diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs index 3de34e570c7..d8ac5114f27 100644 --- a/src/tools/miri/tests/pass/atomic.rs +++ b/src/tools/miri/tests/pass/atomic.rs @@ -2,7 +2,6 @@ //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(strict_provenance_atomic_ptr)] // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index 6cdb82a87bd..38e5e8bbdb9 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -92,7 +92,6 @@ static PROPERTIES: &[&str] = &[ "Case_Ignorable", "Grapheme_Extend", "White_Space", - "Cc", "N", ]; diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index c935a75a690..b5c116cdfef 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -52,6 +52,9 @@ //@ revisions: aarch64_unknown_linux_ohos //@ [aarch64_unknown_linux_ohos] compile-flags: --target aarch64-unknown-linux-ohos //@ [aarch64_unknown_linux_ohos] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_managarm_mlibc +//@ [aarch64_unknown_managarm_mlibc] compile-flags: --target aarch64-unknown-managarm-mlibc +//@ [aarch64_unknown_managarm_mlibc] needs-llvm-components: aarch64 //@ revisions: aarch64_unknown_netbsd //@ [aarch64_unknown_netbsd] compile-flags: --target aarch64-unknown-netbsd //@ [aarch64_unknown_netbsd] needs-llvm-components: aarch64 @@ -490,6 +493,9 @@ //@ revisions: riscv64gc_unknown_linux_musl //@ [riscv64gc_unknown_linux_musl] compile-flags: --target riscv64gc-unknown-linux-musl //@ [riscv64gc_unknown_linux_musl] needs-llvm-components: riscv +//@ revisions: riscv64gc_unknown_managarm_mlibc +//@ [riscv64gc_unknown_managarm_mlibc] compile-flags: --target riscv64gc-unknown-managarm-mlibc +//@ [riscv64gc_unknown_managarm_mlibc] needs-llvm-components: riscv //@ revisions: riscv64gc_unknown_netbsd //@ [riscv64gc_unknown_netbsd] compile-flags: --target riscv64gc-unknown-netbsd //@ [riscv64gc_unknown_netbsd] needs-llvm-components: riscv @@ -649,6 +655,9 @@ //@ revisions: x86_64_unknown_linux_none //@ [x86_64_unknown_linux_none] compile-flags: --target x86_64-unknown-linux-none //@ [x86_64_unknown_linux_none] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_managarm_mlibc +//@ [x86_64_unknown_managarm_mlibc] compile-flags: --target x86_64-unknown-managarm-mlibc +//@ [x86_64_unknown_managarm_mlibc] needs-llvm-components: x86 //@ revisions: x86_64_unknown_netbsd //@ [x86_64_unknown_netbsd] compile-flags: --target x86_64-unknown-netbsd //@ [x86_64_unknown_netbsd] needs-llvm-components: x86 diff --git a/tests/codegen-llvm/array-repeat.rs b/tests/codegen-llvm/array-repeat.rs index 4c755df9390..1c45341d764 100644 --- a/tests/codegen-llvm/array-repeat.rs +++ b/tests/codegen-llvm/array-repeat.rs @@ -1,7 +1,6 @@ //@ compile-flags: -Copt-level=3 #![crate_type = "lib"] -#![feature(array_repeat)] use std::array::repeat; diff --git a/tests/codegen-llvm/atomicptr.rs b/tests/codegen-llvm/atomicptr.rs index ce6c4aa0d2b..9d5e618fe76 100644 --- a/tests/codegen-llvm/atomicptr.rs +++ b/tests/codegen-llvm/atomicptr.rs @@ -6,7 +6,6 @@ //@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes #![crate_type = "lib"] -#![feature(strict_provenance_atomic_ptr)] use std::ptr::without_provenance_mut; use std::sync::atomic::AtomicPtr; diff --git a/tests/codegen-llvm/iter-repeat-n-trivial-drop.rs b/tests/codegen-llvm/iter-repeat-n-trivial-drop.rs index 28173530324..6f340978428 100644 --- a/tests/codegen-llvm/iter-repeat-n-trivial-drop.rs +++ b/tests/codegen-llvm/iter-repeat-n-trivial-drop.rs @@ -4,7 +4,6 @@ #![crate_type = "lib"] #![feature(iter_repeat_n)] -#![feature(array_repeat)] #[derive(Clone)] pub struct NotCopy(u16); diff --git a/tests/ui/array-slice-vec/pattern-matching-fixed-length-vectors-7784.rs b/tests/ui/array-slice-vec/fixed-length-vector-pattern-matching-7784.rs index 7d987e92b63..7d987e92b63 100644 --- a/tests/ui/array-slice-vec/pattern-matching-fixed-length-vectors-7784.rs +++ b/tests/ui/array-slice-vec/fixed-length-vector-pattern-matching-7784.rs diff --git a/tests/ui/array-slice-vec/matching-on-vector-slice-option-8498.rs b/tests/ui/array-slice-vec/vector-slice-matching-8498.rs index e243a247ed5..e243a247ed5 100644 --- a/tests/ui/array-slice-vec/matching-on-vector-slice-option-8498.rs +++ b/tests/ui/array-slice-vec/vector-slice-matching-8498.rs diff --git a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs index 8ea7a9cb4b5..f93a2aae5a1 100644 --- a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs +++ b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs @@ -20,6 +20,7 @@ target_os = "nto", target_os = "openbsd", target_os = "fuchsia", + target_os = "managarm", ), link_section = ".init_array" )] diff --git a/tests/ui/pattern/match-with-at-binding-8391.rs b/tests/ui/binding/match-with-at-binding-8391.rs index bc4e7be7989..bc4e7be7989 100644 --- a/tests/ui/pattern/match-with-at-binding-8391.rs +++ b/tests/ui/binding/match-with-at-binding-8391.rs diff --git a/tests/ui/issues/issue-7092.rs b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.rs index fab18bd7cf7..4cb04cdf5be 100644 --- a/tests/ui/issues/issue-7092.rs +++ b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7092 enum Whatever { } diff --git a/tests/ui/issues/issue-7092.stderr b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.stderr index e2e57486746..1f8ff2d8df1 100644 --- a/tests/ui/issues/issue-7092.stderr +++ b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-7092.rs:6:9 + --> $DIR/method-call-nonsensical-pattern-binding-7092.rs:7:9 | LL | match x { | - this expression has type `Whatever` diff --git a/tests/ui/pattern/ref-in-function-parameter-patterns-8860.rs b/tests/ui/binding/ref-pattern-drop-behavior-8860.rs index 1a67caf021c..1a67caf021c 100644 --- a/tests/ui/pattern/ref-in-function-parameter-patterns-8860.rs +++ b/tests/ui/binding/ref-pattern-drop-behavior-8860.rs diff --git a/tests/ui/issues/issue-6738.rs b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.rs index a2f8dfe9c49..856caa2b297 100644 --- a/tests/ui/issues/issue-6738.rs +++ b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6738 struct Foo<T> { x: T, } diff --git a/tests/ui/issues/issue-6738.stderr b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.stderr index f22d6a2e468..060d33079d3 100644 --- a/tests/ui/issues/issue-6738.stderr +++ b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.stderr @@ -1,5 +1,5 @@ error[E0368]: binary assignment operation `+=` cannot be applied to type `T` - --> $DIR/issue-6738.rs:6:9 + --> $DIR/struct-field-generic-type-binary-assignment-error-6738.rs:7:9 | LL | self.x += v.x; | ------^^^^^^^ diff --git a/tests/ui/issues/auxiliary/issue-5518.rs b/tests/ui/borrowck/auxiliary/aux-5518.rs index bfe96552a5c..bfe96552a5c 100644 --- a/tests/ui/issues/auxiliary/issue-5518.rs +++ b/tests/ui/borrowck/auxiliary/aux-5518.rs diff --git a/tests/ui/issues/issue-5884.rs b/tests/ui/borrowck/borrowed-pointer-in-struct-5884.rs index 559b897395d..d2f17cf905d 100644 --- a/tests/ui/issues/issue-5884.rs +++ b/tests/ui/borrowck/borrowed-pointer-in-struct-5884.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5884 //@ build-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-5550.rs b/tests/ui/borrowck/incorrect-loan-error-on-local-update-5550.rs index 41de8ee5d32..2258d768657 100644 --- a/tests/ui/issues/issue-5550.rs +++ b/tests/ui/borrowck/incorrect-loan-error-on-local-update-5550.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5550 //@ run-pass #![allow(unused_assignments)] diff --git a/tests/ui/issues/issue-5708.rs b/tests/ui/borrowck/struct-with-reference-to-trait-5708.rs index 6fa3cfa4724..5157a3bf36b 100644 --- a/tests/ui/issues/issue-5708.rs +++ b/tests/ui/borrowck/struct-with-reference-to-trait-5708.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5708 //@ run-pass #![allow(unused_variables)] /* @@ -10,7 +11,6 @@ This does not occur with concrete types, only with references to traits. */ - // original trait Inner { fn print(&self); @@ -38,7 +38,6 @@ pub fn main() { outer.inner.print(); } - // minimal pub trait MyTrait<T> { fn dummy(&self, t: T) -> T { panic!() } diff --git a/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs b/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs new file mode 100644 index 00000000000..f254030a011 --- /dev/null +++ b/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs @@ -0,0 +1,7 @@ +// https://github.com/rust-lang/rust/issues/5518 +//@ run-pass +//@ aux-build:aux-5518.rs + +extern crate aux_5518 as other; + +fn main() {} diff --git a/tests/ui/issues/issue-6557.rs b/tests/ui/box/box-patterns-feature-usage-6557.rs index 64a025a294f..e0d9b25c366 100644 --- a/tests/ui/issues/issue-6557.rs +++ b/tests/ui/box/box-patterns-feature-usage-6557.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6557 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-54094.rs b/tests/ui/cast/associated-type-bounds-cast-54094.rs index 4ca7d1d81b6..c9f307e95b9 100644 --- a/tests/ui/issues/issue-54094.rs +++ b/tests/ui/cast/associated-type-bounds-cast-54094.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/54094 //@ check-pass trait Zoo { type X; diff --git a/tests/ui/issues/issue-6318.rs b/tests/ui/cast/owned-struct-to-trait-cast-6318.rs index d3f08285a93..8cfc77c4274 100644 --- a/tests/ui/issues/issue-6318.rs +++ b/tests/ui/cast/owned-struct-to-trait-cast-6318.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6318 //@ run-pass pub enum Thing { diff --git a/tests/ui/check-cfg/cfg-crate-features.stderr b/tests/ui/check-cfg/cfg-crate-features.stderr index d69a24f3f64..6b2e628e12e 100644 --- a/tests/ui/check-cfg/cfg-crate-features.stderr +++ b/tests/ui/check-cfg/cfg-crate-features.stderr @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist` LL | #![cfg(not(target(os = "does_not_exist")))] | ^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, and `uefi` and 10 more + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, and `tvos` and 11 more = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 18e038a442e..6490fc63fd7 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -156,7 +156,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_env` are: ``, `gnu`, `macabi`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `nto80`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, `sim`, `uclibc`, and `v5` + = note: expected values for `target_env` are: ``, `gnu`, `macabi`, `mlibc`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `nto80`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, `sim`, `uclibc`, and `v5` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -274,7 +274,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: 28 warnings emitted diff --git a/tests/ui/issues/issue-6153.rs b/tests/ui/closures/closure-mut-argument-6153.rs index cd78c85d94b..ac19c2bd15f 100644 --- a/tests/ui/issues/issue-6153.rs +++ b/tests/ui/closures/closure-mut-argument-6153.rs @@ -1,6 +1,6 @@ +// https://github.com/rust-lang/rust/issues/6153 //@ run-pass - fn swap<F>(f: F) -> Vec<isize> where F: FnOnce(Vec<isize>) -> Vec<isize> { let x = vec![1, 2, 3]; f(x) diff --git a/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs b/tests/ui/codegen/matrix-row-swap-54462.rs index 70d0bee7332..6bfc600399a 100644 --- a/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs +++ b/tests/ui/codegen/matrix-row-swap-54462.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/54462 //@ run-pass // //@ compile-flags: -Ccodegen-units=1 -O diff --git a/tests/ui/issues/issue-7012.rs b/tests/ui/codegen/static-array-comparison-7012.rs index 69b881e2a43..c08b1c0059b 100644 --- a/tests/ui/issues/issue-7012.rs +++ b/tests/ui/codegen/static-array-comparison-7012.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7012 //@ run-pass #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] diff --git a/tests/ui/coercion/mut-trait-coercion-8248.rs b/tests/ui/coercion/coerce-mut-trait-object-8248.rs index a45a4d94315..a45a4d94315 100644 --- a/tests/ui/coercion/mut-trait-coercion-8248.rs +++ b/tests/ui/coercion/coerce-mut-trait-object-8248.rs diff --git a/tests/ui/coercion/mut-trait-coercion-8248.stderr b/tests/ui/coercion/coerce-mut-trait-object-8248.stderr index 0c7d5f9dc45..c3b35a7063c 100644 --- a/tests/ui/coercion/mut-trait-coercion-8248.stderr +++ b/tests/ui/coercion/coerce-mut-trait-object-8248.stderr @@ -1,5 +1,5 @@ warning: method `dummy` is never used - --> $DIR/mut-trait-coercion-8248.rs:5:8 + --> $DIR/coerce-mut-trait-object-8248.rs:5:8 | LL | trait A { | - method in this trait diff --git a/tests/ui/issues/issue-54477-reduced-2.rs b/tests/ui/collections/vecdeque-append-operation-54477.rs index 5f65e545182..7680fd0bb01 100644 --- a/tests/ui/issues/issue-54477-reduced-2.rs +++ b/tests/ui/collections/vecdeque-append-operation-54477.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/54477 //@ run-pass // rust-lang/rust#54477: runtime bug in the VecDeque library that was // exposed by this test case, derived from test suite of crates.io diff --git a/tests/ui/issues/auxiliary/issue-7178.rs b/tests/ui/cross-crate/auxiliary/aux-7178.rs index 56ae5139af4..56ae5139af4 100644 --- a/tests/ui/issues/auxiliary/issue-7178.rs +++ b/tests/ui/cross-crate/auxiliary/aux-7178.rs diff --git a/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs b/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs new file mode 100644 index 00000000000..3888d3bdaa9 --- /dev/null +++ b/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/7178 +//@ run-pass +//@ aux-build:aux-7178.rs + +extern crate aux_7178 as cross_crate_self; + +pub fn main() { + let _ = cross_crate_self::Foo::new(&1); +} diff --git a/tests/ui/cross-crate/static-regions-in-cross-crate-8259.rs b/tests/ui/cross-crate/static-with-cross-crate-regions-8259.rs index 347cfa2aee1..347cfa2aee1 100644 --- a/tests/ui/cross-crate/static-regions-in-cross-crate-8259.rs +++ b/tests/ui/cross-crate/static-with-cross-crate-regions-8259.rs diff --git a/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs b/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs new file mode 100644 index 00000000000..ce3ea7dd579 --- /dev/null +++ b/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs @@ -0,0 +1,10 @@ +// https://github.com/rust-lang/rust/issues/7899 +//@ run-pass +#![allow(unused_variables)] +//@ aux-build:aux-7899.rs + +extern crate aux_7899 as testcrate; + +fn main() { + let f = testcrate::V2(1.0f32, 2.0f32); +} diff --git a/tests/ui/issues/issue-5900.rs b/tests/ui/enum/enum-referred-by-submodule-5900.rs index 14b7b8f815a..4ed092670a8 100644 --- a/tests/ui/issues/issue-5900.rs +++ b/tests/ui/enum/enum-referred-by-submodule-5900.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5900 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs b/tests/ui/enum/enum-with-generic-parameter-5997.rs index 7ed8819f322..fab7ebbbbdc 100644 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs +++ b/tests/ui/enum/enum-with-generic-parameter-5997.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5997 //@ run-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-6117.rs b/tests/ui/enum/match-either-enum-variants-6117.rs index 3ccf67b0319..7b395066166 100644 --- a/tests/ui/issues/issue-6117.rs +++ b/tests/ui/enum/match-either-enum-variants-6117.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6117 //@ run-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-54696.rs b/tests/ui/function-pointer/function-pointer-comparison-54696.rs index 63ffbe42bcc..2e28dfeaaf8 100644 --- a/tests/ui/issues/issue-54696.rs +++ b/tests/ui/function-pointer/function-pointer-comparison-54696.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/54696 //@ run-pass #![allow(unpredictable_function_pointer_comparisons)] diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.rs index 0b1857ae3df..00bf66dd4e0 100644 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs +++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5997 fn f<Z>() -> bool { enum E { V(Z) } //~^ ERROR can't use generic parameters from outer item diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr index c0b3cd6de66..aea0f049b07 100644 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr +++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/issue-5997-enum.rs:2:16 + --> $DIR/enum-definition-with-outer-generic-parameter-5997.rs:3:16 | LL | fn f<Z>() -> bool { | - type parameter from outer item diff --git a/tests/ui/issues/issue-54410.rs b/tests/ui/issues/issue-54410.rs deleted file mode 100644 index e3e8ca985b9..00000000000 --- a/tests/ui/issues/issue-54410.rs +++ /dev/null @@ -1,8 +0,0 @@ -extern "C" { - pub static mut symbol: [i8]; - //~^ ERROR the size for values of type `[i8]` cannot be known at compilation time -} - -fn main() { - println!("{:p}", unsafe { &symbol }); -} diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr deleted file mode 100644 index cb68ada7e13..00000000000 --- a/tests/ui/issues/issue-54410.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0277]: the size for values of type `[i8]` cannot be known at compilation time - --> $DIR/issue-54410.rs:2:5 - | -LL | pub static mut symbol: [i8]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[i8]` - = note: statics and constants must have a statically known size - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-5518.rs b/tests/ui/issues/issue-5518.rs deleted file mode 100644 index 333185c482f..00000000000 --- a/tests/ui/issues/issue-5518.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -//@ aux-build:issue-5518.rs - - -extern crate issue_5518 as other; - -fn main() {} diff --git a/tests/ui/issues/issue-5844.rs b/tests/ui/issues/issue-5844.rs deleted file mode 100644 index 23021207ae1..00000000000 --- a/tests/ui/issues/issue-5844.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@aux-build:issue-5844-aux.rs - -extern crate issue_5844_aux; - -fn main() { - issue_5844_aux::rand(); //~ ERROR: requires unsafe -} diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs deleted file mode 100644 index 19d994b0dfb..00000000000 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn f<T>() -> bool { - struct S(T); //~ ERROR can't use generic parameters from outer item - - true -} - -fn main() { - let b = f::<isize>(); - assert!(b); -} diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr deleted file mode 100644 index 670a54894b5..00000000000 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0401]: can't use generic parameters from outer item - --> $DIR/issue-5997-struct.rs:2:14 - | -LL | fn f<T>() -> bool { - | - type parameter from outer item -LL | struct S(T); - | -^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `<T>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/issues/issue-6344-match.rs b/tests/ui/issues/issue-6344-match.rs deleted file mode 100644 index 9251e274383..00000000000 --- a/tests/ui/issues/issue-6344-match.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ run-pass -#![allow(non_shorthand_field_patterns)] - -struct A { x: usize } - -impl Drop for A { - fn drop(&mut self) {} -} - -pub fn main() { - let a = A { x: 0 }; - - match a { - A { x : ref x } => { - println!("{}", x) - } - } -} diff --git a/tests/ui/issues/issue-7178.rs b/tests/ui/issues/issue-7178.rs deleted file mode 100644 index 408ce0b03eb..00000000000 --- a/tests/ui/issues/issue-7178.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass -//@ aux-build:issue-7178.rs - - -extern crate issue_7178 as cross_crate_self; - -pub fn main() { - let _ = cross_crate_self::Foo::new(&1); -} diff --git a/tests/ui/issues/issue-53419.rs b/tests/ui/lifetimes/dyn-trait-function-pointer-53419.rs index 55d41f2005d..b1017b104ac 100644 --- a/tests/ui/issues/issue-53419.rs +++ b/tests/ui/lifetimes/dyn-trait-function-pointer-53419.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/53419 //@ check-pass struct Foo { diff --git a/tests/ui/issues/issue-7268.rs b/tests/ui/lifetimes/static-bound-fulfillment-with-pointer-7268.rs index a3bc1bc3446..8ec58e6cd80 100644 --- a/tests/ui/issues/issue-7268.rs +++ b/tests/ui/lifetimes/static-bound-fulfillment-with-pointer-7268.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7268 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.full-debuginfo.stderr index 5b97a2104a3..4b179d59e5f 100644 --- a/tests/ui/limits/huge-enum.stderr +++ b/tests/ui/limits/huge-enum.full-debuginfo.stderr @@ -1,5 +1,5 @@ error: values of the type `Option<TYPE>` are too big for the target architecture - --> $DIR/huge-enum.rs:15:9 + --> $DIR/huge-enum.rs:17:9 | LL | let big: BIG = None; | ^^^ diff --git a/tests/ui/limits/huge-enum.no-debuginfo.stderr b/tests/ui/limits/huge-enum.no-debuginfo.stderr new file mode 100644 index 00000000000..4b179d59e5f --- /dev/null +++ b/tests/ui/limits/huge-enum.no-debuginfo.stderr @@ -0,0 +1,8 @@ +error: values of the type `Option<TYPE>` are too big for the target architecture + --> $DIR/huge-enum.rs:17:9 + | +LL | let big: BIG = None; + | ^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs index 6d5b86411f3..9395bee9765 100644 --- a/tests/ui/limits/huge-enum.rs +++ b/tests/ui/limits/huge-enum.rs @@ -1,9 +1,11 @@ +// FIXME(#61117): Remove revisions once x86_64-gnu-debug CI job sets rust.debuginfo-level-tests=2 +// NOTE: The .stderr for both revisions shall be identical. +//@ revisions: no-debuginfo full-debuginfo //@ build-fail //@ normalize-stderr: "std::option::Option<\[u32; \d+\]>" -> "TYPE" //@ normalize-stderr: "\[u32; \d+\]" -> "TYPE" - -// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0 -//@ compile-flags: -Cdebuginfo=0 +//@[no-debuginfo] compile-flags: -Cdebuginfo=0 +//@[full-debuginfo] compile-flags: -Cdebuginfo=2 #[cfg(target_pointer_width = "32")] type BIG = Option<[u32; (1<<29)-1]>; diff --git a/tests/ui/issues/issue-5741.rs b/tests/ui/loops/unreachable-while-loop-5741.rs index af4702ec22c..bc69df0f675 100644 --- a/tests/ui/issues/issue-5741.rs +++ b/tests/ui/loops/unreachable-while-loop-5741.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5741 //@ run-pass #![allow(while_true)] #![allow(unreachable_code)] diff --git a/tests/ui/issues/issue-5554.rs b/tests/ui/macros/macro-variable-declaration-with-bounds-5554.rs index 7d219a0df70..8ccf8e80131 100644 --- a/tests/ui/issues/issue-5554.rs +++ b/tests/ui/macros/macro-variable-declaration-with-bounds-5554.rs @@ -1,7 +1,7 @@ +// https://github.com/rust-lang/rust/issues/5554 //@ run-pass #![allow(dead_code)] - pub struct X<T> { a: T, } diff --git a/tests/ui/issues/issue-5718.rs b/tests/ui/macros/macro-variable-unused-reporting-5718.rs index 234fb2e2222..55da925461d 100644 --- a/tests/ui/issues/issue-5718.rs +++ b/tests/ui/macros/macro-variable-unused-reporting-5718.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5718 //@ run-pass struct Element; diff --git a/tests/ui/issues/issue-5358-1.rs b/tests/ui/match/mismatched-types-in-match-5358.rs index 281f219c039..d096bf3a493 100644 --- a/tests/ui/issues/issue-5358-1.rs +++ b/tests/ui/match/mismatched-types-in-match-5358.rs @@ -1,8 +1,13 @@ -enum Either<T, U> { Left(T), Right(U) } +// https://github.com/rust-lang/rust/issues/5358 +enum Either<T, U> { + Left(T), + Right(U), +} struct S(Either<usize, usize>); fn main() { - match S(Either::Left(5)) { //~ NOTE this expression has type `S` + match S(Either::Left(5)) { + //~^ NOTE this expression has type `S` Either::Right(_) => {} //~^ ERROR mismatched types //~| NOTE expected `S`, found `Either<_, _>` diff --git a/tests/ui/issues/issue-5358-1.stderr b/tests/ui/match/mismatched-types-in-match-5358.stderr index e68db865dc4..6a6cf3ee269 100644 --- a/tests/ui/issues/issue-5358-1.stderr +++ b/tests/ui/match/mismatched-types-in-match-5358.stderr @@ -1,8 +1,9 @@ error[E0308]: mismatched types - --> $DIR/issue-5358-1.rs:6:9 + --> $DIR/mismatched-types-in-match-5358.rs:11:9 | LL | match S(Either::Left(5)) { | ------------------ this expression has type `S` +LL | LL | Either::Right(_) => {} | ^^^^^^^^^^^^^^^^ expected `S`, found `Either<_, _>` | diff --git a/tests/ui/match/mismatched-types-in-match-pattern-7867.rs b/tests/ui/match/mismatched-types-in-match-7867.rs index 9ff8755c819..9ff8755c819 100644 --- a/tests/ui/match/mismatched-types-in-match-pattern-7867.rs +++ b/tests/ui/match/mismatched-types-in-match-7867.rs diff --git a/tests/ui/match/mismatched-types-in-match-pattern-7867.stderr b/tests/ui/match/mismatched-types-in-match-7867.stderr index 8997f36114a..e41a61e42f4 100644 --- a/tests/ui/match/mismatched-types-in-match-pattern-7867.stderr +++ b/tests/ui/match/mismatched-types-in-match-7867.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/mismatched-types-in-match-pattern-7867.rs:10:9 + --> $DIR/mismatched-types-in-match-7867.rs:10:9 | LL | enum A { B, C } | - unit variant defined here diff --git a/tests/ui/methods/trait-method-self-param-error-7575.rs b/tests/ui/methods/trait-method-resolution-7575.rs index 9793d43cc24..9793d43cc24 100644 --- a/tests/ui/methods/trait-method-self-param-error-7575.rs +++ b/tests/ui/methods/trait-method-resolution-7575.rs diff --git a/tests/ui/methods/trait-method-self-param-error-7575.stderr b/tests/ui/methods/trait-method-resolution-7575.stderr index 656db30352d..8bbc360de57 100644 --- a/tests/ui/methods/trait-method-self-param-error-7575.stderr +++ b/tests/ui/methods/trait-method-resolution-7575.stderr @@ -1,5 +1,5 @@ warning: trait `Foo` is never used - --> $DIR/trait-method-self-param-error-7575.rs:4:7 + --> $DIR/trait-method-resolution-7575.rs:4:7 | LL | trait Foo { | ^^^ diff --git a/tests/ui/issues/issue-5950.rs b/tests/ui/modules/pub-use-module-alias-5950.rs index 6015560fcf8..91d3f9b16ff 100644 --- a/tests/ui/issues/issue-5950.rs +++ b/tests/ui/modules/pub-use-module-alias-5950.rs @@ -1,6 +1,6 @@ +// https://github.com/rust-lang/rust/issues/5950 //@ check-pass - pub use local as local_alias; pub mod local { } diff --git a/tests/ui/resolve/module-import-resolution-7663.rs b/tests/ui/modules/use-statement-duplicate-check-7663.rs index 872806594fc..872806594fc 100644 --- a/tests/ui/resolve/module-import-resolution-7663.rs +++ b/tests/ui/modules/use-statement-duplicate-check-7663.rs diff --git a/tests/ui/issues/issue-6130.rs b/tests/ui/numeric/type-limit-comparisons-6130.rs index c675a8a41dd..54b3f631e67 100644 --- a/tests/ui/issues/issue-6130.rs +++ b/tests/ui/numeric/type-limit-comparisons-6130.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6130 //@ run-pass pub fn main() { diff --git a/tests/ui/issues/issue-5572.rs b/tests/ui/parser/partial-eq-trait-bound-5572.rs index f27744ef0ac..7ee0cdc43ee 100644 --- a/tests/ui/issues/issue-5572.rs +++ b/tests/ui/parser/partial-eq-trait-bound-5572.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5572 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/issues/auxiliary/iss.rs b/tests/ui/privacy/auxiliary/iss-6919.rs index cf32f6c2d5d..cf32f6c2d5d 100644 --- a/tests/ui/issues/auxiliary/iss.rs +++ b/tests/ui/privacy/auxiliary/iss-6919.rs diff --git a/tests/ui/issues/issue-6919.rs b/tests/ui/privacy/deref-separate-compile-unit-6919.rs index 7fb8a2f33bc..5d8934987e5 100644 --- a/tests/ui/issues/issue-6919.rs +++ b/tests/ui/privacy/deref-separate-compile-unit-6919.rs @@ -1,7 +1,7 @@ +// https://github.com/rust-lang/rust/issues/6919 //@ run-pass #![allow(unused_attributes)] -//@ aux-build:iss.rs - +//@ aux-build:iss-6919.rs extern crate issue6919_3; diff --git a/tests/ui/issues/issue-55376.rs b/tests/ui/privacy/pub-restricted-path-usage-55376.rs index 5a6862b6530..ca4e27c30a8 100644 --- a/tests/ui/issues/issue-55376.rs +++ b/tests/ui/privacy/pub-restricted-path-usage-55376.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/55376 //@ run-pass // Tests that paths in `pub(...)` don't fail HIR verification. diff --git a/tests/ui/issues/issue-53728.rs b/tests/ui/repr/packed-struct-with-enum-53728.rs index 364965228c6..6ce65ed634f 100644 --- a/tests/ui/issues/issue-53728.rs +++ b/tests/ui/repr/packed-struct-with-enum-53728.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/53728 //@ run-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-6936.rs b/tests/ui/resolve/duplicate-name-in-module-6936.rs index e9aa80b4eb3..ae9282c0c24 100644 --- a/tests/ui/issues/issue-6936.rs +++ b/tests/ui/resolve/duplicate-name-in-module-6936.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6936 struct T; mod t1 { @@ -30,5 +31,4 @@ mod t6 { impl Foo {} // ok } - fn main() {} diff --git a/tests/ui/issues/issue-6936.stderr b/tests/ui/resolve/duplicate-name-in-module-6936.stderr index 03cc50636b4..76bb8f57386 100644 --- a/tests/ui/issues/issue-6936.stderr +++ b/tests/ui/resolve/duplicate-name-in-module-6936.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-6936.rs:5:5 + --> $DIR/duplicate-name-in-module-6936.rs:6:5 | LL | type Foo = crate::T; | -------------------- previous definition of the type `Foo` here @@ -9,7 +9,7 @@ LL | mod Foo {} = note: `Foo` must be defined only once in the type namespace of this module error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-6936.rs:10:5 + --> $DIR/duplicate-name-in-module-6936.rs:11:5 | LL | type Foo = crate::T; | -------------------- previous definition of the type `Foo` here @@ -19,7 +19,7 @@ LL | struct Foo; = note: `Foo` must be defined only once in the type namespace of this module error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-6936.rs:15:5 + --> $DIR/duplicate-name-in-module-6936.rs:16:5 | LL | type Foo = crate::T; | -------------------- previous definition of the type `Foo` here @@ -29,7 +29,7 @@ LL | enum Foo {} = note: `Foo` must be defined only once in the type namespace of this module error[E0428]: the name `Bar` is defined multiple times - --> $DIR/issue-6936.rs:25:5 + --> $DIR/duplicate-name-in-module-6936.rs:26:5 | LL | type Bar<T> = T; | ---------------- previous definition of the type `Bar` here diff --git a/tests/ui/issues/issue-7044.rs b/tests/ui/resolve/unit-like-struct-masks-constant-7044.rs index a6e22bc5237..f48dd695f01 100644 --- a/tests/ui/issues/issue-7044.rs +++ b/tests/ui/resolve/unit-like-struct-masks-constant-7044.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7044 static X: isize = 0; struct X; //~ ERROR the name `X` is defined multiple times diff --git a/tests/ui/issues/issue-7044.stderr b/tests/ui/resolve/unit-like-struct-masks-constant-7044.stderr index 9d1fb3a10dd..48aa6fce455 100644 --- a/tests/ui/issues/issue-7044.stderr +++ b/tests/ui/resolve/unit-like-struct-masks-constant-7044.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `X` is defined multiple times - --> $DIR/issue-7044.rs:2:1 + --> $DIR/unit-like-struct-masks-constant-7044.rs:3:1 | LL | static X: isize = 0; | -------------------- previous definition of the value `X` here diff --git a/tests/ui/issues/issue-55380.rs b/tests/ui/specialization/trait-specialization-default-methods-55380.rs index 54894cdede0..b3d79fb5ffb 100644 --- a/tests/ui/issues/issue-55380.rs +++ b/tests/ui/specialization/trait-specialization-default-methods-55380.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/55380 //@ run-pass #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete diff --git a/tests/ui/issues/issue-55380.stderr b/tests/ui/specialization/trait-specialization-default-methods-55380.stderr index 403844c726f..f7c1903da62 100644 --- a/tests/ui/issues/issue-55380.stderr +++ b/tests/ui/specialization/trait-specialization-default-methods-55380.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-55380.rs:2:12 + --> $DIR/trait-specialization-default-methods-55380.rs:3:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-7364.rs b/tests/ui/static/global-variable-promotion-error-7364.rs index 4ce9beb68cd..dba4a484d61 100644 --- a/tests/ui/issues/issue-7364.rs +++ b/tests/ui/static/global-variable-promotion-error-7364.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7364 use std::cell::RefCell; // Regression test for issue 7364 diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/static/global-variable-promotion-error-7364.stderr index a47a90c90ce..b9d75676bef 100644 --- a/tests/ui/issues/issue-7364.stderr +++ b/tests/ui/static/global-variable-promotion-error-7364.stderr @@ -1,5 +1,5 @@ error[E0277]: `RefCell<isize>` cannot be shared between threads safely - --> $DIR/issue-7364.rs:4:15 + --> $DIR/global-variable-promotion-error-7364.rs:5:15 | LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0)); | ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely @@ -12,7 +12,7 @@ note: required because it appears within the type `Box<RefCell<isize>>` = note: shared static variables must have a type that implements `Sync` error[E0015]: cannot call non-const associated function `Box::<RefCell<isize>>::new` in statics - --> $DIR/issue-7364.rs:4:37 + --> $DIR/global-variable-promotion-error-7364.rs:5:37 | LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-5917.rs b/tests/ui/static/static-list-initialization-5917.rs index 8e91b1052a2..c6c32f7582e 100644 --- a/tests/ui/issues/issue-5917.rs +++ b/tests/ui/static/static-list-initialization-5917.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5917 //@ run-pass #![allow(non_upper_case_globals)] diff --git a/tests/ui/issues/issue-5688.rs b/tests/ui/static/static-struct-initialization-5688.rs index a7db1dfb15f..6a4c2f45b6b 100644 --- a/tests/ui/issues/issue-5688.rs +++ b/tests/ui/static/static-struct-initialization-5688.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5688 //@ run-pass /* # Corrupted initialization in the static struct diff --git a/tests/ui/structs-enums/auxiliary/aux-8044.rs b/tests/ui/structs/auxiliary/aux-8044.rs index 2ec25f51cde..2ec25f51cde 100644 --- a/tests/ui/structs-enums/auxiliary/aux-8044.rs +++ b/tests/ui/structs/auxiliary/aux-8044.rs diff --git a/tests/ui/structs-enums/struct-and-enum-usage-8044.rs b/tests/ui/structs/btree-struct-usage-8044.rs index 9b544f33f1c..9b544f33f1c 100644 --- a/tests/ui/structs-enums/struct-and-enum-usage-8044.rs +++ b/tests/ui/structs/btree-struct-usage-8044.rs diff --git a/tests/ui/issues/issue-6344-let.rs b/tests/ui/structs/destructuring-struct-with-dtor-6344.rs index 1e1bdfa17be..b107a99e89f 100644 --- a/tests/ui/issues/issue-6344-let.rs +++ b/tests/ui/structs/destructuring-struct-with-dtor-6344.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6344 //@ run-pass #![allow(non_shorthand_field_patterns)] diff --git a/tests/ui/issues/issue-5439.rs b/tests/ui/structs/nonexistent-struct-field-error-5439.rs index 852b264dc5d..b2b3293ac91 100644 --- a/tests/ui/issues/issue-5439.rs +++ b/tests/ui/structs/nonexistent-struct-field-error-5439.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5439 struct Foo { foo: isize, } diff --git a/tests/ui/issues/issue-5439.stderr b/tests/ui/structs/nonexistent-struct-field-error-5439.stderr index 6d1d74e3045..b560772fbf0 100644 --- a/tests/ui/issues/issue-5439.stderr +++ b/tests/ui/structs/nonexistent-struct-field-error-5439.stderr @@ -1,5 +1,5 @@ error[E0560]: struct `Foo` has no field named `nonexistent` - --> $DIR/issue-5439.rs:11:31 + --> $DIR/nonexistent-struct-field-error-5439.rs:12:31 | LL | return Box::new(Foo { nonexistent: self, foo: i }); | ^^^^^^^^^^^ `Foo` does not have this field diff --git a/tests/ui/issues/issue-5666.rs b/tests/ui/traits/dynamic-dispatch-trait-objects-5666.rs index 76e2f8229a0..e335949d832 100644 --- a/tests/ui/issues/issue-5666.rs +++ b/tests/ui/traits/dynamic-dispatch-trait-objects-5666.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5666 //@ run-pass struct Dog { @@ -14,7 +15,6 @@ impl Barks for Dog { } } - pub fn main() { let snoopy = Box::new(Dog{name: "snoopy".to_string()}); let bubbles = Box::new(Dog{name: "bubbles".to_string()}); diff --git a/tests/ui/issues/issue-53568.rs b/tests/ui/traits/nll-ice-custom-type-ops-53568.rs index 9862d4ced12..9b240cdc190 100644 --- a/tests/ui/issues/issue-53568.rs +++ b/tests/ui/traits/nll-ice-custom-type-ops-53568.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/53568 // Regression test for an NLL-related ICE (#53568) -- we failed to // resolve inference variables in "custom type-ops". // diff --git a/tests/ui/issues/issue-5883.rs b/tests/ui/traits/opaque-trait-size-error-5883.rs index dd4753e0344..e39e24e7342 100644 --- a/tests/ui/issues/issue-5883.rs +++ b/tests/ui/traits/opaque-trait-size-error-5883.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5883 trait A {} struct Struct { diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/traits/opaque-trait-size-error-5883.stderr index 2ca437b8c47..78de250b19a 100644 --- a/tests/ui/issues/issue-5883.stderr +++ b/tests/ui/traits/opaque-trait-size-error-5883.stderr @@ -1,19 +1,19 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:9:6 + --> $DIR/opaque-trait-size-error-5883.rs:10:6 | LL | ) -> Struct { | ^^^^^^ doesn't have a size known at compile-time | = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)` note: required because it appears within the type `Struct` - --> $DIR/issue-5883.rs:3:8 + --> $DIR/opaque-trait-size-error-5883.rs:4:8 | LL | struct Struct { | ^^^^^^ = note: the return type of a function must have a statically known size error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:8:8 + --> $DIR/opaque-trait-size-error-5883.rs:9:8 | LL | r: dyn A + 'static | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/traits/self-implements-kinds-in-default-methods-8171.rs b/tests/ui/traits/self-not-send-in-default-method-8171.rs index 59ea62c7690..59ea62c7690 100644 --- a/tests/ui/traits/self-implements-kinds-in-default-methods-8171.rs +++ b/tests/ui/traits/self-not-send-in-default-method-8171.rs diff --git a/tests/ui/issues/issue-6898.rs b/tests/ui/traits/trait-implementation-generic-access-6898.rs index c810acaf61b..e9437b1c522 100644 --- a/tests/ui/issues/issue-6898.rs +++ b/tests/ui/traits/trait-implementation-generic-access-6898.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6898 //@ check-pass use std::mem; diff --git a/tests/ui/issues/issue-5988.rs b/tests/ui/traits/trait-implementation-restriction-5988.rs index b7527d9bea8..d3a5b10569b 100644 --- a/tests/ui/issues/issue-5988.rs +++ b/tests/ui/traits/trait-implementation-restriction-5988.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5988 //@ run-pass trait B { diff --git a/tests/ui/traits/trait-implementation-and-usage-7563.rs b/tests/ui/traits/trait-object-lifetime-bounds-7563.rs index 8cfc7a14ffe..8cfc7a14ffe 100644 --- a/tests/ui/traits/trait-implementation-and-usage-7563.rs +++ b/tests/ui/traits/trait-object-lifetime-bounds-7563.rs diff --git a/tests/ui/issues/issue-7344.rs b/tests/ui/unreachable-code/boolean-negation-in-unreachable-code-7344.rs index 406b24634f5..8fd091872c3 100644 --- a/tests/ui/issues/issue-7344.rs +++ b/tests/ui/unreachable-code/boolean-negation-in-unreachable-code-7344.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7344 //@ run-pass #![allow(unused_must_use)] diff --git a/tests/ui/issues/auxiliary/issue-5844-aux.rs b/tests/ui/unsafe/auxiliary/aux-5844.rs index ea83378cad6..ea83378cad6 100644 --- a/tests/ui/issues/auxiliary/issue-5844-aux.rs +++ b/tests/ui/unsafe/auxiliary/aux-5844.rs diff --git a/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs b/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs new file mode 100644 index 00000000000..11863ce647a --- /dev/null +++ b/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs @@ -0,0 +1,8 @@ +// https://github.com/rust-lang/rust/issues/5844 +//@aux-build:aux-5844.rs + +extern crate aux_5844; + +fn main() { + aux_5844::rand(); //~ ERROR: requires unsafe +} diff --git a/tests/ui/issues/issue-5844.stderr b/tests/ui/unsafe/extern-function-requires-unsafe-5844.stderr index bae917fa72c..44dee178991 100644 --- a/tests/ui/issues/issue-5844.stderr +++ b/tests/ui/unsafe/extern-function-requires-unsafe-5844.stderr @@ -1,8 +1,8 @@ error[E0133]: call to unsafe function `rand` is unsafe and requires unsafe function or block - --> $DIR/issue-5844.rs:6:5 + --> $DIR/extern-function-requires-unsafe-5844.rs:7:5 | -LL | issue_5844_aux::rand(); - | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function +LL | aux_5844::rand(); + | ^^^^^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior |
