diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index f61efcf238852..abe7fb77e847e 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -294,6 +294,9 @@ pub enum AttributeKind { /// Represents `#[link_name]`. LinkName { name: Symbol, span: Span }, + /// Represents `#[link_ordinal]`. + LinkOrdinal { ordinal: u16, span: Span }, + /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute) LinkSection { name: Symbol, span: Span }, diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index ad587523e0373..b7653881a7886 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -40,6 +40,7 @@ impl AttributeKind { Ignore { .. } => No, Inline(..) => No, LinkName { .. } => Yes, + LinkOrdinal { .. } => No, LinkSection { .. } => No, LoopMatch(..) => No, MacroTransparency(..) => Yes, diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index bec3a1e8a599b..8d0ead63a8d82 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -78,6 +78,9 @@ attr_parsing_invalid_repr_hint_no_value = attr_parsing_invalid_since = 'since' must be a Rust version number, such as "1.31.0" +attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}` + .note = the value may not exceed `u16::MAX` + attr_parsing_missing_feature = missing 'feature' diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 23a8e96482de8..960cebd89259a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,14 +1,14 @@ use rustc_attr_data_structures::AttributeKind; -use rustc_attr_data_structures::AttributeKind::{LinkName, LinkSection}; +use rustc_attr_data_structures::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; use rustc_feature::{AttributeTemplate, template}; use rustc_span::{Span, Symbol, sym}; use crate::attributes::{ AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, }; -use crate::context::{AcceptContext, Stage}; +use crate::context::{AcceptContext, Stage, parse_single_integer}; use crate::parser::ArgParser; -use crate::session_diagnostics::NullOnLinkSection; +use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection}; pub(crate) struct LinkNameParser; @@ -87,3 +87,36 @@ impl NoArgsAttributeParser for StdInternalSymbolParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol; } + +pub(crate) struct LinkOrdinalParser; + +impl SingleAttributeParser for LinkOrdinalParser { + const PATH: &[Symbol] = &[sym::link_ordinal]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const TEMPLATE: AttributeTemplate = template!(List: "ordinal"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let ordinal = parse_single_integer(cx, args)?; + + // According to the table at + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, the + // ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined + // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import + // information to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t. + // + // FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for + // this: both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that + // specifies a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import + // library for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an + // import library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I + // don't know yet if the resulting EXE runs, as I haven't yet built the necessary DLL -- + // see earlier comment about LINK.EXE failing.) + let Ok(ordinal) = ordinal.try_into() else { + cx.emit_err(LinkOrdinalOutOfRange { span: cx.attr_span, ordinal }); + return None; + }; + + Some(LinkOrdinal { ordinal, span: cx.attr_span }) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index ec821cb11ce9f..7ca951dc0bbb0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,10 +1,9 @@ -use rustc_ast::LitKind; use rustc_attr_data_structures::AttributeKind; use rustc_feature::{AttributeTemplate, template}; use rustc_span::{Symbol, sym}; use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; +use crate::context::{AcceptContext, Stage, parse_single_integer}; use crate::parser::ArgParser; pub(crate) struct RustcLayoutScalarValidRangeStart; @@ -16,8 +15,8 @@ impl SingleAttributeParser for RustcLayoutScalarValidRangeStart { const TEMPLATE: AttributeTemplate = template!(List: "start"); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { - parse_rustc_layout_scalar_valid_range(cx, args) - .map(|n| AttributeKind::RustcLayoutScalarValidRangeStart(n, cx.attr_span)) + parse_single_integer(cx, args) + .map(|n| AttributeKind::RustcLayoutScalarValidRangeStart(Box::new(n), cx.attr_span)) } } @@ -30,34 +29,11 @@ impl SingleAttributeParser for RustcLayoutScalarValidRangeEnd { const TEMPLATE: AttributeTemplate = template!(List: "end"); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { - parse_rustc_layout_scalar_valid_range(cx, args) - .map(|n| AttributeKind::RustcLayoutScalarValidRangeEnd(n, cx.attr_span)) + parse_single_integer(cx, args) + .map(|n| AttributeKind::RustcLayoutScalarValidRangeEnd(Box::new(n), cx.attr_span)) } } -fn parse_rustc_layout_scalar_valid_range( - cx: &mut AcceptContext<'_, '_, S>, - args: &ArgParser<'_>, -) -> Option> { - let Some(list) = args.list() else { - cx.expected_list(cx.attr_span); - return None; - }; - let Some(single) = list.single() else { - cx.expected_single_argument(list.span); - return None; - }; - let Some(lit) = single.lit() else { - cx.expected_integer_literal(single.span()); - return None; - }; - let LitKind::Int(num, _ty) = lit.kind else { - cx.expected_integer_literal(single.span()); - return None; - }; - Some(Box::new(num.0)) -} - pub(crate) struct RustcObjectLifetimeDefaultParser; impl SingleAttributeParser for RustcObjectLifetimeDefaultParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index ad48eb1498e11..4e4eeac92bb4f 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -5,7 +5,7 @@ use std::ops::{Deref, DerefMut}; use std::sync::LazyLock; use private::Sealed; -use rustc_ast::{self as ast, MetaItemLit, NodeId}; +use rustc_ast::{self as ast, LitKind, MetaItemLit, NodeId}; use rustc_attr_data_structures::AttributeKind; use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind}; use rustc_errors::{DiagCtxtHandle, Diagnostic}; @@ -24,8 +24,8 @@ use crate::attributes::deprecation::DeprecationParser; use crate::attributes::dummy::DummyParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; use crate::attributes::link_attrs::{ - ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkSectionParser, - StdInternalSymbolParser, + ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser, + LinkSectionParser, StdInternalSymbolParser, }; use crate::attributes::lint_helpers::{AsPtrParser, PassByValueParser, PubTransparentParser}; use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; @@ -141,6 +141,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, @@ -772,3 +773,32 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { } } } + +/// Parse a single integer. +/// +/// Used by attributes that take a single integer as argument, such as +/// `#[link_ordinal]` and `#[rustc_layout_scalar_valid_range_start]`. +/// `cx` is the context given to the attribute. +/// `args` is the parser for the attribute arguments. +pub(crate) fn parse_single_integer( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser<'_>, +) -> Option { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span); + return None; + }; + let Some(single) = list.single() else { + cx.expected_single_argument(list.span); + return None; + }; + let Some(lit) = single.lit() else { + cx.expected_integer_literal(single.span()); + return None; + }; + let LitKind::Int(num, _ty) = lit.kind else { + cx.expected_integer_literal(single.span()); + return None; + }; + Some(num.0) +} diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 28f6786f37fae..8a240639d75a8 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -514,6 +514,15 @@ pub(crate) struct NakedFunctionIncompatibleAttribute { pub attr: String, } +#[derive(Diagnostic)] +#[diag(attr_parsing_link_ordinal_out_of_range)] +#[note] +pub(crate) struct LinkOrdinalOutOfRange { + #[primary_span] + pub span: Span, + pub ordinal: u128, +} + pub(crate) enum AttributeParseErrorReason { ExpectedNoArgs, ExpectedStringLiteral { byte_string: Option }, diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 63e9005da45c2..c7bd6ffd1f27c 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -80,9 +80,6 @@ codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extensio codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced -codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal` - .note = an unsuffixed integer value, e.g., `1`, is expected - codegen_ssa_incorrect_cgu_reuse_type = CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least -> [one] {"at least "} @@ -93,9 +90,6 @@ codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and i codegen_ssa_invalid_instruction_set = invalid instruction set specified -codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]` - .note = the attribute requires exactly one argument - codegen_ssa_invalid_literal_value = invalid literal value .label = value must be an integer between `0` and `255` diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 85d01d4f93898..dd49db26689e0 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -116,6 +116,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align), AttributeKind::LinkName { name, .. } => codegen_fn_attrs.link_name = Some(*name), + AttributeKind::LinkOrdinal { ordinal, span } => { + codegen_fn_attrs.link_ordinal = Some(*ordinal); + link_ordinal_span = Some(*span); + } AttributeKind::LinkSection { name, .. } => { codegen_fn_attrs.link_section = Some(*name) } @@ -250,12 +254,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } } - sym::link_ordinal => { - link_ordinal_span = Some(attr.span()); - if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { - codegen_fn_attrs.link_ordinal = ordinal; - } - } sym::no_sanitize => { no_sanitize_span = Some(attr.span()); if let Some(list) = attr.meta_item_list() { @@ -568,45 +566,6 @@ fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment } -fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option { - use rustc_ast::{LitIntType, LitKind, MetaItemLit}; - let meta_item_list = attr.meta_item_list()?; - let [sole_meta_list] = &meta_item_list[..] else { - tcx.dcx().emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span() }); - return None; - }; - if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = - sole_meta_list.lit() - { - // According to the table at - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, the - // ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined - // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import - // information to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t. - // - // FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for - // this: both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that - // specifies a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import - // library for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an - // import library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I - // don't know yet if the resulting EXE runs, as I haven't yet built the necessary DLL -- - // see earlier comment about LINK.EXE failing.) - if *ordinal <= u16::MAX as u128 { - Some(ordinal.get() as u16) - } else { - let msg = format!("ordinal value in `link_ordinal` is too large: `{ordinal}`"); - tcx.dcx() - .struct_span_err(attr.span(), msg) - .with_note("the value may not exceed `u16::MAX`") - .emit(); - None - } - } else { - tcx.dcx().emit_err(errors::InvalidLinkOrdinalFormat { span: attr.span() }); - None - } -} - fn check_link_name_xor_ordinal( tcx: TyCtxt<'_>, codegen_fn_attrs: &CodegenFnAttrs, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index e042fe1f81966..9040915b6af34 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1108,22 +1108,6 @@ pub(crate) struct InvalidNoSanitize { pub span: Span, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_invalid_link_ordinal_nargs)] -#[note] -pub(crate) struct InvalidLinkOrdinalNargs { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(codegen_ssa_illegal_link_ordinal_format)] -#[note] -pub(crate) struct InvalidLinkOrdinalFormat { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_target_feature_safe_trait)] pub(crate) struct TargetFeatureSafeTrait { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index f10d71f4c6540..4d276f814ef25 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf}; use rustc_abi::ExternAbi; use rustc_ast::CRATE_NODE_ID; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_attr_parsing as attr; use rustc_data_structures::fx::FxHashSet; use rustc_middle::query::LocalCrate; @@ -496,14 +497,9 @@ impl<'tcx> Collector<'tcx> { } _ => { for &child_item in foreign_items { - if self.tcx.def_kind(child_item).has_codegen_attrs() - && self.tcx.codegen_fn_attrs(child_item).link_ordinal.is_some() + if let Some(span) = find_attr!(self.tcx.get_all_attrs(child_item), AttributeKind::LinkOrdinal {span, ..} => *span) { - let link_ordinal_attr = - self.tcx.get_attr(child_item, sym::link_ordinal).unwrap(); - sess.dcx().emit_err(errors::LinkOrdinalRawDylib { - span: link_ordinal_attr.span(), - }); + sess.dcx().emit_err(errors::LinkOrdinalRawDylib { span }); } } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index bb5c1e0e653a7..03d4b64b823a0 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -310,6 +310,7 @@ pub fn check_builtin_meta_item( | sym::must_use | sym::track_caller | sym::link_name + | sym::link_ordinal | sym::export_name | sym::rustc_macro_transparency | sym::link_section diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9a96749f3e7fd..5f712d7d864c9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -250,6 +250,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::LinkName { span: attr_span, name }) => { self.check_link_name(hir_id, *attr_span, *name, span, target) } + Attribute::Parsed(AttributeKind::LinkOrdinal { span: attr_span, .. }) => { + self.check_link_ordinal(*attr_span, span, target) + } Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => { self.check_may_dangle(hir_id, *attr_span) } @@ -327,7 +330,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::rustc_has_incoherent_inherent_impls, ..] => { self.check_has_incoherent_inherent_impls(attr, span, target) } - [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), + [sym::ffi_pure, ..] => self.check_ffi_pure(attr.span(), attrs, target), + [sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target), [sym::link, ..] => self.check_link(hir_id, attr, span, target), [sym::macro_use, ..] | [sym::macro_escape, ..] => { self.check_macro_use(hir_id, attr, target) @@ -2258,11 +2262,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_link_ordinal(&self, attr: &Attribute, _span: Span, target: Target) { + fn check_link_ordinal(&self, attr_span: Span, _span: Span, target: Target) { match target { Target::ForeignFn | Target::ForeignStatic => {} _ => { - self.dcx().emit_err(errors::LinkOrdinal { attr_span: attr.span() }); + self.dcx().emit_err(errors::LinkOrdinal { attr_span }); } } } diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index e1381ace44151..7d41ae45093ea 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -358,7 +358,7 @@ macro_rules! impl_Display { } #[cfg(feature = "optimize_for_size")] { - offset = _inner_slow_integer_to_str(self.unsigned_abs().$conv_fn(), &mut buf.buf); + offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(self.unsigned_abs().$conv_fn(), &mut buf.buf); } // Only difference between signed and unsigned are these 4 lines. if self < 0 { @@ -401,7 +401,7 @@ macro_rules! impl_Display { } #[cfg(feature = "optimize_for_size")] { - offset = _inner_slow_integer_to_str(self.$conv_fn(), &mut buf.buf); + offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(self.$conv_fn(), &mut buf.buf); } // SAFETY: Starting from `offset`, all elements of the slice have been set. unsafe { slice_buffer_to_str(&buf.buf, offset) } @@ -412,7 +412,7 @@ macro_rules! impl_Display { )* #[cfg(feature = "optimize_for_size")] - fn _inner_slow_integer_to_str(mut n: $u, buf: &mut [MaybeUninit::]) -> usize { + fn ${concat(_inner_slow_integer_to_str, $gen_name)}(mut n: $u, buf: &mut [MaybeUninit::]) -> usize { let mut curr = buf.len(); // SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning @@ -437,7 +437,7 @@ macro_rules! impl_Display { const MAX_DEC_N: usize = $u::MAX.ilog(10) as usize + 1; let mut buf = [MaybeUninit::::uninit(); MAX_DEC_N]; - let offset = _inner_slow_integer_to_str(n, &mut buf); + let offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(n, &mut buf); // SAFETY: Starting from `offset`, all elements of the slice have been set. let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) }; f.pad_integral(is_nonnegative, "", buf_slice) diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs index 854e03cf18279..b5dfe6dbd71e1 100644 --- a/library/core/src/io/borrowed_buf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -69,6 +69,23 @@ impl<'data> From<&'data mut [MaybeUninit]> for BorrowedBuf<'data> { } } +/// Creates a new `BorrowedBuf` from a cursor. +/// +/// Use `BorrowedCursor::with_unfilled_buf` instead for a safer alternative. +impl<'data> From> for BorrowedBuf<'data> { + #[inline] + fn from(mut buf: BorrowedCursor<'data>) -> BorrowedBuf<'data> { + let init = buf.init_mut().len(); + BorrowedBuf { + // SAFETY: no initialized byte is ever uninitialized as per + // `BorrowedBuf`'s invariant + buf: unsafe { buf.buf.buf.get_unchecked_mut(buf.buf.filled..) }, + filled: 0, + init, + } + } +} + impl<'data> BorrowedBuf<'data> { /// Returns the total capacity of the buffer. #[inline] @@ -353,4 +370,38 @@ impl<'a> BorrowedCursor<'a> { } self.buf.filled += buf.len(); } + + /// Runs the given closure with a `BorrowedBuf` containing the unfilled part + /// of the cursor. + /// + /// This enables inspecting what was written to the cursor. + /// + /// # Panics + /// + /// Panics if the `BorrowedBuf` given to the closure is replaced by another + /// one. + pub fn with_unfilled_buf(&mut self, f: impl FnOnce(&mut BorrowedBuf<'_>) -> T) -> T { + let mut buf = BorrowedBuf::from(self.reborrow()); + let prev_ptr = buf.buf as *const _; + let res = f(&mut buf); + + // Check that the caller didn't replace the `BorrowedBuf`. + // This is necessary for the safety of the code below: if the check wasn't + // there, one could mark some bytes as initialized even though there aren't. + assert!(core::ptr::addr_eq(prev_ptr, buf.buf)); + + let filled = buf.filled; + let init = buf.init; + + // Update `init` and `filled` fields with what was written to the buffer. + // `self.buf.filled` was the starting length of the `BorrowedBuf`. + // + // SAFETY: These amounts of bytes were initialized/filled in the `BorrowedBuf`, + // and therefore they are initialized/filled in the cursor too, because the + // buffer wasn't replaced. + self.buf.init = self.buf.filled + init; + self.buf.filled += filled; + + res + } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 2f701171505c7..e08edde3b38bb 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -160,6 +160,7 @@ #![feature(lang_items)] #![feature(link_llvm_intrinsics)] #![feature(macro_metavar_expr)] +#![feature(macro_metavar_expr_concat)] #![feature(marker_trait_attr)] #![feature(min_specialization)] #![feature(multiple_supertrait_upcastable)] diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs index 55fa91d0b9f49..c460f38bd2e4d 100644 --- a/library/core/src/num/wrapping.rs +++ b/library/core/src/num/wrapping.rs @@ -94,9 +94,9 @@ macro_rules! sh_impl_signed { #[inline] fn shl(self, other: $f) -> Wrapping<$t> { if other < 0 { - Wrapping(self.0.wrapping_shr((-other & self::shift_max::$t as $f) as u32)) + Wrapping(self.0.wrapping_shr(-other as u32)) } else { - Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32)) + Wrapping(self.0.wrapping_shl(other as u32)) } } } @@ -119,9 +119,9 @@ macro_rules! sh_impl_signed { #[inline] fn shr(self, other: $f) -> Wrapping<$t> { if other < 0 { - Wrapping(self.0.wrapping_shl((-other & self::shift_max::$t as $f) as u32)) + Wrapping(self.0.wrapping_shl(-other as u32)) } else { - Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32)) + Wrapping(self.0.wrapping_shr(other as u32)) } } } @@ -147,7 +147,7 @@ macro_rules! sh_impl_unsigned { #[inline] fn shl(self, other: $f) -> Wrapping<$t> { - Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32)) + Wrapping(self.0.wrapping_shl(other as u32)) } } forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, @@ -168,7 +168,7 @@ macro_rules! sh_impl_unsigned { #[inline] fn shr(self, other: $f) -> Wrapping<$t> { - Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32)) + Wrapping(self.0.wrapping_shr(other as u32)) } } forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, @@ -1052,39 +1052,3 @@ macro_rules! wrapping_int_impl_unsigned { } wrapping_int_impl_unsigned! { usize u8 u16 u32 u64 u128 } - -mod shift_max { - #![allow(non_upper_case_globals)] - - #[cfg(target_pointer_width = "16")] - mod platform { - pub(crate) const usize: u32 = super::u16; - pub(crate) const isize: u32 = super::i16; - } - - #[cfg(target_pointer_width = "32")] - mod platform { - pub(crate) const usize: u32 = super::u32; - pub(crate) const isize: u32 = super::i32; - } - - #[cfg(target_pointer_width = "64")] - mod platform { - pub(crate) const usize: u32 = super::u64; - pub(crate) const isize: u32 = super::i64; - } - - pub(super) const i8: u32 = (1 << 3) - 1; - pub(super) const i16: u32 = (1 << 4) - 1; - pub(super) const i32: u32 = (1 << 5) - 1; - pub(super) const i64: u32 = (1 << 6) - 1; - pub(super) const i128: u32 = (1 << 7) - 1; - pub(super) use self::platform::isize; - - pub(super) const u8: u32 = i8; - pub(super) const u16: u32 = i16; - pub(super) const u32: u32 = i32; - pub(super) const u64: u32 = i64; - pub(super) const u128: u32 = i128; - pub(super) use self::platform::usize; -} diff --git a/library/coretests/tests/io/borrowed_buf.rs b/library/coretests/tests/io/borrowed_buf.rs index fbd3864dcac14..73dbfaf5ee906 100644 --- a/library/coretests/tests/io/borrowed_buf.rs +++ b/library/coretests/tests/io/borrowed_buf.rs @@ -165,3 +165,39 @@ fn cursor_set_init() { assert_eq!(rbuf.unfilled().uninit_mut().len(), 4); assert_eq!(unsafe { rbuf.unfilled().as_mut().len() }, 12); } + +#[test] +fn cursor_with_unfilled_buf() { + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf = BorrowedBuf::from(buf); + let mut cursor = rbuf.unfilled(); + + cursor.with_unfilled_buf(|buf| { + buf.unfilled().append(&[1, 2, 3]); + assert_eq!(buf.filled(), &[1, 2, 3]); + }); + + assert_eq!(cursor.init_mut().len(), 0); + assert_eq!(cursor.written(), 3); + + cursor.with_unfilled_buf(|buf| { + assert_eq!(buf.capacity(), 13); + assert_eq!(buf.init_len(), 0); + + buf.unfilled().ensure_init(); + buf.unfilled().advance(4); + }); + + assert_eq!(cursor.init_mut().len(), 9); + assert_eq!(cursor.written(), 7); + + cursor.with_unfilled_buf(|buf| { + assert_eq!(buf.capacity(), 9); + assert_eq!(buf.init_len(), 9); + }); + + assert_eq!(cursor.init_mut().len(), 9); + assert_eq!(cursor.written(), 7); + + assert_eq!(rbuf.filled(), &[1, 2, 3, 0, 0, 0, 0]); +} diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index b05318ce9e6cf..4f44cf1701c43 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -55,6 +55,9 @@ Similar to shell commands, directives can extend across multiple lines if their last char is `\`. In this case, the start of the next line should be `//`, with no `@`. +Similar to compiletest directives, besides a space you can also use a colon `:` to separate +the directive name and the arguments, however a space is preferred for HtmlDocCk directives. + Use the special string `{{channel}}` in XPaths, `PATTERN` arguments and [snapshot files](#snapshot) if you'd like to refer to the URL `https://doc.rust-lang.org/CHANNEL` where `CHANNEL` refers to the current release channel (e.g, `stable` or `nightly`). diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index ddbd256a0d8c9..72975cc6206c0 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -147,48 +147,17 @@ def concat_multi_lines(f): print_err(lineno, line, "Trailing backslash at the end of the file") -def get_known_directive_names(): - def filter_line(line): - line = line.strip() - return line.startswith('"') and (line.endswith('",') or line.endswith('"')) - - # Equivalent to `src/tools/compiletest/src/header.rs` constant of the same name. - with open( - os.path.join( - # We go back to `src`. - os.path.dirname(os.path.dirname(__file__)), - "tools/compiletest/src/directive-list.rs", - ), - "r", - encoding="utf8", - ) as fd: - content = fd.read() - return [ - line.strip().replace('",', "").replace('"', "") - for line in content.split("\n") - if filter_line(line) - ] - - -# To prevent duplicating the list of commmands between `compiletest` and `htmldocck`, we put -# it into a common file which is included in rust code and parsed here. -# FIXME: This setup is temporary until we figure out how to improve this situation. -# See . -KNOWN_DIRECTIVE_NAMES = get_known_directive_names() - LINE_PATTERN = re.compile( r""" //@\s+ - (?P!?)(?P[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*) - (?P.*)$ + (?P!?)(?P.+?) + (?:[\s:](?P.*))?$ """, re.X | re.UNICODE, ) DEPRECATED_LINE_PATTERN = re.compile( - r""" - //\s+@ -""", + r"//\s+@", re.X | re.UNICODE, ) @@ -209,12 +178,7 @@ def get_commands(template): cmd = m.group("cmd") negated = m.group("negated") == "!" - if not negated and cmd in KNOWN_DIRECTIVE_NAMES: - continue - args = m.group("args") - if args and not args[:1].isspace(): - print_err(lineno, line, "Invalid template syntax") - continue + args = m.group("args") or "" try: args = shlex.split(args) except UnicodeEncodeError: @@ -636,14 +600,11 @@ def check_command(c, cache): else: raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == "valid-html": - raise InvalidCheck("Unimplemented valid-html") - - elif c.cmd == "valid-links": - raise InvalidCheck("Unimplemented valid-links") - else: - raise InvalidCheck("Unrecognized {}".format(c.cmd)) + # Ignore unknown directives as they might be compiletest directives + # since they share the same `//@` prefix by convention. In any case, + # compiletest rejects unknown directives for us. + return if ret == c.negated: raise FailedCheck(cerr) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs deleted file mode 100644 index adf2a7bffeff9..0000000000000 --- a/src/tools/compiletest/src/directive-list.rs +++ /dev/null @@ -1,260 +0,0 @@ -/// This was originally generated by collecting directives from ui tests and then extracting their -/// directive names. This is **not** an exhaustive list of all possible directives. Instead, this is -/// a best-effort approximation for diagnostics. Add new directives to this list when needed. -const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ - // tidy-alphabetical-start - "add-core-stubs", - "assembly-output", - "aux-bin", - "aux-build", - "aux-codegen-backend", - "aux-crate", - "build-aux-docs", - "build-fail", - "build-pass", - "check-fail", - "check-pass", - "check-run-results", - "check-stdout", - "check-test-line-numbers-match", - "compile-flags", - "doc-flags", - "dont-check-compiler-stderr", - "dont-check-compiler-stdout", - "dont-check-failure-status", - "dont-require-annotations", - "edition", - "error-pattern", - "exact-llvm-major-version", - "exec-env", - "failure-status", - "filecheck-flags", - "forbid-output", - "force-host", - "ignore-16bit", - "ignore-32bit", - "ignore-64bit", - "ignore-aarch64", - "ignore-aarch64-pc-windows-msvc", - "ignore-aarch64-unknown-linux-gnu", - "ignore-aix", - "ignore-android", - "ignore-apple", - "ignore-arm", - "ignore-arm-unknown-linux-gnueabi", - "ignore-arm-unknown-linux-gnueabihf", - "ignore-arm-unknown-linux-musleabi", - "ignore-arm-unknown-linux-musleabihf", - "ignore-auxiliary", - "ignore-avr", - "ignore-beta", - "ignore-cdb", - "ignore-compare-mode-next-solver", - "ignore-compare-mode-polonius", - "ignore-coverage-map", - "ignore-coverage-run", - "ignore-cross-compile", - "ignore-eabi", - "ignore-elf", - "ignore-emscripten", - "ignore-endian-big", - "ignore-enzyme", - "ignore-freebsd", - "ignore-fuchsia", - "ignore-gdb", - "ignore-gdb-version", - "ignore-gnu", - "ignore-haiku", - "ignore-horizon", - "ignore-i686-pc-windows-gnu", - "ignore-i686-pc-windows-msvc", - "ignore-illumos", - "ignore-ios", - "ignore-linux", - "ignore-lldb", - "ignore-llvm-version", - "ignore-loongarch32", - "ignore-loongarch64", - "ignore-macabi", - "ignore-macos", - "ignore-msp430", - "ignore-msvc", - "ignore-musl", - "ignore-netbsd", - "ignore-nightly", - "ignore-none", - "ignore-nto", - "ignore-nvptx64", - "ignore-nvptx64-nvidia-cuda", - "ignore-openbsd", - "ignore-pass", - "ignore-powerpc", - "ignore-remote", - "ignore-riscv64", - "ignore-rustc-debug-assertions", - "ignore-rustc_abi-x86-sse2", - "ignore-s390x", - "ignore-sgx", - "ignore-sparc64", - "ignore-spirv", - "ignore-stable", - "ignore-stage1", - "ignore-stage2", - "ignore-std-debug-assertions", - "ignore-test", - "ignore-thumb", - "ignore-thumbv8m.base-none-eabi", - "ignore-thumbv8m.main-none-eabi", - "ignore-tvos", - "ignore-unix", - "ignore-unknown", - "ignore-uwp", - "ignore-visionos", - "ignore-vxworks", - "ignore-wasi", - "ignore-wasm", - "ignore-wasm32", - "ignore-wasm32-bare", - "ignore-wasm64", - "ignore-watchos", - "ignore-windows", - "ignore-windows-gnu", - "ignore-windows-msvc", - "ignore-x32", - "ignore-x86", - "ignore-x86_64", - "ignore-x86_64-apple-darwin", - "ignore-x86_64-pc-windows-gnu", - "ignore-x86_64-unknown-linux-gnu", - "incremental", - "known-bug", - "llvm-cov-flags", - "max-llvm-major-version", - "min-cdb-version", - "min-gdb-version", - "min-lldb-version", - "min-llvm-version", - "min-system-llvm-version", - "needs-asm-support", - "needs-crate-type", - "needs-deterministic-layouts", - "needs-dlltool", - "needs-dynamic-linking", - "needs-enzyme", - "needs-force-clang-based-tests", - "needs-git-hash", - "needs-llvm-components", - "needs-llvm-zstd", - "needs-profiler-runtime", - "needs-relocation-model-pic", - "needs-run-enabled", - "needs-rust-lld", - "needs-rustc-debug-assertions", - "needs-sanitizer-address", - "needs-sanitizer-cfi", - "needs-sanitizer-dataflow", - "needs-sanitizer-hwaddress", - "needs-sanitizer-kcfi", - "needs-sanitizer-leak", - "needs-sanitizer-memory", - "needs-sanitizer-memtag", - "needs-sanitizer-safestack", - "needs-sanitizer-shadow-call-stack", - "needs-sanitizer-support", - "needs-sanitizer-thread", - "needs-std-debug-assertions", - "needs-subprocess", - "needs-symlink", - "needs-target-has-atomic", - "needs-target-std", - "needs-threads", - "needs-unwind", - "needs-wasmtime", - "needs-xray", - "no-auto-check-cfg", - "no-prefer-dynamic", - "normalize-stderr", - "normalize-stderr-32bit", - "normalize-stderr-64bit", - "normalize-stdout", - "only-16bit", - "only-32bit", - "only-64bit", - "only-aarch64", - "only-aarch64-apple-darwin", - "only-aarch64-unknown-linux-gnu", - "only-apple", - "only-arm", - "only-avr", - "only-beta", - "only-bpf", - "only-cdb", - "only-dist", - "only-elf", - "only-emscripten", - "only-gnu", - "only-i686-pc-windows-gnu", - "only-i686-pc-windows-msvc", - "only-i686-unknown-linux-gnu", - "only-ios", - "only-linux", - "only-loongarch32", - "only-loongarch64", - "only-loongarch64-unknown-linux-gnu", - "only-macos", - "only-mips", - "only-mips64", - "only-msp430", - "only-msvc", - "only-nightly", - "only-nvptx64", - "only-powerpc", - "only-riscv64", - "only-rustc_abi-x86-sse2", - "only-s390x", - "only-sparc", - "only-sparc64", - "only-stable", - "only-thumb", - "only-tvos", - "only-unix", - "only-visionos", - "only-wasm32", - "only-wasm32-bare", - "only-wasm32-wasip1", - "only-watchos", - "only-windows", - "only-windows-gnu", - "only-windows-msvc", - "only-x86", - "only-x86_64", - "only-x86_64-apple-darwin", - "only-x86_64-fortanix-unknown-sgx", - "only-x86_64-pc-windows-gnu", - "only-x86_64-pc-windows-msvc", - "only-x86_64-unknown-linux-gnu", - "pp-exact", - "pretty-compare-only", - "pretty-mode", - "proc-macro", - "reference", - "regex-error-pattern", - "remap-src-base", - "revisions", - "run-fail", - "run-flags", - "run-pass", - "run-rustfix", - "rustc-env", - "rustfix-only-machine-applicable", - "should-fail", - "should-ice", - "stderr-per-bitwidth", - "test-mir-pass", - "unique-doc-out-dir", - "unset-exec-env", - "unset-rustc-env", - // Used by the tidy check `unknown_revision`. - "unused-revision-names", - // tidy-alphabetical-end -]; diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 7fadb4dae2a1d..215793fe947f8 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -765,11 +765,266 @@ fn line_directive<'line>( Some(DirectiveLine { line_number, revision, raw_directive }) } -// To prevent duplicating the list of directives between `compiletest`,`htmldocck` and `jsondocck`, -// we put it into a common file which is included in rust code and parsed here. -// FIXME: This setup is temporary until we figure out how to improve this situation. -// See . -include!("directive-list.rs"); +/// This was originally generated by collecting directives from ui tests and then extracting their +/// directive names. This is **not** an exhaustive list of all possible directives. Instead, this is +/// a best-effort approximation for diagnostics. Add new directives to this list when needed. +const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ + // tidy-alphabetical-start + "add-core-stubs", + "assembly-output", + "aux-bin", + "aux-build", + "aux-codegen-backend", + "aux-crate", + "build-aux-docs", + "build-fail", + "build-pass", + "check-fail", + "check-pass", + "check-run-results", + "check-stdout", + "check-test-line-numbers-match", + "compile-flags", + "doc-flags", + "dont-check-compiler-stderr", + "dont-check-compiler-stdout", + "dont-check-failure-status", + "dont-require-annotations", + "edition", + "error-pattern", + "exact-llvm-major-version", + "exec-env", + "failure-status", + "filecheck-flags", + "forbid-output", + "force-host", + "ignore-16bit", + "ignore-32bit", + "ignore-64bit", + "ignore-aarch64", + "ignore-aarch64-pc-windows-msvc", + "ignore-aarch64-unknown-linux-gnu", + "ignore-aix", + "ignore-android", + "ignore-apple", + "ignore-arm", + "ignore-arm-unknown-linux-gnueabi", + "ignore-arm-unknown-linux-gnueabihf", + "ignore-arm-unknown-linux-musleabi", + "ignore-arm-unknown-linux-musleabihf", + "ignore-auxiliary", + "ignore-avr", + "ignore-beta", + "ignore-cdb", + "ignore-compare-mode-next-solver", + "ignore-compare-mode-polonius", + "ignore-coverage-map", + "ignore-coverage-run", + "ignore-cross-compile", + "ignore-eabi", + "ignore-elf", + "ignore-emscripten", + "ignore-endian-big", + "ignore-enzyme", + "ignore-freebsd", + "ignore-fuchsia", + "ignore-gdb", + "ignore-gdb-version", + "ignore-gnu", + "ignore-haiku", + "ignore-horizon", + "ignore-i686-pc-windows-gnu", + "ignore-i686-pc-windows-msvc", + "ignore-illumos", + "ignore-ios", + "ignore-linux", + "ignore-lldb", + "ignore-llvm-version", + "ignore-loongarch32", + "ignore-loongarch64", + "ignore-macabi", + "ignore-macos", + "ignore-msp430", + "ignore-msvc", + "ignore-musl", + "ignore-netbsd", + "ignore-nightly", + "ignore-none", + "ignore-nto", + "ignore-nvptx64", + "ignore-nvptx64-nvidia-cuda", + "ignore-openbsd", + "ignore-pass", + "ignore-powerpc", + "ignore-remote", + "ignore-riscv64", + "ignore-rustc-debug-assertions", + "ignore-rustc_abi-x86-sse2", + "ignore-s390x", + "ignore-sgx", + "ignore-sparc64", + "ignore-spirv", + "ignore-stable", + "ignore-stage1", + "ignore-stage2", + "ignore-std-debug-assertions", + "ignore-test", + "ignore-thumb", + "ignore-thumbv8m.base-none-eabi", + "ignore-thumbv8m.main-none-eabi", + "ignore-tvos", + "ignore-unix", + "ignore-unknown", + "ignore-uwp", + "ignore-visionos", + "ignore-vxworks", + "ignore-wasi", + "ignore-wasm", + "ignore-wasm32", + "ignore-wasm32-bare", + "ignore-wasm64", + "ignore-watchos", + "ignore-windows", + "ignore-windows-gnu", + "ignore-windows-msvc", + "ignore-x32", + "ignore-x86", + "ignore-x86_64", + "ignore-x86_64-apple-darwin", + "ignore-x86_64-pc-windows-gnu", + "ignore-x86_64-unknown-linux-gnu", + "incremental", + "known-bug", + "llvm-cov-flags", + "max-llvm-major-version", + "min-cdb-version", + "min-gdb-version", + "min-lldb-version", + "min-llvm-version", + "min-system-llvm-version", + "needs-asm-support", + "needs-crate-type", + "needs-deterministic-layouts", + "needs-dlltool", + "needs-dynamic-linking", + "needs-enzyme", + "needs-force-clang-based-tests", + "needs-git-hash", + "needs-llvm-components", + "needs-llvm-zstd", + "needs-profiler-runtime", + "needs-relocation-model-pic", + "needs-run-enabled", + "needs-rust-lld", + "needs-rustc-debug-assertions", + "needs-sanitizer-address", + "needs-sanitizer-cfi", + "needs-sanitizer-dataflow", + "needs-sanitizer-hwaddress", + "needs-sanitizer-kcfi", + "needs-sanitizer-leak", + "needs-sanitizer-memory", + "needs-sanitizer-memtag", + "needs-sanitizer-safestack", + "needs-sanitizer-shadow-call-stack", + "needs-sanitizer-support", + "needs-sanitizer-thread", + "needs-std-debug-assertions", + "needs-subprocess", + "needs-symlink", + "needs-target-has-atomic", + "needs-target-std", + "needs-threads", + "needs-unwind", + "needs-wasmtime", + "needs-xray", + "no-auto-check-cfg", + "no-prefer-dynamic", + "normalize-stderr", + "normalize-stderr-32bit", + "normalize-stderr-64bit", + "normalize-stdout", + "only-16bit", + "only-32bit", + "only-64bit", + "only-aarch64", + "only-aarch64-apple-darwin", + "only-aarch64-unknown-linux-gnu", + "only-apple", + "only-arm", + "only-avr", + "only-beta", + "only-bpf", + "only-cdb", + "only-dist", + "only-elf", + "only-emscripten", + "only-gnu", + "only-i686-pc-windows-gnu", + "only-i686-pc-windows-msvc", + "only-i686-unknown-linux-gnu", + "only-ios", + "only-linux", + "only-loongarch32", + "only-loongarch64", + "only-loongarch64-unknown-linux-gnu", + "only-macos", + "only-mips", + "only-mips64", + "only-msp430", + "only-msvc", + "only-nightly", + "only-nvptx64", + "only-powerpc", + "only-riscv64", + "only-rustc_abi-x86-sse2", + "only-s390x", + "only-sparc", + "only-sparc64", + "only-stable", + "only-thumb", + "only-tvos", + "only-unix", + "only-visionos", + "only-wasm32", + "only-wasm32-bare", + "only-wasm32-wasip1", + "only-watchos", + "only-windows", + "only-windows-gnu", + "only-windows-msvc", + "only-x86", + "only-x86_64", + "only-x86_64-apple-darwin", + "only-x86_64-fortanix-unknown-sgx", + "only-x86_64-pc-windows-gnu", + "only-x86_64-pc-windows-msvc", + "only-x86_64-unknown-linux-gnu", + "pp-exact", + "pretty-compare-only", + "pretty-mode", + "proc-macro", + "reference", + "regex-error-pattern", + "remap-src-base", + "revisions", + "run-fail", + "run-flags", + "run-pass", + "run-rustfix", + "rustc-env", + "rustfix-only-machine-applicable", + "should-fail", + "should-ice", + "stderr-per-bitwidth", + "test-mir-pass", + "unique-doc-out-dir", + "unset-exec-env", + "unset-rustc-env", + // Used by the tidy check `unknown_revision`. + "unused-revision-names", + // tidy-alphabetical-end +]; const KNOWN_HTMLDOCCK_DIRECTIVE_NAMES: &[&str] = &[ "count", @@ -834,35 +1089,26 @@ pub(crate) struct CheckDirectiveResult<'ln> { pub(crate) fn check_directive<'a>( directive_ln: &'a str, mode: TestMode, - original_line: &str, ) -> CheckDirectiveResult<'a> { let (directive_name, post) = directive_ln.split_once([':', ' ']).unwrap_or((directive_ln, "")); + let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name) + || match mode { + TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES.contains(&directive_name), + TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES.contains(&directive_name), + _ => false, + }; + let trailing = post.trim().split_once(' ').map(|(pre, _)| pre).unwrap_or(post); - let is_known = |s: &str| { - KNOWN_DIRECTIVE_NAMES.contains(&s) - || match mode { - TestMode::Rustdoc | TestMode::RustdocJson => { - original_line.starts_with("//@") - && match mode { - TestMode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES, - TestMode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES, - _ => unreachable!(), - } - .contains(&s) - } - _ => false, - } - }; let trailing_directive = { // 1. is the directive name followed by a space? (to exclude `:`) - matches!(directive_ln.get(directive_name.len()..), Some(s) if s.starts_with(' ')) + directive_ln.get(directive_name.len()..).is_some_and(|s| s.starts_with(' ')) // 2. is what is after that directive also a directive (ex: "only-x86 only-arm") - && is_known(trailing) + && KNOWN_DIRECTIVE_NAMES.contains(&trailing) } .then_some(trailing); - CheckDirectiveResult { is_known_directive: is_known(&directive_name), trailing_directive } + CheckDirectiveResult { is_known_directive, trailing_directive } } const COMPILETEST_DIRECTIVE_PREFIX: &str = "//@"; @@ -914,9 +1160,9 @@ fn iter_directives( }; // Perform unknown directive check on Rust files. - if testfile.extension().map(|e| e == "rs").unwrap_or(false) { + if testfile.extension() == Some("rs") { let CheckDirectiveResult { is_known_directive, trailing_directive } = - check_directive(directive_line.raw_directive, mode, ln); + check_directive(directive_line.raw_directive, mode); if !is_known_directive { *poisoned = true; @@ -936,7 +1182,7 @@ fn iter_directives( "{testfile}:{line_number}: detected trailing compiletest test directive `{}`", trailing_directive, ); - help!("put the trailing directive in it's own line: `//@ {}`", trailing_directive); + help!("put the trailing directive in its own line: `//@ {}`", trailing_directive); return; } diff --git a/src/tools/compiletest/src/runtest/rustdoc.rs b/src/tools/compiletest/src/runtest/rustdoc.rs index 637ea833357a2..236f021ce827c 100644 --- a/src/tools/compiletest/src/runtest/rustdoc.rs +++ b/src/tools/compiletest/src/runtest/rustdoc.rs @@ -4,7 +4,7 @@ use super::{TestCx, remove_and_create_dir_all}; impl TestCx<'_> { pub(super) fn run_rustdoc_test(&self) { - assert!(self.revision.is_none(), "revisions not relevant here"); + assert!(self.revision.is_none(), "revisions not supported in this test suite"); let out_dir = self.output_base_dir(); remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| { diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs index 9f88faca89268..4f35efedfde49 100644 --- a/src/tools/compiletest/src/runtest/rustdoc_json.rs +++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs @@ -6,7 +6,7 @@ impl TestCx<'_> { pub(super) fn run_rustdoc_json_test(&self) { //FIXME: Add bless option. - assert!(self.revision.is_none(), "revisions not relevant here"); + assert!(self.revision.is_none(), "revisions not supported in this test suite"); let out_dir = self.output_base_dir(); remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| { diff --git a/src/tools/jsondocck/src/directive.rs b/src/tools/jsondocck/src/directive.rs index fdb2fa6dbbe01..c52c16866608d 100644 --- a/src/tools/jsondocck/src/directive.rs +++ b/src/tools/jsondocck/src/directive.rs @@ -105,13 +105,10 @@ impl DirectiveKind { [_path, value] => Self::HasNotValue { value: value.clone() }, _ => panic!("`//@ !has` must have 2 or 3 arguments, but got {args:?}"), }, - // Ignore compiletest directives, like //@ edition - (_, false) if KNOWN_DIRECTIVE_NAMES.contains(&directive_name) => { - return None; - } - _ => { - panic!("Invalid directive `//@ {}{directive_name}`", if negated { "!" } else { "" }) - } + // Ignore unknown directives as they might be compiletest directives + // since they share the same `//@` prefix by convention. In any case, + // compiletest rejects unknown directives for us. + _ => return None, }; Some((kind, &args[0])) @@ -216,10 +213,6 @@ fn get_one<'a>(matches: &[&'a Value]) -> Result<&'a Value, String> { } } -// FIXME: This setup is temporary until we figure out how to improve this situation. -// See . -include!(concat!(env!("CARGO_MANIFEST_DIR"), "/../compiletest/src/directive-list.rs")); - fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> { if s.starts_with("$") { Cow::Borrowed(&cache.variables.get(&s[1..]).unwrap_or_else(|| { diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index d84be4d3a3a6f..c3487565c23ed 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -47,8 +47,8 @@ static LINE_PATTERN: LazyLock = LazyLock::new(|| { ^\s* //@\s+ (?P!?) - (?P[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*) - (?P.*)$ + (?P.+?) + (?:[\s:](?P.*))?$ "#, ) .ignore_whitespace(true) @@ -58,15 +58,7 @@ static LINE_PATTERN: LazyLock = LazyLock::new(|| { }); static DEPRECATED_LINE_PATTERN: LazyLock = LazyLock::new(|| { - RegexBuilder::new( - r#" - //\s+@ - "#, - ) - .ignore_whitespace(true) - .unicode(true) - .build() - .unwrap() + RegexBuilder::new(r"//\s+@").ignore_whitespace(true).unicode(true).build().unwrap() }); fn print_err(msg: &str, lineno: usize) { @@ -94,7 +86,7 @@ fn get_directives(template: &str) -> Result, ()> { let negated = &cap["negated"] == "!"; - let args_str = &cap["args"]; + let args_str = cap.name("args").map(|m| m.as_str()).unwrap_or_default(); let Some(args) = shlex::split(args_str) else { print_err(&format!("Invalid arguments to shlex::split: `{args_str}`",), lineno); errors = true; diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs index bda08423487b5..b9741431b5034 100644 --- a/src/tools/remote-test-client/src/main.rs +++ b/src/tools/remote-test-client/src/main.rs @@ -335,7 +335,9 @@ fn run(support_lib_count: usize, exe: String, all_args: Vec) { std::process::exit(code); } else { println!("died due to signal {}", code); - std::process::exit(3); + // Behave like bash and other tools and exit with 128 + the signal + // number. That way we can avoid special case code in other places. + std::process::exit(128 + code); } } diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 4835c22021042..d995106ae0257 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tidy" version = "0.1.0" -edition = "2021" +edition = "2024" autobins = false [dependencies] diff --git a/src/tools/tidy/src/alphabetical.rs b/src/tools/tidy/src/alphabetical.rs index 141083290c6c8..9ddce72510693 100644 --- a/src/tools/tidy/src/alphabetical.rs +++ b/src/tools/tidy/src/alphabetical.rs @@ -103,7 +103,7 @@ fn check_section<'a>( let prev_line_trimmed_lowercase = prev_line.trim_start_matches(' '); - if version_sort(&trimmed_line, &prev_line_trimmed_lowercase).is_lt() { + if version_sort(trimmed_line, prev_line_trimmed_lowercase).is_lt() { tidy_error_ext!(err, bad, "{file}:{}: line not in alphabetical order", idx + 1); } diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 9b78ba75a0553..a18f549844b86 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -75,7 +75,7 @@ mod os_impl { return ReadOnlyFs; } - panic!("unable to create temporary file `{:?}`: {:?}", path, e); + panic!("unable to create temporary file `{path:?}`: {e:?}"); } } } @@ -83,12 +83,7 @@ mod os_impl { for &source_dir in sources { match check_dir(source_dir) { Unsupported => return false, - ReadOnlyFs => { - return match check_dir(output) { - Supported => true, - _ => false, - }; - } + ReadOnlyFs => return matches!(check_dir(output), Supported), _ => {} } } @@ -139,7 +134,7 @@ mod os_impl { return; } - if t!(is_executable(&file), file) { + if t!(is_executable(file), file) { let rel_path = file.strip_prefix(path).unwrap(); let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/"); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index bf813d2131e87..f43f5eae9a560 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -624,7 +624,7 @@ fn check_proc_macro_dep_list(root: &Path, cargo: &Path, bless: bool, bad: &mut b let is_proc_macro_pkg = |pkg: &Package| pkg.targets.iter().any(|target| target.is_proc_macro()); let mut proc_macro_deps = HashSet::new(); - for pkg in metadata.packages.iter().filter(|pkg| is_proc_macro_pkg(*pkg)) { + for pkg in metadata.packages.iter().filter(|pkg| is_proc_macro_pkg(pkg)) { deps_of(&metadata, &pkg.id, &mut proc_macro_deps); } // Remove the proc-macro crates themselves diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index bb61412f67882..65aa89fe80169 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -119,8 +119,7 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec) -> Vec) -> Vec) -> Vec, pos_args: &[String], ) -> Result<(), Error> { - let show_diff = std::env::var("TIDY_PRINT_DIFF") - .map_or(false, |v| v.eq_ignore_ascii_case("true") || v == "1"); + let show_diff = + std::env::var("TIDY_PRINT_DIFF").is_ok_and(|v| v.eq_ignore_ascii_case("true") || v == "1"); // Split comma-separated args up let lint_args = match extra_checks { @@ -141,7 +141,7 @@ fn check_impl( ); } // Rethrow error - let _ = res?; + res?; } if python_fmt { @@ -173,7 +173,7 @@ fn check_impl( } // Rethrow error - let _ = res?; + res?; } if cpp_fmt { @@ -244,7 +244,7 @@ fn check_impl( } } // Rethrow error - let _ = res?; + res?; } if shell_lint { @@ -286,8 +286,8 @@ fn run_ruff( file_args: &[&OsStr], ruff_args: &[&OsStr], ) -> Result<(), Error> { - let mut cfg_args_ruff = cfg_args.into_iter().copied().collect::>(); - let mut file_args_ruff = file_args.into_iter().copied().collect::>(); + let mut cfg_args_ruff = cfg_args.to_vec(); + let mut file_args_ruff = file_args.to_vec(); let mut cfg_path = root_path.to_owned(); cfg_path.extend(RUFF_CONFIG_PATH); @@ -305,7 +305,7 @@ fn run_ruff( file_args_ruff.push(root_path.as_os_str()); } - let mut args: Vec<&OsStr> = ruff_args.into_iter().copied().collect(); + let mut args: Vec<&OsStr> = ruff_args.to_vec(); args.extend(merge_args(&cfg_args_ruff, &file_args_ruff)); py_runner(py_path, true, None, "ruff", &args) } diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index 55f937aeacf50..bc217a55cc199 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -41,7 +41,7 @@ pub fn check(root: &Path, bad: &mut bool) { let source = line.split_once('=').unwrap().1.trim(); // Ensure source is allowed. - if !ALLOWED_SOURCES.contains(&&*source) { + if !ALLOWED_SOURCES.contains(&source) { tidy_error!(bad, "invalid source: {}", source); } } diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 6093e7fd2632f..e83b47e138064 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -125,8 +125,8 @@ pub fn check( let gate_test_str = "gate-test-"; let feature_name = match line.find(gate_test_str) { - // NB: the `splitn` always succeeds, even if the delimiter is not present. - Some(i) => line[i + gate_test_str.len()..].splitn(2, ' ').next().unwrap(), + // `split` always contains at least 1 element, even if the delimiter is not present. + Some(i) => line[i + gate_test_str.len()..].split(' ').next().unwrap(), None => continue, }; match features.get_mut(feature_name) { @@ -135,16 +135,14 @@ pub fn check( err(&format!( "The file is already marked as gate test \ through its name, no need for a \ - 'gate-test-{}' comment", - feature_name + 'gate-test-{feature_name}' comment" )); } f.has_gate_test = true; } None => { err(&format!( - "gate-test test found referencing a nonexistent feature '{}'", - feature_name + "gate-test test found referencing a nonexistent feature '{feature_name}'" )); } } @@ -170,8 +168,7 @@ pub fn check( ); println!( "Hint: If you already have such a test and don't want to rename it,\ - \n you can also add a // gate-test-{} line to the test file.", - name + \n you can also add a // gate-test-{name} line to the test file." ); } @@ -231,7 +228,7 @@ pub fn check( fn get_version_and_channel(src_path: &Path) -> (Version, String) { let version_str = t!(std::fs::read_to_string(src_path.join("version"))); let version_str = version_str.trim(); - let version = t!(std::str::FromStr::from_str(&version_str).map_err(|e| format!("{e:?}"))); + let version = t!(std::str::FromStr::from_str(version_str).map_err(|e| format!("{e:?}"))); let channel_str = t!(std::fs::read_to_string(src_path.join("ci").join("channel"))); (version, channel_str.trim().to_owned()) } @@ -468,7 +465,7 @@ fn get_and_check_lib_features( map_lib_features(base_src_path, &mut |res, file, line| match res { Ok((name, f)) => { let mut check_features = |f: &Feature, list: &Features, display: &str| { - if let Some(ref s) = list.get(name) { + if let Some(s) = list.get(name) { if f.tracking_issue != s.tracking_issue && f.level != Status::Accepted { tidy_error!( bad, @@ -483,7 +480,7 @@ fn get_and_check_lib_features( } } }; - check_features(&f, &lang_features, "corresponding lang feature"); + check_features(&f, lang_features, "corresponding lang feature"); check_features(&f, &lib_features, "previous"); lib_features.insert(name.to_owned(), f); } @@ -543,7 +540,7 @@ fn map_lib_features( continue; } - if let Some((ref name, ref mut f)) = becoming_feature { + if let Some((name, ref mut f)) = becoming_feature { if f.tracking_issue.is_none() { f.tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none); } diff --git a/src/tools/tidy/src/features/version.rs b/src/tools/tidy/src/features/version.rs index 6a902e80f8e70..0e0629a48e218 100644 --- a/src/tools/tidy/src/features/version.rs +++ b/src/tools/tidy/src/features/version.rs @@ -20,7 +20,7 @@ impl fmt::Display for Version { Version::Explicit { parts } => { f.pad(&format!("{}.{}.{}", parts[0], parts[1], parts[2])) } - Version::CurrentPlaceholder => f.pad(&format!("CURRENT")), + Version::CurrentPlaceholder => f.pad("CURRENT"), } } } diff --git a/src/tools/tidy/src/features/version/tests.rs b/src/tools/tidy/src/features/version/tests.rs index 7701dce2df173..453ba40586e73 100644 --- a/src/tools/tidy/src/features/version/tests.rs +++ b/src/tools/tidy/src/features/version/tests.rs @@ -33,6 +33,6 @@ fn test_to_string() { assert_eq!(v_1_0_0.to_string(), "1.0.0"); assert_eq!(v_1_32_1.to_string(), "1.32.1"); - assert_eq!(format!("{:<8}", v_1_32_1), "1.32.1 "); - assert_eq!(format!("{:>8}", v_1_32_1), " 1.32.1"); + assert_eq!(format!("{v_1_32_1:<8}"), "1.32.1 "); + assert_eq!(format!("{v_1_32_1:>8}"), " 1.32.1"); } diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs index 6f154b92eff15..48d14a37514bd 100644 --- a/src/tools/tidy/src/fluent_alphabetical.rs +++ b/src/tools/tidy/src/fluent_alphabetical.rs @@ -13,8 +13,8 @@ fn message() -> &'static Regex { static_regex!(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#) } -fn filter_fluent(path: &Path) -> bool { - if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true } +fn is_fluent(path: &Path) -> bool { + path.extension().is_some_and(|ext| ext == "flt") } fn check_alphabetic( @@ -92,7 +92,7 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) { let mut all_defined_msgs = HashMap::new(); walk( path, - |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)), + |path, is_dir| filter_dirs(path) || (!is_dir && !is_fluent(path)), &mut |ent, contents| { if bless { let sorted = sort_messages( @@ -104,7 +104,7 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) { if sorted != contents { let mut f = OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap(); - f.write(sorted.as_bytes()).unwrap(); + f.write_all(sorted.as_bytes()).unwrap(); } } else { check_alphabetic( diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs index 6a136e5aec698..85c1ef6166a4b 100644 --- a/src/tools/tidy/src/fluent_period.rs +++ b/src/tools/tidy/src/fluent_period.rs @@ -37,7 +37,7 @@ fn check_period(filename: &str, contents: &str, bad: &mut bool) { if let Some(PatternElement::TextElement { value }) = pat.elements.last() { // We don't care about ellipses. if value.ends_with(".") && !value.ends_with("...") { - let ll = find_line(contents, *value); + let ll = find_line(contents, value); let name = m.id.name; tidy_error!(bad, "{filename}:{ll}: message `{name}` ends in a period"); } @@ -52,7 +52,7 @@ fn check_period(filename: &str, contents: &str, bad: &mut bool) { if let Some(PatternElement::TextElement { value }) = attr.value.elements.last() { if value.ends_with(".") && !value.ends_with("...") { - let ll = find_line(contents, *value); + let ll = find_line(contents, value); let name = attr.id.name; tidy_error!(bad, "{filename}:{ll}: attr `{name}` ends in a period"); } diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs index ab56b5f0b0ec3..12fafd9a7ffc2 100644 --- a/src/tools/tidy/src/fluent_used.rs +++ b/src/tools/tidy/src/fluent_used.rs @@ -13,8 +13,8 @@ fn filter_used_messages( // we don't just check messages never appear in Rust files, // because messages can be used as parts of other fluent messages in Fluent files, // so we do checking messages appear only once in all Rust and Fluent files. - let mut matches = static_regex!(r"\w+").find_iter(contents); - while let Some(name) = matches.next() { + let matches = static_regex!(r"\w+").find_iter(contents); + for name in matches { if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) { // if one msg appears for the first time, // remove it from `msgs_not_appeared_yet` and insert it into `msgs_appeared_only_once`. diff --git a/src/tools/tidy/src/gcc_submodule.rs b/src/tools/tidy/src/gcc_submodule.rs index 952ebe9e0cffe..5d726c3ea48ff 100644 --- a/src/tools/tidy/src/gcc_submodule.rs +++ b/src/tools/tidy/src/gcc_submodule.rs @@ -7,7 +7,9 @@ use std::process::Command; pub fn check(root_path: &Path, compiler_path: &Path, bad: &mut bool) { let cg_gcc_version_path = compiler_path.join("rustc_codegen_gcc/libgccjit.version"); let cg_gcc_version = std::fs::read_to_string(&cg_gcc_version_path) - .expect(&format!("Cannot read GCC version from {}", cg_gcc_version_path.display())) + .unwrap_or_else(|_| { + panic!("Cannot read GCC version from {}", cg_gcc_version_path.display()) + }) .trim() .to_string(); @@ -27,14 +29,13 @@ pub fn check(root_path: &Path, compiler_path: &Path, bad: &mut bool) { // e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc (master-e607be166673a8de9fc07f6f02c60426e556c5f2.e607be) // +e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc (master-e607be166673a8de9fc07f6f02c60426e556c5f2.e607be) let git_output = String::from_utf8_lossy(&git_output.stdout) - .trim() .split_whitespace() .next() .unwrap_or_default() .to_string(); // The SHA can start with + if the submodule is modified or - if it is not checked out. - let gcc_submodule_sha = git_output.trim_start_matches(&['+', '-']); + let gcc_submodule_sha = git_output.trim_start_matches(['+', '-']); if gcc_submodule_sha != cg_gcc_version { *bad = true; eprintln!( diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 1eb5485f2b869..a67f7a511b598 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -15,11 +15,12 @@ use std::{env, process}; use tidy::*; fn main() { - // Running Cargo will read the libstd Cargo.toml + // Enable nightly, because Cargo will read the libstd Cargo.toml // which uses the unstable `public-dependency` feature. - // - // `setenv` might not be thread safe, so run it before using multiple threads. - env::set_var("RUSTC_BOOTSTRAP", "1"); + // SAFETY: no other threads have been spawned + unsafe { + env::set_var("RUSTC_BOOTSTRAP", "1"); + } let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into(); let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into(); diff --git a/src/tools/tidy/src/mir_opt_tests.rs b/src/tools/tidy/src/mir_opt_tests.rs index bb0d8150be4e1..1efe71b1687e3 100644 --- a/src/tools/tidy/src/mir_opt_tests.rs +++ b/src/tools/tidy/src/mir_opt_tests.rs @@ -49,7 +49,7 @@ fn check_unused_files(path: &Path, bless: bool, bad: &mut bool) { } fn check_dash_files(path: &Path, bless: bool, bad: &mut bool) { - for file in walkdir::WalkDir::new(&path.join("mir-opt")) + for file in walkdir::WalkDir::new(path.join("mir-opt")) .into_iter() .filter_map(Result::ok) .filter(|e| e.file_type().is_file()) diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 9b915e0f737dc..b7d4a331891a8 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -86,7 +86,7 @@ pub fn check(path: &Path, bad: &mut bool) { return; } - check_cfgs(contents, &file, bad, &mut saw_target_arch, &mut saw_cfg_bang); + check_cfgs(contents, file, bad, &mut saw_target_arch, &mut saw_cfg_bang); }); assert!(saw_target_arch); diff --git a/src/tools/tidy/src/rustdoc_gui_tests.rs b/src/tools/tidy/src/rustdoc_gui_tests.rs index 91776bc989e1d..3b995f219d269 100644 --- a/src/tools/tidy/src/rustdoc_gui_tests.rs +++ b/src/tools/tidy/src/rustdoc_gui_tests.rs @@ -5,7 +5,7 @@ use std::path::Path; pub fn check(path: &Path, bad: &mut bool) { crate::walk::walk( &path.join("rustdoc-gui"), - |p, is_dir| !is_dir && p.extension().map_or(true, |e| e != "goml"), + |p, is_dir| !is_dir && p.extension().is_none_or(|e| e != "goml"), &mut |entry, content| { for line in content.lines() { if !line.starts_with("// ") { diff --git a/src/tools/tidy/src/rustdoc_js.rs b/src/tools/tidy/src/rustdoc_js.rs index 5e924544f0dc7..5737fcbafc02d 100644 --- a/src/tools/tidy/src/rustdoc_js.rs +++ b/src/tools/tidy/src/rustdoc_js.rs @@ -88,7 +88,7 @@ pub fn check(librustdoc_path: &Path, tools_path: &Path, src_path: &Path, bad: &m let mut files_to_check = Vec::new(); walk_no_read( &[&librustdoc_path.join("html/static/js")], - |path, is_dir| is_dir || !path.extension().is_some_and(|ext| ext == OsStr::new("js")), + |path, is_dir| is_dir || path.extension().is_none_or(|ext| ext != OsStr::new("js")), &mut |path: &DirEntry| { files_to_check.push(path.path().into()); }, diff --git a/src/tools/tidy/src/rustdoc_json.rs b/src/tools/tidy/src/rustdoc_json.rs index 19b8e79ec33a3..722e1ebd0cad2 100644 --- a/src/tools/tidy/src/rustdoc_json.rs +++ b/src/tools/tidy/src/rustdoc_json.rs @@ -20,7 +20,7 @@ pub fn check(src_path: &Path, ci_info: &crate::CiInfo, bad: &mut bool) { return; } // Then we check that if `FORMAT_VERSION` was updated, the `Latest feature:` was also updated. - match crate::git_diff(&base_commit, src_path.join("rustdoc-json-types")) { + match crate::git_diff(base_commit, src_path.join("rustdoc-json-types")) { Some(output) => { let mut format_version_updated = false; let mut latest_feature_comment_updated = false; diff --git a/src/tools/tidy/src/rustdoc_templates.rs b/src/tools/tidy/src/rustdoc_templates.rs index 2173dbf7e746a..dca3e8d9d25f8 100644 --- a/src/tools/tidy/src/rustdoc_templates.rs +++ b/src/tools/tidy/src/rustdoc_templates.rs @@ -14,7 +14,7 @@ const TAGS: &[(&str, &str)] = &[("{#", "#}"), ("{%", "%}"), ("{{", "}}")]; pub fn check(librustdoc_path: &Path, bad: &mut bool) { walk( &librustdoc_path.join("html/templates"), - |path, is_dir| is_dir || !path.extension().is_some_and(|ext| ext == OsStr::new("html")), + |path, is_dir| is_dir || path.extension().is_none_or(|ext| ext != OsStr::new("html")), &mut |path: &DirEntry, file_content: &str| { let mut lines = file_content.lines().enumerate().peekable(); @@ -23,7 +23,7 @@ pub fn check(librustdoc_path: &Path, bad: &mut bool) { if let Some(need_next_line_check) = TAGS.iter().find_map(|(tag, end_tag)| { // We first check if the line ends with a jinja tag. if !line.ends_with(end_tag) { - return None; + None // Then we check if this a comment tag. } else if *tag != "{#" { return Some(false); diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 2237eac200d80..8dde4618ce528 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -94,10 +94,9 @@ fn generate_problems<'a>( letter_digit: &'a FxHashMap, ) -> impl Iterator + 'a { consts.iter().flat_map(move |const_value| { - let problem = - letter_digit.iter().fold(format!("{:X}", const_value), |acc, (key, value)| { - acc.replace(&value.to_string(), &key.to_string()) - }); + let problem = letter_digit.iter().fold(format!("{const_value:X}"), |acc, (key, value)| { + acc.replace(&value.to_string(), &key.to_string()) + }); let indexes: Vec = problem .chars() .enumerate() @@ -341,7 +340,7 @@ fn is_unexplained_ignore(extension: &str, line: &str) -> bool { pub fn check(path: &Path, bad: &mut bool) { fn skip(path: &Path, is_dir: bool) -> bool { - if path.file_name().map_or(false, |name| name.to_string_lossy().starts_with(".#")) { + if path.file_name().is_some_and(|name| name.to_string_lossy().starts_with(".#")) { // vim or emacs temporary file return true; } @@ -358,12 +357,12 @@ pub fn check(path: &Path, bad: &mut bool) { let extensions = ["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "goml"]; // NB: don't skip paths without extensions (or else we'll skip all directories and will only check top level files) - if path.extension().map_or(true, |ext| !extensions.iter().any(|e| ext == OsStr::new(e))) { + if path.extension().is_none_or(|ext| !extensions.iter().any(|e| ext == OsStr::new(e))) { return true; } // We only check CSS files in rustdoc. - path.extension().map_or(false, |e| e == "css") && !is_in(path, "src", "librustdoc") + path.extension().is_some_and(|e| e == "css") && !is_in(path, "src", "librustdoc") } // This creates a RegexSet as regex contains performance optimizations to be able to deal with these over @@ -435,7 +434,7 @@ pub fn check(path: &Path, bad: &mut bool) { mut skip_copyright, mut skip_dbg, mut skip_odd_backticks, - ] = contains_ignore_directives(&path_str, can_contain, &contents, CONFIGURABLE_CHECKS); + ] = contains_ignore_directives(&path_str, can_contain, contents, CONFIGURABLE_CHECKS); let mut leading_new_lines = false; let mut trailing_new_lines = 0; let mut lines = 0; diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs index a66ccd37070ad..1a6fd3eaf2dde 100644 --- a/src/tools/tidy/src/target_specific_tests.rs +++ b/src/tools/tidy/src/target_specific_tests.rs @@ -30,10 +30,9 @@ pub fn check(tests_path: &Path, bad: &mut bool) { comp_vec.push(component); } } - } else if directive.starts_with(COMPILE_FLAGS_HEADER) { - let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..]; + } else if let Some(compile_flags) = directive.strip_prefix(COMPILE_FLAGS_HEADER) { if let Some((_, v)) = compile_flags.split_once("--target") { - let v = v.trim_start_matches(|c| c == ' ' || c == '='); + let v = v.trim_start_matches([' ', '=']); let v = if v == "{{target}}" { Some((v, v)) } else { v.split_once("-") }; if let Some((arch, _)) = v { let info = header_map.entry(revision).or_insert(RevisionInfo::default()); @@ -57,15 +56,13 @@ pub fn check(tests_path: &Path, bad: &mut bool) { (None, None) => {} (Some(_), None) => { eprintln!( - "{}: revision {} should specify `{}` as it has `--target` set", - file, rev, LLVM_COMPONENTS_HEADER + "{file}: revision {rev} should specify `{LLVM_COMPONENTS_HEADER}` as it has `--target` set" ); *bad = true; } (None, Some(_)) => { eprintln!( - "{}: revision {} should not specify `{}` as it doesn't need `--target`", - file, rev, LLVM_COMPONENTS_HEADER + "{file}: revision {rev} should not specify `{LLVM_COMPONENTS_HEADER}` as it doesn't need `--target`" ); *bad = true; } diff --git a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs index ee92d302db3c9..02412b6f190e8 100644 --- a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs +++ b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs @@ -38,7 +38,7 @@ pub fn check(tests_path: impl AsRef, bad: &mut bool) { let sibling_path = sibling.path(); - let Some(ext) = sibling_path.extension().map(OsStr::to_str).flatten() else { + let Some(ext) = sibling_path.extension().and_then(OsStr::to_str) else { continue; }; @@ -84,7 +84,7 @@ pub fn check(tests_path: impl AsRef, bad: &mut bool) { } }); - let Some(test_name) = test.file_stem().map(OsStr::to_str).flatten() else { + let Some(test_name) = test.file_stem().and_then(OsStr::to_str) else { continue; }; @@ -102,9 +102,9 @@ pub fn check(tests_path: impl AsRef, bad: &mut bool) { // of the form: `test-name.revision.compare_mode.extension`, but our only concern is // `test-name.revision` and `extension`. for sibling in files_under_inspection.iter().filter(|f| { - f.extension().map(OsStr::to_str).flatten().is_some_and(|ext| EXTENSIONS.contains(&ext)) + f.extension().and_then(OsStr::to_str).is_some_and(|ext| EXTENSIONS.contains(&ext)) }) { - let Some(filename) = sibling.file_name().map(OsStr::to_str).flatten() else { + let Some(filename) = sibling.file_name().and_then(OsStr::to_str) else { continue; }; @@ -131,10 +131,10 @@ pub fn check(tests_path: impl AsRef, bad: &mut bool) { } [_, _] => return, [_, found_revision, .., extension] => { - if !IGNORES.contains(&found_revision) + if !IGNORES.contains(found_revision) && !expected_revisions.contains(*found_revision) // This is from `//@ stderr-per-bitwidth` - && !(*extension == "stderr" && ["32bit", "64bit"].contains(&found_revision)) + && !(*extension == "stderr" && ["32bit", "64bit"].contains(found_revision)) { // Found some unexpected revision-esque component that is not a known // compare-mode or expected revision. diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 53226fcb80e6a..b1ace74e5bd28 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -57,11 +57,9 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ fn check_entries(tests_path: &Path, bad: &mut bool) { let mut directories: HashMap = HashMap::new(); - for dir in Walk::new(&tests_path.join("ui")) { - if let Ok(entry) = dir { - let parent = entry.path().parent().unwrap().to_path_buf(); - *directories.entry(parent).or_default() += 1; - } + for entry in Walk::new(tests_path.join("ui")).flatten() { + let parent = entry.path().parent().unwrap().to_path_buf(); + *directories.entry(parent).or_default() += 1; } let (mut max, mut max_issues) = (0, 0); @@ -99,7 +97,7 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) { "#; let path = &root_path.join("tests"); - check_entries(&path, bad); + check_entries(path, bad); // the list of files in ui tests that are allowed to start with `issue-XXXX` // BTreeSet because we would like a stable ordering so --bless works @@ -109,13 +107,12 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) { .strip_prefix(issues_txt_header) .unwrap() .lines() - .map(|line| { + .inspect(|&line| { if prev_line > line { is_sorted = false; } prev_line = line; - line }) .collect(); @@ -203,7 +200,7 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) { // so we don't bork things on panic or a contributor using Ctrl+C let blessed_issues_path = tidy_src.join("issues_blessed.txt"); let mut blessed_issues_txt = fs::File::create(&blessed_issues_path).unwrap(); - blessed_issues_txt.write(issues_txt_header.as_bytes()).unwrap(); + blessed_issues_txt.write_all(issues_txt_header.as_bytes()).unwrap(); // If we changed paths to use the OS separator, reassert Unix chauvinism for blessing. for filename in allowed_issue_names.difference(&remaining_issue_names) { writeln!(blessed_issues_txt, "{filename}").unwrap(); diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index a2453a6c96057..9dc9d42d46600 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -38,7 +38,7 @@ fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool { pub fn collect_unstable_feature_names(features: &Features) -> BTreeSet { features .iter() - .filter(|&(_, ref f)| f.level == Status::Unstable) + .filter(|&(_, f)| f.level == Status::Unstable) .map(|(name, _)| name.replace('_', "-")) .collect() } @@ -90,7 +90,7 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { let lib_features = features .lib .into_iter() - .filter(|&(ref name, _)| !lang_features.contains_key(name)) + .filter(|(name, _)| !lang_features.contains_key(name)) .collect::(); // Library features diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index c2c9eb8d2507e..7825ebeb5baa6 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -66,7 +66,7 @@ pub fn walk_many( Ok(s) => s, Err(_) => return, // skip this file }; - f(&entry, &contents_str); + f(entry, contents_str); }); } @@ -83,7 +83,7 @@ pub(crate) fn walk_no_read( !skip(e.path(), e.file_type().map(|ft| ft.is_dir()).unwrap_or(false)) }); for entry in walker.build().flatten() { - if entry.file_type().map_or(true, |kind| kind.is_dir() || kind.is_symlink()) { + if entry.file_type().is_none_or(|kind| kind.is_dir() || kind.is_symlink()) { continue; } f(&entry); diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 489343561e180..6a5e9eca81328 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -26,7 +26,7 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { // Check this is the rust-lang/rust x tool installation since it should be // installed at a path containing `src/tools/x`. if let Some(path) = iter.next() { - if path.contains(&"src/tools/x") { + if path.contains("src/tools/x") { let version = version.strip_prefix("v").unwrap(); installed = Some(Version::parse(version).unwrap()); break; @@ -42,15 +42,15 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { if let Some(expected) = get_x_wrapper_version(root, cargo) { if installed < expected { - return println!( + println!( "Current version of x is {installed}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" - ); + ) } } else { - return tidy_error!( + tidy_error!( bad, "Unable to parse the latest version of `x` at `src/tools/x/Cargo.toml`" - ); + ) } } else { tidy_error!(bad, "failed to check version of `x`: {}", cargo_list.status) diff --git a/tests/codegen/fn-parameters-on-different-lines-debuginfo.rs b/tests/codegen/fn-parameters-on-different-lines-debuginfo.rs new file mode 100644 index 0000000000000..7779df1762619 --- /dev/null +++ b/tests/codegen/fn-parameters-on-different-lines-debuginfo.rs @@ -0,0 +1,18 @@ +//! Make sure that line debuginfo of function parameters are correct even if +//! they are not on the same line. Regression test for +// . + +//@ compile-flags: -g -Copt-level=0 + +#![crate_type = "dylib"] +#[rustfmt::skip] // Having parameters on different lines is crucial for this test. +pub fn foo( + x: i32, + y: i32) + -> i32 +{ x + y } + +// CHECK: !DILocalVariable(name: "x", arg: 1, +// CHECK-SAME: line: 10 +// CHECK: !DILocalVariable(name: "y", arg: 2, +// CHECK-SAME: line: 11 diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index f16ba706485da..4837b2dce9608 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -116,12 +116,6 @@ error: malformed `cfi_encoding` attribute input LL | #[cfi_encoding] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` -error: malformed `link_ordinal` attribute input - --> $DIR/malformed-attrs.rs:167:5 - | -LL | #[link_ordinal] - | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_ordinal(ordinal)]` - error: malformed `linkage` attribute input --> $DIR/malformed-attrs.rs:173:5 | @@ -537,6 +531,15 @@ LL | #[unsafe(ffi_pure = 1)] | | didn't expect any arguments here | help: must be of the form: `#[ffi_pure]` +error[E0539]: malformed `link_ordinal` attribute input + --> $DIR/malformed-attrs.rs:167:5 + | +LL | #[link_ordinal] + | ^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[link_ordinal(ordinal)]` + error[E0565]: malformed `ffi_const` attribute input --> $DIR/malformed-attrs.rs:171:5 | diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs index 9b7e8d70743b7..87b4999c5f9fd 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs @@ -1,10 +1,10 @@ #[link(name = "foo")] extern "C" { #[link_ordinal("JustMonika")] - //~^ ERROR illegal ordinal format in `link_ordinal` + //~^ ERROR malformed `link_ordinal` attribute input fn foo(); #[link_ordinal("JustMonika")] - //~^ ERROR illegal ordinal format in `link_ordinal` + //~^ ERROR malformed `link_ordinal` attribute input static mut imported_variable: i32; } diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr index 6341e57a0be53..ffae30aabcc3f 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr @@ -1,18 +1,21 @@ -error: illegal ordinal format in `link_ordinal` +error[E0539]: malformed `link_ordinal` attribute input --> $DIR/link-ordinal-invalid-format.rs:3:5 | LL | #[link_ordinal("JustMonika")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: an unsuffixed integer value, e.g., `1`, is expected + | ^^^^^^^^^^^^^^^------------^^ + | | | + | | expected an integer literal here + | help: must be of the form: `#[link_ordinal(ordinal)]` -error: illegal ordinal format in `link_ordinal` +error[E0539]: malformed `link_ordinal` attribute input --> $DIR/link-ordinal-invalid-format.rs:6:5 | LL | #[link_ordinal("JustMonika")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: an unsuffixed integer value, e.g., `1`, is expected + | ^^^^^^^^^^^^^^^------------^^ + | | | + | | expected an integer literal here + | help: must be of the form: `#[link_ordinal(ordinal)]` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs index 6b8cd49566dfe..2a8b9ebacf7f1 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs @@ -1,10 +1,12 @@ #[link(name = "foo")] extern "C" { #[link_ordinal()] - //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + //~^ ERROR malformed `link_ordinal` attribute input + //~| NOTE expected a single argument fn foo(); #[link_ordinal()] - //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + //~^ ERROR malformed `link_ordinal` attribute input + //~| NOTE expected a single argument static mut imported_variable: i32; } diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr index 1b04bb228e76a..c6b8a18d03a36 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr @@ -1,18 +1,21 @@ -error: incorrect number of arguments to `#[link_ordinal]` +error[E0805]: malformed `link_ordinal` attribute input --> $DIR/link-ordinal-missing-argument.rs:3:5 | LL | #[link_ordinal()] - | ^^^^^^^^^^^^^^^^^ - | - = note: the attribute requires exactly one argument + | ^^^^^^^^^^^^^^--^ + | | | + | | expected a single argument here + | help: must be of the form: `#[link_ordinal(ordinal)]` -error: incorrect number of arguments to `#[link_ordinal]` - --> $DIR/link-ordinal-missing-argument.rs:6:5 +error[E0805]: malformed `link_ordinal` attribute input + --> $DIR/link-ordinal-missing-argument.rs:7:5 | LL | #[link_ordinal()] - | ^^^^^^^^^^^^^^^^^ - | - = note: the attribute requires exactly one argument + | ^^^^^^^^^^^^^^--^ + | | | + | | expected a single argument here + | help: must be of the form: `#[link_ordinal(ordinal)]` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0805`. diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs index 9988115fd8b0d..ddf9583352fad 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs @@ -1,10 +1,12 @@ #[link(name = "foo")] extern "C" { #[link_ordinal(3, 4)] - //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + //~^ ERROR malformed `link_ordinal` attribute input + //~| NOTE expected a single argument fn foo(); #[link_ordinal(3, 4)] - //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + //~^ ERROR malformed `link_ordinal` attribute input + //~| NOTE expected a single argument static mut imported_variable: i32; } diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr index d5ce8aff34f20..7d63304f5982b 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr @@ -1,18 +1,21 @@ -error: incorrect number of arguments to `#[link_ordinal]` +error[E0805]: malformed `link_ordinal` attribute input --> $DIR/link-ordinal-too-many-arguments.rs:3:5 | LL | #[link_ordinal(3, 4)] - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: the attribute requires exactly one argument + | ^^^^^^^^^^^^^^------^ + | | | + | | expected a single argument here + | help: must be of the form: `#[link_ordinal(ordinal)]` -error: incorrect number of arguments to `#[link_ordinal]` - --> $DIR/link-ordinal-too-many-arguments.rs:6:5 +error[E0805]: malformed `link_ordinal` attribute input + --> $DIR/link-ordinal-too-many-arguments.rs:7:5 | LL | #[link_ordinal(3, 4)] - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: the attribute requires exactly one argument + | ^^^^^^^^^^^^^^------^ + | | | + | | expected a single argument here + | help: must be of the form: `#[link_ordinal(ordinal)]` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0805`.