From 09f774da8eccc725f54b38715c88cf7d52315361 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sun, 23 Nov 2025 01:56:15 -0500 Subject: [PATCH 01/47] Mark all arms as being from a desugaring when lowering `?` and for loops. --- compiler/rustc_ast_lowering/src/expr.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 524f8b054cb49..0ab3191f23be5 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -941,14 +941,14 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); this.arena.alloc(this.expr(gen_future_span, expr_break)) }); - self.arm(ready_pat, break_x) + self.arm(ready_pat, break_x, span) }; // `::std::task::Poll::Pending => {}` let pending_arm = { let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); let empty_block = self.expr_block_empty(span); - self.arm(pending_pat, empty_block) + self.arm(pending_pat, empty_block, span) }; let inner_match_stmt = { @@ -1002,7 +1002,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }); // mut __awaitee => loop { ... } - let awaitee_arm = self.arm(awaitee_pat, loop_expr); + let awaitee_arm = self.arm(awaitee_pat, loop_expr, span); // `match ::std::future::IntoFuture::into_future() { ... }` let into_future_expr = match await_kind { @@ -1788,7 +1788,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let break_expr = self.with_loop_scope(loop_hir_id, |this| this.expr_break_alloc(for_span)); let pat = self.pat_none(for_span); - self.arm(pat, break_expr) + self.arm(pat, break_expr, for_span) }; // Some() => , @@ -1797,7 +1797,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_block = self.with_loop_scope(loop_hir_id, |this| this.lower_block(body, false)); let body_expr = self.arena.alloc(self.expr_block(body_block)); - self.arm(some_pat, body_expr) + self.arm(some_pat, body_expr, for_span) }; // `mut iter` @@ -1856,7 +1856,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span }); // `mut iter => { ... }` - let iter_arm = self.arm(iter_pat, loop_expr); + let iter_arm = self.arm(iter_pat, loop_expr, for_span); let match_expr = match loop_kind { ForLoopKind::For => { @@ -1901,7 +1901,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::IntoAsyncIterIntoIter, arena_vec![self; head], ); - let iter_arm = self.arm(async_iter_pat, inner_match_expr); + let iter_arm = self.arm(async_iter_pat, inner_match_expr, for_span); self.arena.alloc(self.expr_match( for_span, iter, @@ -1968,7 +1968,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let val_expr = self.expr_ident(span, val_ident, val_pat_nid); self.lower_attrs(val_expr.hir_id, &attrs, span, Target::Expression); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); - self.arm(continue_pat, val_expr) + self.arm(continue_pat, val_expr, try_span) }; // `ControlFlow::Break(residual) => @@ -2004,7 +2004,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs(ret_expr.hir_id, &attrs, span, Target::Expression); let break_pat = self.pat_cf_break(try_span, residual_local); - self.arm(break_pat, ret_expr) + self.arm(break_pat, ret_expr, try_span) }; hir::ExprKind::Match( @@ -2329,12 +2329,13 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>, + span: Span, ) -> hir::Arm<'hir> { hir::Arm { hir_id: self.next_id(), pat, guard: None, - span: self.lower_span(expr.span), + span: self.lower_span(span), body: expr, } } From 2135bc1f1063073479b8b4c8e83fcb9a635f9ab0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Jan 2026 15:00:59 +1100 Subject: [PATCH 02/47] Remove `rustc_lexer::cursor` module. It contains the `Cursor` type and an `impl Cursor` block with a few methods. But there is a larger `impl Cursor` block in the crate root. The only other thing in the `cursor` module is the simple `FrontmatterAllowed` type. So this commit just moves everything in the `cursor` module (which isn't much) into the crate root. --- compiler/rustc_lexer/src/cursor.rs | 125 --------------------------- compiler/rustc_lexer/src/lib.rs | 130 +++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 130 deletions(-) delete mode 100644 compiler/rustc_lexer/src/cursor.rs diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs deleted file mode 100644 index 165262b82c75d..0000000000000 --- a/compiler/rustc_lexer/src/cursor.rs +++ /dev/null @@ -1,125 +0,0 @@ -use std::str::Chars; - -pub enum FrontmatterAllowed { - Yes, - No, -} - -/// Peekable iterator over a char sequence. -/// -/// Next characters can be peeked via `first` method, -/// and position can be shifted forward via `bump` method. -pub struct Cursor<'a> { - len_remaining: usize, - /// Iterator over chars. Slightly faster than a &str. - chars: Chars<'a>, - pub(crate) frontmatter_allowed: FrontmatterAllowed, - #[cfg(debug_assertions)] - prev: char, -} - -pub(crate) const EOF_CHAR: char = '\0'; - -impl<'a> Cursor<'a> { - pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { - Cursor { - len_remaining: input.len(), - chars: input.chars(), - frontmatter_allowed, - #[cfg(debug_assertions)] - prev: EOF_CHAR, - } - } - - pub fn as_str(&self) -> &'a str { - self.chars.as_str() - } - - /// Returns the last eaten symbol (or `'\0'` in release builds). - /// (For debug assertions only.) - pub(crate) fn prev(&self) -> char { - #[cfg(debug_assertions)] - { - self.prev - } - - #[cfg(not(debug_assertions))] - { - EOF_CHAR - } - } - - /// Peeks the next symbol from the input stream without consuming it. - /// If requested position doesn't exist, `EOF_CHAR` is returned. - /// However, getting `EOF_CHAR` doesn't always mean actual end of file, - /// it should be checked with `is_eof` method. - pub fn first(&self) -> char { - // `.next()` optimizes better than `.nth(0)` - self.chars.clone().next().unwrap_or(EOF_CHAR) - } - - /// Peeks the second symbol from the input stream without consuming it. - pub(crate) fn second(&self) -> char { - // `.next()` optimizes better than `.nth(1)` - let mut iter = self.chars.clone(); - iter.next(); - iter.next().unwrap_or(EOF_CHAR) - } - - /// Peeks the third symbol from the input stream without consuming it. - pub fn third(&self) -> char { - // `.next()` optimizes better than `.nth(2)` - let mut iter = self.chars.clone(); - iter.next(); - iter.next(); - iter.next().unwrap_or(EOF_CHAR) - } - - /// Checks if there is nothing more to consume. - pub(crate) fn is_eof(&self) -> bool { - self.chars.as_str().is_empty() - } - - /// Returns amount of already consumed symbols. - pub(crate) fn pos_within_token(&self) -> u32 { - (self.len_remaining - self.chars.as_str().len()) as u32 - } - - /// Resets the number of bytes consumed to 0. - pub(crate) fn reset_pos_within_token(&mut self) { - self.len_remaining = self.chars.as_str().len(); - } - - /// Moves to the next character. - pub(crate) fn bump(&mut self) -> Option { - let c = self.chars.next()?; - - #[cfg(debug_assertions)] - { - self.prev = c; - } - - Some(c) - } - - /// Moves to a substring by a number of bytes. - pub(crate) fn bump_bytes(&mut self, n: usize) { - self.chars = self.as_str()[n..].chars(); - } - - /// Eats symbols while predicate returns true or until the end of file is reached. - pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { - // It was tried making optimized version of this for eg. line comments, but - // LLVM can inline all of this and compile it down to fast iteration over bytes. - while predicate(self.first()) && !self.is_eof() { - self.bump(); - } - } - - pub(crate) fn eat_until(&mut self, byte: u8) { - self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) { - Some(index) => self.as_str()[index..].chars(), - None => "".chars(), - } - } -} diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 27ffcbc943bde..9d3da6ef49302 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -25,15 +25,13 @@ #![deny(unstable_features)] // tidy-alphabetical-end -mod cursor; - #[cfg(test)] mod tests; +use std::str::Chars; + use LiteralKind::*; use TokenKind::*; -use cursor::EOF_CHAR; -pub use cursor::{Cursor, FrontmatterAllowed}; pub use unicode_ident::UNICODE_VERSION; use unicode_properties::UnicodeEmoji; @@ -407,7 +405,129 @@ pub fn is_ident(string: &str) -> bool { } } -impl Cursor<'_> { +pub enum FrontmatterAllowed { + Yes, + No, +} + +/// Peekable iterator over a char sequence. +/// +/// Next characters can be peeked via `first` method, +/// and position can be shifted forward via `bump` method. +pub struct Cursor<'a> { + len_remaining: usize, + /// Iterator over chars. Slightly faster than a &str. + chars: Chars<'a>, + pub(crate) frontmatter_allowed: FrontmatterAllowed, + #[cfg(debug_assertions)] + prev: char, +} + +const EOF_CHAR: char = '\0'; + +impl<'a> Cursor<'a> { + pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { + Cursor { + len_remaining: input.len(), + chars: input.chars(), + frontmatter_allowed, + #[cfg(debug_assertions)] + prev: EOF_CHAR, + } + } + + pub fn as_str(&self) -> &'a str { + self.chars.as_str() + } + + /// Returns the last eaten symbol (or `'\0'` in release builds). + /// (For debug assertions only.) + pub(crate) fn prev(&self) -> char { + #[cfg(debug_assertions)] + { + self.prev + } + + #[cfg(not(debug_assertions))] + { + EOF_CHAR + } + } + + /// Peeks the next symbol from the input stream without consuming it. + /// If requested position doesn't exist, `EOF_CHAR` is returned. + /// However, getting `EOF_CHAR` doesn't always mean actual end of file, + /// it should be checked with `is_eof` method. + pub fn first(&self) -> char { + // `.next()` optimizes better than `.nth(0)` + self.chars.clone().next().unwrap_or(EOF_CHAR) + } + + /// Peeks the second symbol from the input stream without consuming it. + pub(crate) fn second(&self) -> char { + // `.next()` optimizes better than `.nth(1)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) + } + + /// Peeks the third symbol from the input stream without consuming it. + pub fn third(&self) -> char { + // `.next()` optimizes better than `.nth(2)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) + } + + /// Checks if there is nothing more to consume. + pub(crate) fn is_eof(&self) -> bool { + self.chars.as_str().is_empty() + } + + /// Returns amount of already consumed symbols. + pub(crate) fn pos_within_token(&self) -> u32 { + (self.len_remaining - self.chars.as_str().len()) as u32 + } + + /// Resets the number of bytes consumed to 0. + pub(crate) fn reset_pos_within_token(&mut self) { + self.len_remaining = self.chars.as_str().len(); + } + + /// Moves to the next character. + pub(crate) fn bump(&mut self) -> Option { + let c = self.chars.next()?; + + #[cfg(debug_assertions)] + { + self.prev = c; + } + + Some(c) + } + + /// Moves to a substring by a number of bytes. + pub(crate) fn bump_bytes(&mut self, n: usize) { + self.chars = self.as_str()[n..].chars(); + } + + /// Eats symbols while predicate returns true or until the end of file is reached. + pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { + // It was tried making optimized version of this for eg. line comments, but + // LLVM can inline all of this and compile it down to fast iteration over bytes. + while predicate(self.first()) && !self.is_eof() { + self.bump(); + } + } + + pub(crate) fn eat_until(&mut self, byte: u8) { + self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) { + Some(index) => self.as_str()[index..].chars(), + None => "".chars(), + } + } + /// Parses a token from the input string. pub fn advance_token(&mut self) -> Token { let Some(first_char) = self.bump() else { From 506ea790caa945aa6541f371f98df39c999e149c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Jan 2026 15:22:21 +1100 Subject: [PATCH 03/47] Move two `rustc_parse` error diagnostics. Every diagnostic struct in `rustc_parse` is in the `errors` module, except for `ForbiddenLetReason` and `MisspelledKw`. There's no good reason for this, and presumably it is just an accidental inconsistency. This commit moves them into `errors`. --- compiler/rustc_parse/src/errors.rs | 34 ++++++++++++++- .../rustc_parse/src/parser/diagnostics.rs | 24 ++--------- compiler/rustc_parse/src/parser/expr.rs | 41 ++++++------------- compiler/rustc_parse/src/parser/mod.rs | 1 - 4 files changed, 50 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 42327c7e343d1..92ec1377d0454 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -17,7 +17,7 @@ use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; -use crate::parser::{ForbiddenLetReason, TokenDescription}; +use crate::parser::TokenDescription; #[derive(Diagnostic)] #[diag(parse_maybe_report_ambiguous_plus)] @@ -3703,3 +3703,35 @@ pub(crate) struct StructLiteralWithoutPathLate { #[suggestion(applicability = "has-placeholders", code = "/* Type */ ", style = "verbose")] pub suggestion_span: Span, } + +/// Used to forbid `let` expressions in certain syntactic locations. +#[derive(Clone, Copy, Subdiagnostic)] +pub(crate) enum ForbiddenLetReason { + /// `let` is not valid and the source environment is not important + OtherForbidden, + /// A let chain with the `||` operator + #[note(parse_not_supported_or)] + NotSupportedOr(#[primary_span] Span), + /// A let chain with invalid parentheses + /// + /// For example, `let 1 = 1 && (expr && expr)` is allowed + /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not + #[note(parse_not_supported_parentheses)] + NotSupportedParentheses(#[primary_span] Span), +} + +#[derive(Debug, rustc_macros::Subdiagnostic)] +#[suggestion( + parse_misspelled_kw, + applicability = "machine-applicable", + code = "{similar_kw}", + style = "verbose" +)] +pub(crate) struct MisspelledKw { + // We use a String here because `Symbol::into_diag_arg` calls `Symbol::to_ident_string`, which + // prefix the keyword with a `r#` because it aims to print the symbol as an identifier. + pub similar_kw: String, + #[primary_span] + pub span: Span, + pub is_incorrect_case: bool, +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 60e12fa05adfd..cb8a291c7fa05 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -35,10 +35,10 @@ use crate::errors::{ ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, - PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, - StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, - SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, TernaryOperatorSuggestion, - UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, + MisspelledKw, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, + SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, + SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, + TernaryOperatorSuggestion, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::parser::FnContext; @@ -212,22 +212,6 @@ impl std::fmt::Display for UnaryFixity { } } -#[derive(Debug, rustc_macros::Subdiagnostic)] -#[suggestion( - parse_misspelled_kw, - applicability = "machine-applicable", - code = "{similar_kw}", - style = "verbose" -)] -struct MisspelledKw { - // We use a String here because `Symbol::into_diag_arg` calls `Symbol::to_ident_string`, which - // prefix the keyword with a `r#` because it aims to print the symbol as an identifier. - similar_kw: String, - #[primary_span] - span: Span, - is_incorrect_case: bool, -} - /// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`. /// /// This is a specialized version of [`Symbol::find_similar`] that constructs an error when a diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c31a4798b471e..8ba7493f6f115 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -21,7 +21,6 @@ use rustc_ast::{ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; use rustc_literal_escaper::unescape_char; -use rustc_macros::Subdiagnostic; use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; @@ -2770,7 +2769,7 @@ impl<'a> Parser<'a> { let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) { let err = errors::ExpectedExpressionFoundLet { span: self.token.span, - reason: ForbiddenLetReason::OtherForbidden, + reason: errors::ForbiddenLetReason::OtherForbidden, missing_let: None, comparison: None, }; @@ -4169,22 +4168,6 @@ pub(crate) fn could_be_unclosed_char_literal(ident: Ident) -> bool { && unescape_char(ident.without_first_quote().name.as_str()).is_ok() } -/// Used to forbid `let` expressions in certain syntactic locations. -#[derive(Clone, Copy, Subdiagnostic)] -pub(crate) enum ForbiddenLetReason { - /// `let` is not valid and the source environment is not important - OtherForbidden, - /// A let chain with the `||` operator - #[note(parse_not_supported_or)] - NotSupportedOr(#[primary_span] Span), - /// A let chain with invalid parentheses - /// - /// For example, `let 1 = 1 && (expr && expr)` is allowed - /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not - #[note(parse_not_supported_parentheses)] - NotSupportedParentheses(#[primary_span] Span), -} - /// Whether let chains are allowed on all editions, or it's edition dependent (allowed only on /// 2024 and later). In case of edition dependence, specify the currently present edition. pub enum LetChainsPolicy { @@ -4205,7 +4188,7 @@ struct CondChecker<'a> { parser: &'a Parser<'a>, let_chains_policy: LetChainsPolicy, depth: u32, - forbid_let_reason: Option, + forbid_let_reason: Option, missing_let: Option, comparison: Option, } @@ -4226,14 +4209,13 @@ impl<'a> CondChecker<'a> { impl MutVisitor for CondChecker<'_> { fn visit_expr(&mut self, e: &mut Expr) { self.depth += 1; - use ForbiddenLetReason::*; let span = e.span; match e.kind { ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => { if let Some(reason) = self.forbid_let_reason { let error = match reason { - NotSupportedOr(or_span) => { + errors::ForbiddenLetReason::NotSupportedOr(or_span) => { self.parser.dcx().emit_err(errors::OrInLetChain { span: or_span }) } _ => self.parser.dcx().emit_err(errors::ExpectedExpressionFoundLet { @@ -4260,24 +4242,27 @@ impl MutVisitor for CondChecker<'_> { mut_visit::walk_expr(self, e); } ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _) - if let None | Some(NotSupportedOr(_)) = self.forbid_let_reason => + if let None | Some(errors::ForbiddenLetReason::NotSupportedOr(_)) = + self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(NotSupportedOr(or_span)); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::NotSupportedOr(or_span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } ExprKind::Paren(ref inner) - if let None | Some(NotSupportedParentheses(_)) = self.forbid_let_reason => + if let None | Some(errors::ForbiddenLetReason::NotSupportedParentheses(_)) = + self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(NotSupportedParentheses(inner.span)); + self.forbid_let_reason = + Some(errors::ForbiddenLetReason::NotSupportedParentheses(inner.span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } ExprKind::Assign(ref lhs, _, span) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); let missing_let = self.missing_let; if let ExprKind::Binary(_, _, rhs) = &lhs.kind && let ExprKind::Path(_, _) @@ -4310,7 +4295,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Tup(_) | ExprKind::Paren(_) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } @@ -4318,7 +4303,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Type(ref mut op, _) | ExprKind::UnsafeBinderCast(_, ref mut op, _) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); self.visit_expr(op); self.forbid_let_reason = forbid_let_reason; } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3ef73a55d47d7..81aaac0004ecb 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -20,7 +20,6 @@ use std::{fmt, mem, slice}; use attr_wrapper::{AttrWrapper, UsePreAttrPos}; pub use diagnostics::AttemptLocalParseRecovery; -pub(crate) use expr::ForbiddenLetReason; // Public to use it for custom `if` expressions in rustfmt forks like https://github.com/tucant/rustfmt pub use expr::LetChainsPolicy; pub(crate) use item::{FnContext, FnParseMode}; From b33fdb2c7093fb414833936d830e2e1135cebf9b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Jan 2026 15:47:00 +1100 Subject: [PATCH 04/47] Move `TokenDescription`. From the `parser` module to the `errors` module, which is where most of its uses are. This means the `errors` module no longer depends on the `parser` module, removing a cyclic dependency between the two modules. --- compiler/rustc_parse/src/errors.rs | 32 ++++++++++++++++++++++++-- compiler/rustc_parse/src/parser/mod.rs | 31 +------------------------ 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 92ec1377d0454..7d0acc3337737 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use std::path::PathBuf; -use rustc_ast::token::Token; +use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, Token}; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; @@ -17,7 +17,6 @@ use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; -use crate::parser::TokenDescription; #[derive(Diagnostic)] #[diag(parse_maybe_report_ambiguous_plus)] @@ -3735,3 +3734,32 @@ pub(crate) struct MisspelledKw { pub span: Span, pub is_incorrect_case: bool, } + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(super) enum TokenDescription { + ReservedIdentifier, + Keyword, + ReservedKeyword, + DocComment, + + // Expanded metavariables are wrapped in invisible delimiters which aren't + // pretty-printed. In error messages we must handle these specially + // otherwise we get confusing things in messages like "expected `(`, found + // ``". It's better to say e.g. "expected `(`, found type metavariable". + MetaVar(MetaVarKind), +} + +impl TokenDescription { + pub(super) fn from_token(token: &Token) -> Option { + match token.kind { + _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), + _ if token.is_used_keyword() => Some(TokenDescription::Keyword), + _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), + token::DocComment(..) => Some(TokenDescription::DocComment), + token::OpenInvisible(InvisibleOrigin::MetaVar(kind)) => { + Some(TokenDescription::MetaVar(kind)) + } + _ => None, + } + } +} diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 81aaac0004ecb..0ff0b66229366 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -49,7 +49,7 @@ use token_type::TokenTypeSet; pub use token_type::{ExpKeywordPair, ExpTokenPair, TokenType}; use tracing::debug; -use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral}; +use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral, TokenDescription}; use crate::exp; #[cfg(test)] @@ -307,35 +307,6 @@ impl From for Trailing { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(super) enum TokenDescription { - ReservedIdentifier, - Keyword, - ReservedKeyword, - DocComment, - - // Expanded metavariables are wrapped in invisible delimiters which aren't - // pretty-printed. In error messages we must handle these specially - // otherwise we get confusing things in messages like "expected `(`, found - // ``". It's better to say e.g. "expected `(`, found type metavariable". - MetaVar(MetaVarKind), -} - -impl TokenDescription { - pub(super) fn from_token(token: &Token) -> Option { - match token.kind { - _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), - _ if token.is_used_keyword() => Some(TokenDescription::Keyword), - _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), - token::DocComment(..) => Some(TokenDescription::DocComment), - token::OpenInvisible(InvisibleOrigin::MetaVar(kind)) => { - Some(TokenDescription::MetaVar(kind)) - } - _ => None, - } - } -} - pub fn token_descr(token: &Token) -> String { let s = pprust::token_to_string(token).to_string(); From 849725e96fafddcb0eb65175f79869426e5c1e9f Mon Sep 17 00:00:00 2001 From: enthropy7 <221884178+enthropy7@users.noreply.github.com> Date: Tue, 27 Jan 2026 17:13:42 +0300 Subject: [PATCH 05/47] fix refining_impl_trait suggestion with return_type_notation --- .../src/check/compare_impl_item/refine.rs | 14 ++++++++++- compiler/rustc_hir_analysis/src/errors.rs | 4 ++-- .../async-example-desugared-boxed.stderr | 2 +- .../async-example-desugared-manual.stderr | 2 +- .../bad-item-bound-within-rpitit.stderr | 2 +- ...e-to-map-to-reearlybound-ice-108580.stderr | 5 ++-- tests/ui/impl-trait/in-trait/foreign.stderr | 4 ++-- .../in-trait/refine-return-type-notation.rs | 13 ++++++++++ .../refine-return-type-notation.stderr | 24 +++++++++++++++++++ 9 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/refine-return-type-notation.rs create mode 100644 tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index c20e5146546a2..31104411ab55b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE}; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_types_for_signature}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, @@ -332,6 +333,17 @@ fn report_mismatched_rpitit_signature<'tcx>( hir::FnRetTy::Return(ty) => ty.span, }); + // Use ForSignature mode to ensure RPITITs are printed as `impl Trait` rather than + // `impl Trait { T::method(..) }` when RTN is enabled. + // + // We use `with_no_trimmed_paths!` to avoid triggering the `trimmed_def_paths` query, + // which requires diagnostic context (via `must_produce_diag`). Since we're formatting + // the type before creating the diagnostic, we need to avoid this query. This is the + // standard approach used elsewhere in the compiler for formatting types in suggestions + // (e.g., see `rustc_hir_typeck/src/demand.rs`). + let return_ty_suggestion = + with_no_trimmed_paths!(with_types_for_signature!(format!("{return_ty}"))); + let span = unmatched_bound.unwrap_or(span); tcx.emit_node_span_lint( if is_internal { REFINING_IMPL_TRAIT_INTERNAL } else { REFINING_IMPL_TRAIT_REACHABLE }, @@ -342,7 +354,7 @@ fn report_mismatched_rpitit_signature<'tcx>( trait_return_span, pre, post, - return_ty, + return_ty: return_ty_suggestion, unmatched_bound, }, ); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2a77d0b997e2c..308877f21aa4f 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1023,7 +1023,7 @@ pub(crate) struct UnusedAssociatedTypeBounds { #[diag(hir_analysis_rpitit_refined)] #[note] #[note(hir_analysis_feedback_note)] -pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { +pub(crate) struct ReturnPositionImplTraitInTraitRefined { #[suggestion(applicability = "maybe-incorrect", code = "{pre}{return_ty}{post}")] pub impl_return_span: Span, #[label] @@ -1033,7 +1033,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { pub pre: &'static str, pub post: &'static str, - pub return_ty: Ty<'tcx>, + pub return_ty: String, } #[derive(LintDiagnostic)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index d3765a7e6e6fd..327ac40503ac0 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -18,7 +18,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn foo(&self) -> Pin + '_>> { -LL + fn foo(&self) -> impl Future { +LL + fn foo(&self) -> impl std::future::Future { | warning: 1 warning emitted diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index 3328dea37fe4d..983c946d2a70d 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -18,7 +18,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn foo(&self) -> MyFuture { -LL + fn foo(&self) -> impl Future { +LL + fn foo(&self) -> impl std::future::Future { | warning: 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr index 8bc3c8b647c08..29975bdfcce8c 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr @@ -29,7 +29,7 @@ LL | fn iter(&self) -> impl 'a + Iterator> { help: replace the return type so that it matches the trait | LL - fn iter(&self) -> impl 'a + Iterator> { -LL + fn iter(&self) -> impl Iterator::Item<'_>> + '_ { +LL + fn iter(&self) -> impl std::iter::Iterator::Item<'_>> + '_ { | error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr b/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr index 0a73a36378601..f44b34e38cfd6 100644 --- a/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr +++ b/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr @@ -12,8 +12,9 @@ LL | fn bar(&self) -> impl Iterator + '_ { = note: `#[warn(refining_impl_trait_internal)]` (part of `#[warn(refining_impl_trait)]`) on by default help: replace the return type so that it matches the trait | -LL | fn bar(&self) -> impl Iterator + '_ { - | +++++++++++++++++++ +LL - fn bar(&self) -> impl Iterator + '_ { +LL + fn bar(&self) -> impl std::iter::Iterator + '_ { + | warning: 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/foreign.stderr b/tests/ui/impl-trait/in-trait/foreign.stderr index 8801ccc68b3be..f1c76f743c6e2 100644 --- a/tests/ui/impl-trait/in-trait/foreign.stderr +++ b/tests/ui/impl-trait/in-trait/foreign.stderr @@ -15,7 +15,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn bar(self) -> Arc { -LL + fn bar(self) -> impl Deref { +LL + fn bar(self) -> impl std::ops::Deref { | warning: impl trait in impl method signature does not match trait method signature @@ -34,7 +34,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn bar(self) -> Arc { -LL + fn bar(self) -> impl Deref { +LL + fn bar(self) -> impl std::ops::Deref { | warning: 2 warnings emitted diff --git a/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs b/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs new file mode 100644 index 0000000000000..281f4c73ac21a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs @@ -0,0 +1,13 @@ +#![feature(return_type_notation)] +#![deny(refining_impl_trait)] + +trait Trait { + fn f() -> impl Sized; +} + +impl Trait for () { + fn f() {} + //~^ ERROR impl trait in impl method signature does not match trait method signature +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr b/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr new file mode 100644 index 0000000000000..1f9a5b9e87492 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr @@ -0,0 +1,24 @@ +error: impl trait in impl method signature does not match trait method signature + --> $DIR/refine-return-type-notation.rs:9:5 + | +LL | fn f() -> impl Sized; + | ---------- return type from trait method defined here +... +LL | fn f() {} + | ^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +note: the lint level is defined here + --> $DIR/refine-return-type-notation.rs:2:9 + | +LL | #![deny(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(refining_impl_trait_internal)]` implied by `#[deny(refining_impl_trait)]` +help: replace the return type so that it matches the trait + | +LL | fn f()-> impl Sized {} + | +++++++++++++ + +error: aborting due to 1 previous error + From 91850e90de096eb37364358e8a4eb7e0b30284ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Wed, 28 Jan 2026 22:05:10 +0100 Subject: [PATCH 06/47] Avoid `unsafe fn` in aarch64, powerpc and s390x tests --- .../crates/core_arch/src/aarch64/neon/mod.rs | 264 ++++----- .../crates/core_arch/src/powerpc/altivec.rs | 528 ++++++++++-------- .../crates/core_arch/src/powerpc/vsx.rs | 36 +- .../crates/core_arch/src/s390x/vector.rs | 135 +++-- 4 files changed, 537 insertions(+), 426 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index b172b57f32543..bac45742393cb 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -569,47 +569,46 @@ mod tests { use crate::core_arch::aarch64::test_support::*; use crate::core_arch::arm_shared::test_support::*; use crate::core_arch::{aarch64::neon::*, aarch64::*, simd::*}; - use std::mem::transmute; use stdarch_test::simd_test; #[simd_test(enable = "neon")] - unsafe fn test_vadd_f64() { - let a = 1.; - let b = 8.; - let e = 9.; - let r: f64 = transmute(vadd_f64(transmute(a), transmute(b))); + fn test_vadd_f64() { + let a = f64x1::from_array([1.]); + let b = f64x1::from_array([8.]); + let e = f64x1::from_array([9.]); + let r = f64x1::from(vadd_f64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddq_f64() { + fn test_vaddq_f64() { let a = f64x2::new(1., 2.); let b = f64x2::new(8., 7.); let e = f64x2::new(9., 9.); - let r: f64x2 = transmute(vaddq_f64(transmute(a), transmute(b))); + let r = f64x2::from(vaddq_f64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vadd_s64() { - let a = 1_i64; - let b = 8_i64; - let e = 9_i64; - let r: i64 = transmute(vadd_s64(transmute(a), transmute(b))); + fn test_vadd_s64() { + let a = i64x1::from_array([1]); + let b = i64x1::from_array([8]); + let e = i64x1::from_array([9]); + let r = i64x1::from(vadd_s64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vadd_u64() { - let a = 1_u64; - let b = 8_u64; - let e = 9_u64; - let r: u64 = transmute(vadd_u64(transmute(a), transmute(b))); + fn test_vadd_u64() { + let a = u64x1::from_array([1]); + let b = u64x1::from_array([8]); + let e = u64x1::from_array([9]); + let r = u64x1::from(vadd_u64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddd_s64() { + fn test_vaddd_s64() { let a = 1_i64; let b = 8_i64; let e = 9_i64; @@ -618,7 +617,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vaddd_u64() { + fn test_vaddd_u64() { let a = 1_u64; let b = 8_u64; let e = 9_u64; @@ -627,25 +626,25 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vext_p64() { - let a: i64x1 = i64x1::new(0); - let b: i64x1 = i64x1::new(1); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vext_p64::<0>(transmute(a), transmute(b))); + fn test_vext_p64() { + let a = u64x1::new(0); + let b = u64x1::new(1); + let e = u64x1::new(0); + let r = u64x1::from(vext_p64::<0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_f64() { - let a: f64x1 = f64x1::new(0.); - let b: f64x1 = f64x1::new(1.); - let e: f64x1 = f64x1::new(0.); - let r: f64x1 = transmute(vext_f64::<0>(transmute(a), transmute(b))); + fn test_vext_f64() { + let a = f64x1::new(0.); + let b = f64x1::new(1.); + let e = f64x1::new(0.); + let r = f64x1::from(vext_f64::<0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vshld_n_s64() { + fn test_vshld_n_s64() { let a: i64 = 1; let e: i64 = 4; let r: i64 = vshld_n_s64::<2>(a); @@ -653,7 +652,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshld_n_u64() { + fn test_vshld_n_u64() { let a: u64 = 1; let e: u64 = 4; let r: u64 = vshld_n_u64::<2>(a); @@ -661,7 +660,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshrd_n_s64() { + fn test_vshrd_n_s64() { let a: i64 = 4; let e: i64 = 1; let r: i64 = vshrd_n_s64::<2>(a); @@ -669,7 +668,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshrd_n_u64() { + fn test_vshrd_n_u64() { let a: u64 = 4; let e: u64 = 1; let r: u64 = vshrd_n_u64::<2>(a); @@ -677,7 +676,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vsrad_n_s64() { + fn test_vsrad_n_s64() { let a: i64 = 1; let b: i64 = 4; let e: i64 = 2; @@ -686,7 +685,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vsrad_n_u64() { + fn test_vsrad_n_u64() { let a: u64 = 1; let b: u64 = 4; let e: u64 = 2; @@ -695,293 +694,300 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vdup_n_f64() { + fn test_vdup_n_f64() { let a: f64 = 3.3; let e = f64x1::new(3.3); - let r: f64x1 = transmute(vdup_n_f64(a)); + let r = f64x1::from(vdup_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_n_p64() { + fn test_vdup_n_p64() { let a: u64 = 3; let e = u64x1::new(3); - let r: u64x1 = transmute(vdup_n_p64(a)); + let r = u64x1::from(vdup_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_n_f64() { + fn test_vdupq_n_f64() { let a: f64 = 3.3; let e = f64x2::new(3.3, 3.3); - let r: f64x2 = transmute(vdupq_n_f64(a)); + let r = f64x2::from(vdupq_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_n_p64() { + fn test_vdupq_n_p64() { let a: u64 = 3; let e = u64x2::new(3, 3); - let r: u64x2 = transmute(vdupq_n_p64(a)); + let r = u64x2::from(vdupq_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmov_n_p64() { + fn test_vmov_n_p64() { let a: u64 = 3; let e = u64x1::new(3); - let r: u64x1 = transmute(vmov_n_p64(a)); + let r = u64x1::from(vmov_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmov_n_f64() { + fn test_vmov_n_f64() { let a: f64 = 3.3; let e = f64x1::new(3.3); - let r: f64x1 = transmute(vmov_n_f64(a)); + let r = f64x1::from(vmov_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovq_n_p64() { + fn test_vmovq_n_p64() { let a: u64 = 3; let e = u64x2::new(3, 3); - let r: u64x2 = transmute(vmovq_n_p64(a)); + let r = u64x2::from(vmovq_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovq_n_f64() { + fn test_vmovq_n_f64() { let a: f64 = 3.3; let e = f64x2::new(3.3, 3.3); - let r: f64x2 = transmute(vmovq_n_f64(a)); + let r = f64x2::from(vmovq_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_high_f64() { + fn test_vget_high_f64() { let a = f64x2::new(1.0, 2.0); let e = f64x1::new(2.0); - let r: f64x1 = transmute(vget_high_f64(transmute(a))); + let r = f64x1::from(vget_high_f64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_high_p64() { + fn test_vget_high_p64() { let a = u64x2::new(1, 2); let e = u64x1::new(2); - let r: u64x1 = transmute(vget_high_p64(transmute(a))); + let r = u64x1::from(vget_high_p64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_low_f64() { + fn test_vget_low_f64() { let a = f64x2::new(1.0, 2.0); let e = f64x1::new(1.0); - let r: f64x1 = transmute(vget_low_f64(transmute(a))); + let r = f64x1::from(vget_low_f64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_low_p64() { + fn test_vget_low_p64() { let a = u64x2::new(1, 2); let e = u64x1::new(1); - let r: u64x1 = transmute(vget_low_p64(transmute(a))); + let r = u64x1::from(vget_low_p64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_lane_f64() { + fn test_vget_lane_f64() { let v = f64x1::new(1.0); - let r = vget_lane_f64::<0>(transmute(v)); + let r = vget_lane_f64::<0>(v.into()); assert_eq!(r, 1.0); } #[simd_test(enable = "neon")] - unsafe fn test_vgetq_lane_f64() { + fn test_vgetq_lane_f64() { let v = f64x2::new(0.0, 1.0); - let r = vgetq_lane_f64::<1>(transmute(v)); + let r = vgetq_lane_f64::<1>(v.into()); assert_eq!(r, 1.0); - let r = vgetq_lane_f64::<0>(transmute(v)); + let r = vgetq_lane_f64::<0>(v.into()); assert_eq!(r, 0.0); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_s64() { - let a: i64x1 = i64x1::new(1); - let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_lane_s64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_s64() { + let a = i64x1::new(1); + let b = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = i64x1::from(vcopy_lane_s64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcopy_lane_u64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_u64() { + let a = u64x1::new(1); + let b = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_lane_u64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_p64() { - let a: i64x1 = i64x1::new(1); - let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_lane_p64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_p64() { + let a = u64x1::new(1); + let b = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_lane_p64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_f64() { - let a: f64 = 1.; - let b: f64 = 0.; - let e: f64 = 0.; - let r: f64 = transmute(vcopy_lane_f64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_f64() { + let a = f64x1::from_array([1.]); + let b = f64x1::from_array([0.]); + let e = f64x1::from_array([0.]); + let r = f64x1::from(vcopy_lane_f64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_s64() { - let a: i64x1 = i64x1::new(1); - let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_laneq_s64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_s64() { + let a = i64x1::new(1); + let b = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = i64x1::from(vcopy_laneq_s64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcopy_laneq_u64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_u64() { + let a = u64x1::new(1); + let b = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_laneq_u64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_p64() { - let a: i64x1 = i64x1::new(1); - let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_laneq_p64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_p64() { + let a = u64x1::new(1); + let b = u64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_laneq_p64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_f64() { - let a: f64 = 1.; - let b: f64x2 = f64x2::new(0., 0.5); - let e: f64 = 0.5; - let r: f64 = transmute(vcopy_laneq_f64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_f64() { + let a = f64x1::from_array([1.]); + let b = f64x2::from_array([0., 0.5]); + let e = f64x1::from_array([0.5]); + let r = f64x1::from(vcopy_laneq_f64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vbsl_f64() { + fn test_vbsl_f64() { let a = u64x1::new(0x8000000000000000); let b = f64x1::new(-1.23f64); let c = f64x1::new(2.34f64); let e = f64x1::new(-2.34f64); - let r: f64x1 = transmute(vbsl_f64(transmute(a), transmute(b), transmute(c))); + let r = f64x1::from(vbsl_f64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbsl_p64() { + fn test_vbsl_p64() { let a = u64x1::new(1); let b = u64x1::new(u64::MAX); let c = u64x1::new(u64::MIN); let e = u64x1::new(1); - let r: u64x1 = transmute(vbsl_p64(transmute(a), transmute(b), transmute(c))); + let r = u64x1::from(vbsl_p64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbslq_f64() { + fn test_vbslq_f64() { let a = u64x2::new(1, 0x8000000000000000); let b = f64x2::new(f64::MAX, -1.23f64); let c = f64x2::new(f64::MIN, 2.34f64); let e = f64x2::new(f64::MIN, -2.34f64); - let r: f64x2 = transmute(vbslq_f64(transmute(a), transmute(b), transmute(c))); + let r = f64x2::from(vbslq_f64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbslq_p64() { + fn test_vbslq_p64() { let a = u64x2::new(u64::MAX, 1); let b = u64x2::new(u64::MAX, u64::MAX); let c = u64x2::new(u64::MIN, u64::MIN); let e = u64x2::new(u64::MAX, 1); - let r: u64x2 = transmute(vbslq_p64(transmute(a), transmute(b), transmute(c))); + let r = u64x2::from(vbslq_p64(a.into(), b.into(), c.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_f64() { + fn test_vld1_f64() { let a: [f64; 2] = [0., 1.]; let e = f64x1::new(1.); - let r: f64x1 = transmute(vld1_f64(a[1..].as_ptr())); + let r = unsafe { f64x1::from(vld1_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f64() { + fn test_vld1q_f64() { let a: [f64; 3] = [0., 1., 2.]; let e = f64x2::new(1., 2.); - let r: f64x2 = transmute(vld1q_f64(a[1..].as_ptr())); + let r = unsafe { f64x2::from(vld1q_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1_dup_f64() { + fn test_vld1_dup_f64() { let a: [f64; 2] = [1., 42.]; let e = f64x1::new(42.); - let r: f64x1 = transmute(vld1_dup_f64(a[1..].as_ptr())); + let r = unsafe { f64x1::from(vld1_dup_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_dup_f64() { + fn test_vld1q_dup_f64() { let elem: f64 = 42.; let e = f64x2::new(42., 42.); - let r: f64x2 = transmute(vld1q_dup_f64(&elem)); + let r = unsafe { f64x2::from(vld1q_dup_f64(&elem)) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1_lane_f64() { + fn test_vld1_lane_f64() { let a = f64x1::new(0.); let elem: f64 = 42.; let e = f64x1::new(42.); - let r: f64x1 = transmute(vld1_lane_f64::<0>(&elem, transmute(a))); + let r = unsafe { f64x1::from(vld1_lane_f64::<0>(&elem, a.into())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_lane_f64() { + fn test_vld1q_lane_f64() { let a = f64x2::new(0., 1.); let elem: f64 = 42.; let e = f64x2::new(0., 42.); - let r: f64x2 = transmute(vld1q_lane_f64::<1>(&elem, transmute(a))); + let r = unsafe { f64x2::from(vld1q_lane_f64::<1>(&elem, a.into())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f64() { + fn test_vst1_f64() { let mut vals = [0_f64; 2]; let a = f64x1::new(1.); - vst1_f64(vals[1..].as_mut_ptr(), transmute(a)); + unsafe { + vst1_f64(vals[1..].as_mut_ptr(), a.into()); + } assert_eq!(vals[0], 0.); assert_eq!(vals[1], 1.); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f64() { + fn test_vst1q_f64() { let mut vals = [0_f64; 3]; let a = f64x2::new(1., 2.); - vst1q_f64(vals[1..].as_mut_ptr(), transmute(a)); + unsafe { + vst1q_f64(vals[1..].as_mut_ptr(), a.into()); + } assert_eq!(vals[0], 0.); assert_eq!(vals[1], 1.); diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index fb1a9d8ed9e2c..7786a6731b4c4 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -47,6 +47,54 @@ types! { pub struct vector_float(4 x f32); } +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_char { + #[inline] + fn from(value: m8x16) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m8x16 { + #[inline] + fn from(value: vector_bool_char) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_short { + #[inline] + fn from(value: m16x8) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m16x8 { + #[inline] + fn from(value: vector_bool_short) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_int { + #[inline] + fn from(value: m32x4) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m32x4 { + #[inline] + fn from(value: vector_bool_int) -> Self { + unsafe { transmute(value) } + } +} + #[allow(improper_ctypes)] unsafe extern "C" { #[link_name = "llvm.ppc.altivec.lvx"] @@ -4653,22 +4701,22 @@ mod tests { }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!(d, r); } }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], $d:expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!($d, r); } } @@ -4677,11 +4725,11 @@ mod tests { macro_rules! test_vec_1 { { $name: ident, $fn:ident, f32x4, [$($a:expr),+], ~[$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: vector_float = transmute(f32x4::new($($a),+)); + fn $name() { + let a = vector_float::from(f32x4::new($($a),+)); - let d: vector_float = transmute(f32x4::new($($d),+)); - let r = transmute(vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON))); + let d = vector_float::from(f32x4::new($($d),+)); + let r = m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON)) }); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); } @@ -4691,18 +4739,18 @@ mod tests { }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a)); + let r = $ty_out::from(unsafe { $fn(a) }); assert_eq!(d, r); } } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ld() { + fn test_vec_ld() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4711,14 +4759,14 @@ mod tests { ]; for off in 0..16 { - let v: u8x16 = transmute(vec_ld(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ld(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) ); } for off in 16..32 { - let v: u8x16 = transmute(vec_ld(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ld(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new( @@ -4729,7 +4777,7 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_xl() { + fn test_vec_xl() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4738,7 +4786,7 @@ mod tests { ]; for off in 0..16 { - let val: u8x16 = transmute(vec_xl(0, (pat.as_ptr() as *const u8).offset(off))); + let val = u8x16::from(unsafe { vec_xl(0, (pat.as_ptr() as *const u8).offset(off)) }); for i in 0..16 { let v = val.extract_dyn(i); assert_eq!(off as usize + i, v as usize); @@ -4747,14 +4795,16 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_xst() { - let v: vector_unsigned_char = transmute(u8x16::new( + fn test_vec_xst() { + let v = vector_unsigned_char::from(u8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, )); for off in 0..16 { let mut buf = [0u8; 32]; - vec_xst(v, 0, (buf.as_mut_ptr() as *mut u8).offset(off)); + unsafe { + vec_xst(v, 0, (buf.as_mut_ptr() as *mut u8).offset(off)); + } for i in 0..16 { assert_eq!(i as u8, buf[off as usize..][i]); } @@ -4762,7 +4812,7 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ldl() { + fn test_vec_ldl() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4771,14 +4821,14 @@ mod tests { ]; for off in 0..16 { - let v: u8x16 = transmute(vec_ldl(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ldl(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) ); } for off in 16..32 { - let v: u8x16 = transmute(vec_ldl(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ldl(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new( @@ -4789,30 +4839,30 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u8() { + fn test_vec_lde_u8() { let pat = [u8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, )]; for off in 0..16 { - let v: u8x16 = transmute(vec_lde(off, pat.as_ptr() as *const u8)); + let v = u8x16::from(unsafe { vec_lde(off, pat.as_ptr() as *const u8) }); assert_eq!(off as u8, v.extract_dyn(off as _)); } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u16() { + fn test_vec_lde_u16() { let pat = [u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)]; for off in 0..8 { - let v: u16x8 = transmute(vec_lde(off * 2, pat.as_ptr() as *const u16)); + let v = u16x8::from(unsafe { vec_lde(off * 2, pat.as_ptr() as *const u16) }); assert_eq!(off as u16, v.extract_dyn(off as _)); } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u32() { + fn test_vec_lde_u32() { let pat = [u32x4::new(0, 1, 2, 3)]; for off in 0..4 { - let v: u32x4 = transmute(vec_lde(off * 4, pat.as_ptr() as *const u32)); + let v = u32x4::from(unsafe { vec_lde(off * 4, pat.as_ptr() as *const u32) }); assert_eq!(off as u32, v.extract_dyn(off as _)); } } @@ -5818,9 +5868,9 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_cmpb() { - let a: vector_float = transmute(f32x4::new(0.1, 0.5, 0.6, 0.9)); - let b: vector_float = transmute(f32x4::new(-0.1, 0.5, -0.6, 0.9)); + fn test_vec_cmpb() { + let a = vector_float::from(f32x4::new(0.1, 0.5, 0.6, 0.9)); + let b = vector_float::from(f32x4::new(-0.1, 0.5, -0.6, 0.9)); let d = i32x4::new( -0b10000000000000000000000000000000, 0, @@ -5828,15 +5878,15 @@ mod tests { 0, ); - assert_eq!(d, transmute(vec_cmpb(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_cmpb(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ceil() { - let a: vector_float = transmute(f32x4::new(0.1, 0.5, 0.6, 0.9)); + fn test_vec_ceil() { + let a = vector_float::from(f32x4::new(0.1, 0.5, 0.6, 0.9)); let d = f32x4::new(1.0, 1.0, 1.0, 1.0); - assert_eq!(d, transmute(vec_ceil(a))); + assert_eq!(d, f32x4::from(unsafe { vec_ceil(a) })); } test_vec_2! { test_vec_andc, vec_andc, i32x4, @@ -5926,11 +5976,11 @@ mod tests { macro_rules! test_vec_abs { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = vec_splats($a); - let a: s_t_l!($ty) = vec_abs(a); + fn $name() { + let a = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abs(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5943,11 +5993,11 @@ mod tests { macro_rules! test_vec_abss { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = vec_splats($a); - let a: s_t_l!($ty) = vec_abss(a); + fn $name() { + let a = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abss(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5959,10 +6009,10 @@ mod tests { macro_rules! test_vec_splats { { $name: ident, $ty: ident, $a: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = vec_splats($a); + fn $name() { + let a: s_t_l!($ty) = unsafe { vec_splats($a) }; let d = $ty::splat($a); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5978,10 +6028,10 @@ mod tests { macro_rules! test_vec_splat { { $name: ident, $fun: ident, $ty: ident, $a: expr, $b: expr} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = $fun::<$a>(); + fn $name() { + let a = unsafe { $fun::<$a>() }; let d = $ty::splat($b); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -6073,12 +6123,12 @@ mod tests { macro_rules! test_vec_min { { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty::new($($d),+); - let r : $ty = transmute(vec_min(a, b)); + let r = $ty::from(unsafe { vec_min(a, b) }); assert_eq!(d, r); } } @@ -6117,12 +6167,12 @@ mod tests { macro_rules! test_vec_max { { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty::new($($d),+); - let r : $ty = transmute(vec_max(a, b)); + let r = $ty::from(unsafe { vec_max(a, b) }); assert_eq!(d, r); } } @@ -6163,13 +6213,13 @@ mod tests { $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+)); - let b: $longtype = transmute($shorttype::new($($b),+)); - let c: vector_unsigned_char = transmute(u8x16::new($($c),+)); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+)); + let b = $longtype::from($shorttype::new($($b),+)); + let c = vector_unsigned_char::from(u8x16::new($($c),+)); let d = $shorttype::new($($d),+); - let r: $shorttype = transmute(vec_perm(a, b, c)); + let r = $shorttype::from(unsafe { vec_perm(a, b, c) }); assert_eq!(d, r); } } @@ -6249,8 +6299,8 @@ mod tests { [0.0, 1.0, 1.0, 1.1]} #[simd_test(enable = "altivec")] - unsafe fn test_vec_madds() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_madds() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6260,19 +6310,19 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = i16x8::new(0, 3, 6, 9, 12, 15, 18, 21); - assert_eq!(d, transmute(vec_madds(a, b, c))); + assert_eq!(d, i16x8::from(unsafe { vec_madds(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_madd_float() { - let a: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let b: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let c: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); + fn test_vec_madd_float() { + let a = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let b = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let c = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); let d = f32x4::new( 0.1 * 0.1 + 0.1, 0.2 * 0.2 + 0.2, @@ -6280,26 +6330,26 @@ mod tests { 0.4 * 0.4 + 0.4, ); - assert_eq!(d, transmute(vec_madd(a, b, c))); + assert_eq!(d, f32x4::from(unsafe { vec_madd(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_nmsub_float() { - let a: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let b: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let c: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); + fn test_vec_nmsub_float() { + let a = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let b = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let c = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); let d = f32x4::new( -(0.1 * 0.1 - 0.1), -(0.2 * 0.2 - 0.2), -(0.3 * 0.3 - 0.3), -(0.4 * 0.4 - 0.4), ); - assert_eq!(d, transmute(vec_nmsub(a, b, c))); + assert_eq!(d, f32x4::from(unsafe { vec_nmsub(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mradds() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_mradds() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6309,25 +6359,25 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, i16::MAX - 1)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, i16::MAX - 1)); let d = i16x8::new(0, 3, 6, 9, 12, 15, 18, i16::MAX); - assert_eq!(d, transmute(vec_mradds(a, b, c))); + assert_eq!(d, i16x8::from(unsafe { vec_mradds(a, b, c) })); } macro_rules! test_vec_mladd { {$name:ident, $sa:ident, $la:ident, $sbc:ident, $lbc:ident, $sd:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: $la = transmute($sa::new($($a),+)); - let b: $lbc = transmute($sbc::new($($b),+)); - let c = transmute($sbc::new($($c),+)); + fn $name() { + let a = $la::from($sa::new($($a),+)); + let b = $lbc::from($sbc::new($($b),+)); + let c = $sbc::new($($c),+).into(); let d = $sd::new($($d),+); - assert_eq!(d, transmute(vec_mladd(a, b, c))); + assert_eq!(d, $sd::from(unsafe { vec_mladd(a, b, c) })); } } } @@ -6335,24 +6385,24 @@ mod tests { test_vec_mladd! { test_vec_mladd_u16x8_u16x8, u16x8, vector_unsigned_short, u16x8, vector_unsigned_short, u16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } - test_vec_mladd! { test_vec_mladd_u16x8_i16x8, u16x8, vector_unsigned_short, i16x8, vector_unsigned_short, i16x8, + test_vec_mladd! { test_vec_mladd_u16x8_i16x8, u16x8, vector_unsigned_short, i16x8, vector_signed_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } test_vec_mladd! { test_vec_mladd_i16x8_u16x8, i16x8, vector_signed_short, u16x8, vector_unsigned_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } - test_vec_mladd! { test_vec_mladd_i16x8_i16x8, i16x8, vector_signed_short, i16x8, vector_unsigned_short, i16x8, + test_vec_mladd! { test_vec_mladd_i16x8_i16x8, i16x8, vector_signed_short, i16x8, vector_signed_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_unsigned_char = transmute(u8x16::new( + fn test_vec_msum_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_unsigned_char::from(u8x16::new( 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, )); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1 + 2 + 3) * 255 + 0, (4 + 5 + 6 + 7) * 255 + 1, @@ -6360,17 +6410,17 @@ mod tests { (4 + 5 + 6 + 7) * 255 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_msum_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, -1, 2, -3, 1, -1, 1, -1, 0, 1, 2, 3, 4, -5, -6, -7, )); - let b: vector_unsigned_char = - transmute(i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); - let c: vector_signed_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = + vector_unsigned_char::from(u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1 + 2 - 3) + 0, (0) + 1, @@ -6378,11 +6428,12 @@ mod tests { (4 - 5 - 6 - 7) + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msum(a, b, c) })); } + #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new( + fn test_vec_msum_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6392,9 +6443,8 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_unsigned_short = - transmute(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = vector_unsigned_short::from(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1) * 256 * 256 + 0, (2 + 3) * 256 * 256 + 1, @@ -6402,12 +6452,12 @@ mod tests { (6 + 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_signed_short() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_msum_signed_short() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, -1 * 256, 2 * 256, @@ -6417,8 +6467,8 @@ mod tests { 6 * 256, -7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1) * 256 * 256 + 0, (2 - 3) * 256 * 256 + 1, @@ -6426,12 +6476,12 @@ mod tests { (6 - 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msums_unsigned() { - let a: vector_unsigned_short = transmute(u16x8::new( + fn test_vec_msums_unsigned() { + let a = vector_unsigned_short::from(u16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6441,9 +6491,8 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_unsigned_short = - transmute(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = vector_unsigned_short::from(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1) * 256 * 256 + 0, (2 + 3) * 256 * 256 + 1, @@ -6451,12 +6500,12 @@ mod tests { (6 + 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msums(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msums(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msums_signed() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_msums_signed() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, -1 * 256, 2 * 256, @@ -6466,8 +6515,8 @@ mod tests { 6 * 256, -7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1) * 256 * 256 + 0, (2 - 3) * 256 * 256 + 1, @@ -6475,23 +6524,23 @@ mod tests { (6 - 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msums(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msums(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum2s() { - let a: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum2s() { + let a = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new(0, 0 + 1 + 1, 0, 2 + 3 + 3); - assert_eq!(d, transmute(vec_sum2s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum2s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( 0 + 1 + 2 + 3 + 0, 4 + 5 + 6 + 7 + 1, @@ -6499,13 +6548,13 @@ mod tests { 4 + 5 + 6 + 7 + 3, ); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, u32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_signed_char() { - let a: vector_signed_char = - transmute(i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_signed_char() { + let a = + vector_signed_char::from(i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( 0 + 1 + 2 + 3 + 0, 4 + 5 + 6 + 7 + 1, @@ -6513,109 +6562,110 @@ mod tests { 4 + 5 + 6 + 7 + 3, ); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new(0 + 1 + 0, 2 + 3 + 1, 4 + 5 + 2, 6 + 7 + 3); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mule_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); let d = u16x8::new(0 * 0, 2 * 2, 4 * 4, 6 * 6, 0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, u16x8::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_mule_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, 1, -2, 3, -4, 5, -6, 7, 0, 1, 2, 3, 4, 5, 6, 7, )); let d = i16x8::new(0 * 0, 2 * 2, 4 * 4, 6 * 6, 0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, i16x8::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mule_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = u32x4::new(0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, u32x4::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); + fn test_vec_mule_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); let d = i32x4::new(0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, i32x4::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mulo_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); let d = u16x8::new(1 * 1, 3 * 3, 5 * 5, 7 * 7, 1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, u16x8::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_mulo_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, 1, -2, 3, -4, 5, -6, 7, 0, 1, 2, 3, 4, 5, 6, 7, )); let d = i16x8::new(1 * 1, 3 * 3, 5 * 5, 7 * 7, 1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, i16x8::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mulo_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = u32x4::new(1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, u32x4::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); + fn test_vec_mulo_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); let d = i32x4::new(1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, i32x4::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn vec_add_i32x4_i32x4() { + fn vec_add_i32x4_i32x4() { let x = i32x4::new(1, 2, 3, 4); let y = i32x4::new(4, 3, 2, 1); - let x: vector_signed_int = transmute(x); - let y: vector_signed_int = transmute(y); - let z = vec_add(x, y); - assert_eq!(i32x4::splat(5), transmute(z)); + let x = vector_signed_int::from(x); + let y = vector_signed_int::from(y); + let z = unsafe { vec_add(x, y) }; + assert_eq!(i32x4::splat(5), i32x4::from(z)); } #[simd_test(enable = "altivec")] - unsafe fn vec_ctf_u32() { - let v: vector_unsigned_int = transmute(u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42)); - let v2 = vec_ctf::<1, _>(v); - let r2: vector_float = transmute(f32x4::new(0.0, 2147483600.0, 2147483600.0, 21.0)); - let v4 = vec_ctf::<2, _>(v); - let r4: vector_float = transmute(f32x4::new(0.0, 1073741800.0, 1073741800.0, 10.5)); - let v8 = vec_ctf::<3, _>(v); - let r8: vector_float = transmute(f32x4::new(0.0, 536870900.0, 536870900.0, 5.25)); + fn vec_ctf_u32() { + let v = vector_unsigned_int::from(u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42)); + let v2 = unsafe { vec_ctf::<1, _>(v) }; + let r2 = vector_float::from(f32x4::new(0.0, 2147483600.0, 2147483600.0, 21.0)); + let v4 = unsafe { vec_ctf::<2, _>(v) }; + let r4 = vector_float::from(f32x4::new(0.0, 1073741800.0, 1073741800.0, 10.5)); + let v8 = unsafe { vec_ctf::<3, _>(v) }; + let r8 = vector_float::from(f32x4::new(0.0, 536870900.0, 536870900.0, 5.25)); let check = |a, b| { - let r = transmute(vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON))); + let r = + m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON)) }); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); }; @@ -6626,26 +6676,32 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ctu() { + fn test_vec_ctu() { let v = u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42); - let v2: u32x4 = transmute(vec_ctu::<1>(transmute(f32x4::new( - 0.0, - 2147483600.0, - 2147483600.0, - 21.0, - )))); - let v4: u32x4 = transmute(vec_ctu::<2>(transmute(f32x4::new( - 0.0, - 1073741800.0, - 1073741800.0, - 10.5, - )))); - let v8: u32x4 = transmute(vec_ctu::<3>(transmute(f32x4::new( - 0.0, - 536870900.0, - 536870900.0, - 5.25, - )))); + let v2 = u32x4::from(unsafe { + vec_ctu::<1>(vector_float::from(f32x4::new( + 0.0, + 2147483600.0, + 2147483600.0, + 21.0, + ))) + }); + let v4 = u32x4::from(unsafe { + vec_ctu::<2>(vector_float::from(f32x4::new( + 0.0, + 1073741800.0, + 1073741800.0, + 10.5, + ))) + }); + let v8 = u32x4::from(unsafe { + vec_ctu::<3>(vector_float::from(f32x4::new( + 0.0, + 536870900.0, + 536870900.0, + 5.25, + ))) + }); assert_eq!(v2, v); assert_eq!(v4, v); @@ -6653,18 +6709,18 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn vec_ctf_i32() { - let v: vector_signed_int = transmute(i32x4::new(i32::MIN, i32::MAX, i32::MAX - 42, 42)); - let v2 = vec_ctf::<1, _>(v); - let r2: vector_float = - transmute(f32x4::new(-1073741800.0, 1073741800.0, 1073741800.0, 21.0)); - let v4 = vec_ctf::<2, _>(v); - let r4: vector_float = transmute(f32x4::new(-536870900.0, 536870900.0, 536870900.0, 10.5)); - let v8 = vec_ctf::<3, _>(v); - let r8: vector_float = transmute(f32x4::new(-268435460.0, 268435460.0, 268435460.0, 5.25)); + fn vec_ctf_i32() { + let v = vector_signed_int::from(i32x4::new(i32::MIN, i32::MAX, i32::MAX - 42, 42)); + let v2 = unsafe { vec_ctf::<1, _>(v) }; + let r2 = vector_float::from(f32x4::new(-1073741800.0, 1073741800.0, 1073741800.0, 21.0)); + let v4 = unsafe { vec_ctf::<2, _>(v) }; + let r4 = vector_float::from(f32x4::new(-536870900.0, 536870900.0, 536870900.0, 10.5)); + let v8 = unsafe { vec_ctf::<3, _>(v) }; + let r8 = vector_float::from(f32x4::new(-268435460.0, 268435460.0, 268435460.0, 5.25)); let check = |a, b| { - let r = transmute(vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON))); + let r = + m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON)) }); println!("{:?} {:?}", a, b); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); @@ -6676,26 +6732,32 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_cts() { + fn test_vec_cts() { let v = i32x4::new(i32::MIN, i32::MAX, i32::MAX, 42); - let v2: i32x4 = transmute(vec_cts::<1>(transmute(f32x4::new( - -1073741800.0, - 1073741800.0, - 1073741800.0, - 21.0, - )))); - let v4: i32x4 = transmute(vec_cts::<2>(transmute(f32x4::new( - -536870900.0, - 536870900.0, - 536870900.0, - 10.5, - )))); - let v8: i32x4 = transmute(vec_cts::<3>(transmute(f32x4::new( - -268435460.0, - 268435460.0, - 268435460.0, - 5.25, - )))); + let v2 = i32x4::from(unsafe { + vec_cts::<1>(transmute(f32x4::new( + -1073741800.0, + 1073741800.0, + 1073741800.0, + 21.0, + ))) + }); + let v4 = i32x4::from(unsafe { + vec_cts::<2>(transmute(f32x4::new( + -536870900.0, + 536870900.0, + 536870900.0, + 10.5, + ))) + }); + let v8 = i32x4::from(unsafe { + vec_cts::<3>(transmute(f32x4::new( + -268435460.0, + 268435460.0, + 268435460.0, + 5.25, + ))) + }); assert_eq!(v2, v); assert_eq!(v4, v); diff --git a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs index ca9fcaabe8b22..0aac236173401 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs @@ -9,6 +9,7 @@ #![allow(non_camel_case_types)] use crate::core_arch::powerpc::*; +use crate::core_arch::simd::*; #[cfg(test)] use stdarch_test::assert_instr; @@ -34,6 +35,22 @@ types! { // pub struct vector_unsigned___int128 = i128x1; } +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_long { + #[inline] + fn from(value: m64x2) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m64x2 { + #[inline] + fn from(value: vector_bool_long) -> Self { + unsafe { transmute(value) } + } +} + #[allow(improper_ctypes)] unsafe extern "C" { #[link_name = "llvm.ppc.altivec.vperm"] @@ -46,7 +63,6 @@ unsafe extern "C" { mod sealed { use super::*; - use crate::core_arch::simd::*; #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub trait VectorPermDI { @@ -221,14 +237,16 @@ mod tests { macro_rules! test_vec_xxpermdi { {$name:ident, $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "vsx")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+, $($b),+)); - let b = transmute($shorttype::new($($c),+, $($d),+)); - - assert_eq!($shorttype::new($($a),+, $($c),+), transmute(vec_xxpermdi::<_, 0>(a, b))); - assert_eq!($shorttype::new($($b),+, $($c),+), transmute(vec_xxpermdi::<_, 1>(a, b))); - assert_eq!($shorttype::new($($a),+, $($d),+), transmute(vec_xxpermdi::<_, 2>(a, b))); - assert_eq!($shorttype::new($($b),+, $($d),+), transmute(vec_xxpermdi::<_, 3>(a, b))); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+, $($b),+)); + let b = $longtype::from($shorttype::new($($c),+, $($d),+)); + + unsafe { + assert_eq!($shorttype::new($($a),+, $($c),+), $shorttype::from(vec_xxpermdi::<_, 0>(a, b))); + assert_eq!($shorttype::new($($b),+, $($c),+), $shorttype::from(vec_xxpermdi::<_, 1>(a, b))); + assert_eq!($shorttype::new($($a),+, $($d),+), $shorttype::from(vec_xxpermdi::<_, 2>(a, b))); + assert_eq!($shorttype::new($($b),+, $($d),+), $shorttype::from(vec_xxpermdi::<_, 3>(a, b))); + } } } } diff --git a/library/stdarch/crates/core_arch/src/s390x/vector.rs b/library/stdarch/crates/core_arch/src/s390x/vector.rs index e1f841030c000..346cd674df665 100644 --- a/library/stdarch/crates/core_arch/src/s390x/vector.rs +++ b/library/stdarch/crates/core_arch/src/s390x/vector.rs @@ -51,6 +51,54 @@ types! { pub struct vector_double(2 x f64); } +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_char { + #[inline] + fn from(value: m8x16) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m8x16 { + #[inline] + fn from(value: vector_bool_char) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_short { + #[inline] + fn from(value: m16x8) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m16x8 { + #[inline] + fn from(value: vector_bool_short) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_int { + #[inline] + fn from(value: m32x4) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m32x4 { + #[inline] + fn from(value: vector_bool_int) -> Self { + unsafe { transmute(value) } + } +} + #[repr(C, packed)] struct PackedTuple { x: T, @@ -6051,27 +6099,16 @@ mod tests { } macro_rules! test_vec_1 { - { $name: ident, $fn:ident, f32x4, [$($a:expr),+], ~[$($d:expr),+] } => { - #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: vector_float = transmute(f32x4::new($($a),+)); - - let d: vector_float = transmute(f32x4::new($($d),+)); - let r = transmute(vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON))); - let e = m32x4::new(true, true, true, true); - assert_eq!(e, r); - } - }; { $name: ident, $fn:ident, $ty: ident, [$($a:expr),+], [$($d:expr),+] } => { test_vec_1! { $name, $fn, $ty -> $ty, [$($a),+], [$($d),+] } }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a)); + let r = $ty_out::from(unsafe { $fn(a) }); assert_eq!(d, r); } } @@ -6086,35 +6123,23 @@ mod tests { }; { $name: ident, $fn:ident, $ty1: ident, $ty2: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty1) = transmute($ty1::new($($a),+)); - let b: s_t_l!($ty2) = transmute($ty2::new($($b),+)); + fn $name() { + let a: s_t_l!($ty1) = $ty1::new($($a),+).into(); + let b: s_t_l!($ty2) = $ty2::new($($b),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!(d, r); } }; - { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], $d:expr } => { - #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); - - let r : $ty_out = transmute($fn(a, b)); - assert_eq!($d, r); - } - } } #[simd_test(enable = "vector")] - unsafe fn vec_add_i32x4_i32x4() { - let x = i32x4::new(1, 2, 3, 4); - let y = i32x4::new(4, 3, 2, 1); - let x: vector_signed_int = transmute(x); - let y: vector_signed_int = transmute(y); - let z = vec_add(x, y); - assert_eq!(i32x4::splat(5), transmute(z)); + fn vec_add_i32x4_i32x4() { + let x = vector_signed_int::from(i32x4::new(1, 2, 3, 4)); + let y = vector_signed_int::from(i32x4::new(4, 3, 2, 1)); + let z = unsafe { vec_add(x, y) }; + assert_eq!(i32x4::splat(5), i32x4::from(z)); } macro_rules! test_vec_sub { @@ -6232,11 +6257,11 @@ mod tests { macro_rules! test_vec_abs { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = vec_splats($a); - let a: s_t_l!($ty) = vec_abs(a); + fn $name() { + let a: s_t_l!($ty) = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abs(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -6386,7 +6411,7 @@ mod tests { [0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 16], [4, 2, 1, 8] } - test_vec_2! { test_vec_sral_pos, vec_sral, u32x4, u8x16 -> i32x4, + test_vec_2! { test_vec_sral_pos, vec_sral, u32x4, u8x16 -> u32x4, [0b1000, 0b1000, 0b1000, 0b1000], [0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 16], [4, 2, 1, 8] } @@ -6423,13 +6448,13 @@ mod tests { $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+)); - let b: $longtype = transmute($shorttype::new($($b),+)); - let c: vector_unsigned_char = transmute(u8x16::new($($c),+)); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+)); + let b = $longtype::from($shorttype::new($($b),+)); + let c = vector_unsigned_char::from(u8x16::new($($c),+)); let d = $shorttype::new($($d),+); - let r: $shorttype = transmute(vec_perm(a, b, c)); + let r = $shorttype::from(unsafe { vec_perm(a, b, c) }); assert_eq!(d, r); } } @@ -6512,46 +6537,46 @@ mod tests { [core::f32::consts::PI, 1.0, 25.0, 2.0], [core::f32::consts::PI.sqrt(), 1.0, 5.0, core::f32::consts::SQRT_2] } - test_vec_2! { test_vec_find_any_eq, vec_find_any_eq, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq, vec_find_any_eq, i32x4, i32x4 -> i32x4, [1, -2, 3, -4], [-5, 3, -7, 8], - [0, 0, 0xFFFFFFFF, 0] + [0, 0, !0, 0] } - test_vec_2! { test_vec_find_any_ne, vec_find_any_ne, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne, vec_find_any_ne, i32x4, i32x4 -> i32x4, [1, -2, 3, -4], [-5, 3, -7, 8], - [0xFFFFFFFF, 0xFFFFFFFF, 0, 0xFFFFFFFF] + [!0, !0, 0, !0] } - test_vec_2! { test_vec_find_any_eq_idx_1, vec_find_any_eq_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_idx_1, vec_find_any_eq_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [5, 3, 7, 8], [0, 8, 0, 0] } - test_vec_2! { test_vec_find_any_eq_idx_2, vec_find_any_eq_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_idx_2, vec_find_any_eq_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [5, 6, 7, 8], [0, 16, 0, 0] } - test_vec_2! { test_vec_find_any_ne_idx_1, vec_find_any_ne_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_idx_1, vec_find_any_ne_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [1, 5, 3, 4], [0, 4, 0, 0] } - test_vec_2! { test_vec_find_any_ne_idx_2, vec_find_any_ne_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_idx_2, vec_find_any_ne_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [1, 2, 3, 4], [0, 16, 0, 0] } - test_vec_2! { test_vec_find_any_eq_or_0_idx_1, vec_find_any_eq_or_0_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_or_0_idx_1, vec_find_any_eq_or_0_idx, i32x4, i32x4 -> i32x4, [1, 2, 0, 4], [5, 6, 7, 8], [0, 8, 0, 0] } - test_vec_2! { test_vec_find_any_ne_or_0_idx_1, vec_find_any_ne_or_0_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_or_0_idx_1, vec_find_any_ne_or_0_idx, i32x4, i32x4 -> i32x4, [1, 2, 0, 4], [1, 2, 3, 4], [0, 8, 0, 0] From e164dca633aa9dcc6f7929ac69be4f16e30d7ddd Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jan 2026 10:34:44 +0100 Subject: [PATCH 07/47] Don't expect specific instructions for _mm256_set_pd/_mm_set_ps These don't correspond to specific instructions and will produce different instructions on x86/x86_64 based on ABI details. --- library/stdarch/crates/core_arch/src/x86/avx.rs | 1 - library/stdarch/crates/core_arch/src/x86/sse.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx.rs b/library/stdarch/crates/core_arch/src/x86/avx.rs index 7b4b210bacf4c..74fc2db13dcdc 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx.rs @@ -2426,7 +2426,6 @@ pub const fn _mm256_setzero_si256() -> __m256i { #[inline] #[target_feature(enable = "avx")] // This intrinsic has no corresponding instruction. -#[cfg_attr(test, assert_instr(vinsertf128))] #[stable(feature = "simd_x86", since = "1.27.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_set_pd(a: f64, b: f64, c: f64, d: f64) -> __m256d { diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs index b83274e60e72a..2c4439a3f3a55 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse.rs @@ -968,7 +968,7 @@ pub const fn _mm_set_ps1(a: f32) -> __m128 { /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set_ps) #[inline] #[target_feature(enable = "sse")] -#[cfg_attr(test, assert_instr(unpcklps))] +// This intrinsic has no corresponding instruction. #[stable(feature = "simd_x86", since = "1.27.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_set_ps(a: f32, b: f32, c: f32, d: f32) -> __m128 { From 293b61e4440234fddee48dba109d61d86f327b5c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jan 2026 11:07:06 +0100 Subject: [PATCH 08/47] Ignore non-yml files in generator Otherwise this picks up vim .swp files. --- library/stdarch/crates/stdarch-gen-arm/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/stdarch/crates/stdarch-gen-arm/src/main.rs b/library/stdarch/crates/stdarch-gen-arm/src/main.rs index 9bf7d0981deb9..e14e2782485b9 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/main.rs @@ -139,6 +139,7 @@ fn parse_args() -> Vec<(PathBuf, Option)> { .into_iter() .filter_map(Result::ok) .filter(|f| f.file_type().is_file()) + .filter(|f| f.file_name().to_string_lossy().ends_with(".yml")) .map(|f| (f.into_path(), out_dir.clone())) .collect() } From f5d594a309d31c83d55fd67d3178429c70b75d95 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jan 2026 11:21:11 +0100 Subject: [PATCH 09/47] Change lanes vcopy_lane tests to avoid zip2 --- .../core_arch/src/aarch64/neon/generated.rs | 78 +++++++++---------- .../spec/neon/aarch64.spec.yml | 8 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 9507b71106dd1..3d5d07ac1b4ed 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -4092,7 +4092,7 @@ pub fn vcmlaq_rot90_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_f32( @@ -4113,7 +4113,7 @@ pub fn vcopy_lane_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { @@ -4137,7 +4137,7 @@ pub fn vcopy_lane_s8(a: int8x8_t, b: int8x8_ #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { @@ -4157,7 +4157,7 @@ pub fn vcopy_lane_s16(a: int16x4_t, b: int16 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { @@ -4175,7 +4175,7 @@ pub fn vcopy_lane_s32(a: int32x2_t, b: int32 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { @@ -4199,7 +4199,7 @@ pub fn vcopy_lane_u8(a: uint8x8_t, b: uint8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u16( @@ -4222,7 +4222,7 @@ pub fn vcopy_lane_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u32( @@ -4243,7 +4243,7 @@ pub fn vcopy_lane_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { @@ -4267,7 +4267,7 @@ pub fn vcopy_lane_p8(a: poly8x8_t, b: poly8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_p16( @@ -4290,7 +4290,7 @@ pub fn vcopy_lane_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_f32( @@ -4312,7 +4312,7 @@ pub fn vcopy_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s8(a: int8x8_t, b: int8x16_t) -> int8x8_t { @@ -4338,7 +4338,7 @@ pub fn vcopy_laneq_s8(a: int8x8_t, b: int8x1 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s16( @@ -4362,7 +4362,7 @@ pub fn vcopy_laneq_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s32( @@ -4384,7 +4384,7 @@ pub fn vcopy_laneq_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u8( @@ -4413,7 +4413,7 @@ pub fn vcopy_laneq_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u16( @@ -4437,7 +4437,7 @@ pub fn vcopy_laneq_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u32( @@ -4459,7 +4459,7 @@ pub fn vcopy_laneq_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_p8( @@ -4488,7 +4488,7 @@ pub fn vcopy_laneq_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_p16( @@ -4624,7 +4624,7 @@ pub fn vcopyq_lane_p64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s8(a: int8x16_t, b: int8x8_t) -> int8x16_t { @@ -4994,7 +4994,7 @@ pub fn vcopyq_lane_s8(a: int8x16_t, b: int8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s16( @@ -5022,7 +5022,7 @@ pub fn vcopyq_lane_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s32( @@ -5046,7 +5046,7 @@ pub fn vcopyq_lane_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u8( @@ -5419,7 +5419,7 @@ pub fn vcopyq_lane_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u16( @@ -5447,7 +5447,7 @@ pub fn vcopyq_lane_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u32( @@ -5471,7 +5471,7 @@ pub fn vcopyq_lane_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_p8( @@ -5844,7 +5844,7 @@ pub fn vcopyq_lane_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_p16( @@ -5872,7 +5872,7 @@ pub fn vcopyq_lane_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_f32( @@ -5895,7 +5895,7 @@ pub fn vcopyq_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_f64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_f64( @@ -5916,7 +5916,7 @@ pub fn vcopyq_laneq_f64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s8( @@ -6287,7 +6287,7 @@ pub fn vcopyq_laneq_s8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s16( @@ -6314,7 +6314,7 @@ pub fn vcopyq_laneq_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s32( @@ -6337,7 +6337,7 @@ pub fn vcopyq_laneq_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s64( @@ -6358,7 +6358,7 @@ pub fn vcopyq_laneq_s64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u8( @@ -6729,7 +6729,7 @@ pub fn vcopyq_laneq_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u16( @@ -6756,7 +6756,7 @@ pub fn vcopyq_laneq_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u32( @@ -6779,7 +6779,7 @@ pub fn vcopyq_laneq_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u64( @@ -6800,7 +6800,7 @@ pub fn vcopyq_laneq_u64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p8( @@ -7171,7 +7171,7 @@ pub fn vcopyq_laneq_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p16( @@ -7198,7 +7198,7 @@ pub fn vcopyq_laneq_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p64( diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index a9bc377924dd0..a099c2c8d6943 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -8958,7 +8958,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -8983,7 +8983,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -9008,7 +9008,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -9037,7 +9037,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] From b500dd3f6b5af7e198a8a307d9eadcd8891dad26 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jan 2026 11:28:32 +0100 Subject: [PATCH 10/47] Adjust expected output for vrfin It actually generates vrfin now --- library/stdarch/crates/core_arch/src/powerpc/altivec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index fb1a9d8ed9e2c..0e238c532553f 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -3249,7 +3249,7 @@ mod sealed { unsafe fn vec_round(self) -> Self; } - test_impl! { vec_vrfin(a: vector_float) -> vector_float [vrfin, xvrspic] } + test_impl! { vec_vrfin(a: vector_float) -> vector_float [vrfin, vrfin] } #[unstable(feature = "stdarch_powerpc", issue = "111145")] impl VectorRound for vector_float { From 9ea3034b584962c763d970d49b897e69dadf1061 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 31 Jan 2026 17:15:16 +0100 Subject: [PATCH 11/47] powerpc: implement `vnmsubfp` using `intrinsics::simd` --- .../stdarch/crates/core_arch/src/powerpc/altivec.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index fb1a9d8ed9e2c..9d54abc5833bc 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -129,8 +129,6 @@ unsafe extern "C" { b: vector_signed_short, c: vector_signed_int, ) -> vector_signed_int; - #[link_name = "llvm.ppc.altivec.vnmsubfp"] - fn vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float; #[link_name = "llvm.ppc.altivec.vsum2sws"] fn vsum2sws(a: vector_signed_int, b: vector_signed_int) -> vector_signed_int; #[link_name = "llvm.ppc.altivec.vsum4ubs"] @@ -1881,9 +1879,9 @@ mod sealed { #[inline] #[target_feature(enable = "altivec")] - #[cfg_attr(test, assert_instr(vnmsubfp))] - unsafe fn vec_vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float { - vnmsubfp(a, b, c) + #[cfg_attr(test, assert_instr(xvnmsubasp))] + pub unsafe fn vec_vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float { + simd_neg(simd_fma(a, b, simd_neg(c))) } #[inline] @@ -4281,7 +4279,7 @@ pub unsafe fn vec_madd(a: vector_float, b: vector_float, c: vector_float) -> vec #[target_feature(enable = "altivec")] #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub unsafe fn vec_nmsub(a: vector_float, b: vector_float, c: vector_float) -> vector_float { - vnmsubfp(a, b, c) + sealed::vec_vnmsubfp(a, b, c) } /// Vector Select From ebc618aab5f6476b215f2b908cbf919765534f6d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 31 Jan 2026 18:47:56 +0100 Subject: [PATCH 12/47] wasm: use `intrinsics::simd` for the narrow functions --- .../crates/core_arch/src/wasm32/simd128.rs | 72 +++++++++++++++---- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs index c864d6a516e08..e1a3754965907 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs @@ -86,10 +86,6 @@ unsafe extern "unadjusted" { fn llvm_i8x16_all_true(x: simd::i8x16) -> i32; #[link_name = "llvm.wasm.bitmask.v16i8"] fn llvm_bitmask_i8x16(a: simd::i8x16) -> i32; - #[link_name = "llvm.wasm.narrow.signed.v16i8.v8i16"] - fn llvm_narrow_i8x16_s(a: simd::i16x8, b: simd::i16x8) -> simd::i8x16; - #[link_name = "llvm.wasm.narrow.unsigned.v16i8.v8i16"] - fn llvm_narrow_i8x16_u(a: simd::i16x8, b: simd::i16x8) -> simd::i8x16; #[link_name = "llvm.wasm.avgr.unsigned.v16i8"] fn llvm_avgr_u_i8x16(a: simd::i8x16, b: simd::i8x16) -> simd::i8x16; @@ -103,10 +99,6 @@ unsafe extern "unadjusted" { fn llvm_i16x8_all_true(x: simd::i16x8) -> i32; #[link_name = "llvm.wasm.bitmask.v8i16"] fn llvm_bitmask_i16x8(a: simd::i16x8) -> i32; - #[link_name = "llvm.wasm.narrow.signed.v8i16.v4i32"] - fn llvm_narrow_i16x8_s(a: simd::i32x4, b: simd::i32x4) -> simd::i16x8; - #[link_name = "llvm.wasm.narrow.unsigned.v8i16.v4i32"] - fn llvm_narrow_i16x8_u(a: simd::i32x4, b: simd::i32x4) -> simd::i16x8; #[link_name = "llvm.wasm.avgr.unsigned.v8i16"] fn llvm_avgr_u_i16x8(a: simd::i16x8, b: simd::i16x8) -> simd::i16x8; @@ -2281,7 +2273,23 @@ pub use i8x16_bitmask as u8x16_bitmask; #[doc(alias("i8x16.narrow_i16x8_s"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn i8x16_narrow_i16x8(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i8x16_s(a.as_i16x8(), b.as_i16x8()).v128() } + unsafe { + let v: simd::i16x16 = simd_shuffle!( + a.as_i16x8(), + b.as_i16x8(), + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + ); + + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); + + let v = simd_select(simd_gt::<_, simd::i16x16>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i16x16>(v, min), min, v); + + let v: simd::i8x16 = simd_cast(v); + + v.v128() + } } /// Converts two input vectors into a smaller lane vector by narrowing each @@ -2295,7 +2303,23 @@ pub fn i8x16_narrow_i16x8(a: v128, b: v128) -> v128 { #[doc(alias("i8x16.narrow_i16x8_u"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn u8x16_narrow_i16x8(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i8x16_u(a.as_i16x8(), b.as_i16x8()).v128() } + unsafe { + let v: simd::i16x16 = simd_shuffle!( + a.as_i16x8(), + b.as_i16x8(), + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + ); + + let max = simd_splat(i16::from(u8::MAX)); + let min = simd_splat(i16::from(u8::MIN)); + + let v = simd_select(simd_gt::<_, simd::i16x16>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i16x16>(v, min), min, v); + + let v: simd::u8x16 = simd_cast(v); + + v.v128() + } } /// Shifts each lane to the left by the specified number of bits. @@ -2593,7 +2617,19 @@ pub use i16x8_bitmask as u16x8_bitmask; #[doc(alias("i16x8.narrow_i32x4_s"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn i16x8_narrow_i32x4(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i16x8_s(a.as_i32x4(), b.as_i32x4()).v128() } + unsafe { + let v: simd::i32x8 = simd_shuffle!(a, b, [0, 1, 2, 3, 4, 5, 6, 7]); + + let max = simd_splat(i32::from(i16::MAX)); + let min = simd_splat(i32::from(i16::MIN)); + + let v = simd_select(simd_gt::<_, simd::i32x8>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i32x8>(v, min), min, v); + + let v: simd::i16x8 = simd_cast(v); + + v.v128() + } } /// Converts two input vectors into a smaller lane vector by narrowing each @@ -2607,7 +2643,19 @@ pub fn i16x8_narrow_i32x4(a: v128, b: v128) -> v128 { #[doc(alias("i16x8.narrow_i32x4_u"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn u16x8_narrow_i32x4(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i16x8_u(a.as_i32x4(), b.as_i32x4()).v128() } + unsafe { + let v: simd::i32x8 = simd_shuffle!(a, b, [0, 1, 2, 3, 4, 5, 6, 7]); + + let max = simd_splat(i32::from(u16::MAX)); + let min = simd_splat(i32::from(u16::MIN)); + + let v = simd_select(simd_gt::<_, simd::i32x8>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i32x8>(v, min), min, v); + + let v: simd::u16x8 = simd_cast(v); + + v.v128() + } } /// Converts low half of the smaller lane vector to a larger lane From e40ae4fe2c8f0b08265d0a40a59a55f46c65e865 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 31 Jan 2026 22:11:50 +0100 Subject: [PATCH 13/47] x86: use `intrinsics::simd` for `hadds`/`hsubs` --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 36 +++++++++++++++---- .../stdarch/crates/core_arch/src/x86/ssse3.rs | 22 +++++++----- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 6a39a0aaf8feb..83aef753c9d93 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -991,7 +991,21 @@ pub const fn _mm256_hadd_epi32(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vphaddsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_hadds_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { transmute(phaddsw(a.as_i16x16(), b.as_i16x16())) } + let a = a.as_i16x16(); + let b = b.as_i16x16(); + unsafe { + let even: i16x16 = simd_shuffle!( + a, + b, + [0, 2, 4, 6, 16, 18, 20, 22, 8, 10, 12, 14, 24, 26, 28, 30] + ); + let odd: i16x16 = simd_shuffle!( + a, + b, + [1, 3, 5, 7, 17, 19, 21, 23, 9, 11, 13, 15, 25, 27, 29, 31] + ); + simd_saturating_add(even, odd).as_m256i() + } } /// Horizontally subtract adjacent pairs of 16-bit integers in `a` and `b`. @@ -1047,7 +1061,21 @@ pub const fn _mm256_hsub_epi32(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vphsubsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_hsubs_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { transmute(phsubsw(a.as_i16x16(), b.as_i16x16())) } + let a = a.as_i16x16(); + let b = b.as_i16x16(); + unsafe { + let even: i16x16 = simd_shuffle!( + a, + b, + [0, 2, 4, 6, 16, 18, 20, 22, 8, 10, 12, 14, 24, 26, 28, 30] + ); + let odd: i16x16 = simd_shuffle!( + a, + b, + [1, 3, 5, 7, 17, 19, 21, 23, 9, 11, 13, 15, 25, 27, 29, 31] + ); + simd_saturating_sub(even, odd).as_m256i() + } } /// Returns values from `slice` at offsets determined by `offsets * scale`, @@ -3791,10 +3819,6 @@ pub const fn _mm256_extract_epi16(a: __m256i) -> i32 { #[allow(improper_ctypes)] unsafe extern "C" { - #[link_name = "llvm.x86.avx2.phadd.sw"] - fn phaddsw(a: i16x16, b: i16x16) -> i16x16; - #[link_name = "llvm.x86.avx2.phsub.sw"] - fn phsubsw(a: i16x16, b: i16x16) -> i16x16; #[link_name = "llvm.x86.avx2.pmadd.wd"] fn pmaddwd(a: i16x16, b: i16x16) -> i32x8; #[link_name = "llvm.x86.avx2.pmadd.ub.sw"] diff --git a/library/stdarch/crates/core_arch/src/x86/ssse3.rs b/library/stdarch/crates/core_arch/src/x86/ssse3.rs index 4426a3274c380..1d7a97944a37b 100644 --- a/library/stdarch/crates/core_arch/src/x86/ssse3.rs +++ b/library/stdarch/crates/core_arch/src/x86/ssse3.rs @@ -188,7 +188,13 @@ pub const fn _mm_hadd_epi16(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(phaddsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_hadds_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { transmute(phaddsw128(a.as_i16x8(), b.as_i16x8())) } + let a = a.as_i16x8(); + let b = b.as_i16x8(); + unsafe { + let even: i16x8 = simd_shuffle!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let odd: i16x8 = simd_shuffle!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + simd_saturating_add(even, odd).as_m128i() + } } /// Horizontally adds the adjacent pairs of values contained in 2 packed @@ -240,7 +246,13 @@ pub const fn _mm_hsub_epi16(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(phsubsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_hsubs_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { transmute(phsubsw128(a.as_i16x8(), b.as_i16x8())) } + let a = a.as_i16x8(); + let b = b.as_i16x8(); + unsafe { + let even: i16x8 = simd_shuffle!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let odd: i16x8 = simd_shuffle!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + simd_saturating_sub(even, odd).as_m128i() + } } /// Horizontally subtract the adjacent pairs of values contained in 2 @@ -337,12 +349,6 @@ unsafe extern "C" { #[link_name = "llvm.x86.ssse3.pshuf.b.128"] fn pshufb128(a: u8x16, b: u8x16) -> u8x16; - #[link_name = "llvm.x86.ssse3.phadd.sw.128"] - fn phaddsw128(a: i16x8, b: i16x8) -> i16x8; - - #[link_name = "llvm.x86.ssse3.phsub.sw.128"] - fn phsubsw128(a: i16x8, b: i16x8) -> i16x8; - #[link_name = "llvm.x86.ssse3.pmadd.ub.sw.128"] fn pmaddubsw128(a: u8x16, b: i8x16) -> i16x8; From 24a28332582ac25470c20079f0fdacf2c2e1b871 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 30 Jan 2026 20:22:18 +0100 Subject: [PATCH 14/47] test the `vld1*` functions --- .../crates/core_arch/src/aarch64/neon/mod.rs | 864 ++++++++++++++++++ 1 file changed, 864 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index bac45742393cb..feaf94a7f9e01 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -993,6 +993,870 @@ mod tests { assert_eq!(vals[1], 1.); assert_eq!(vals[2], 2.); } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1_f16_x2() { + let vals: [f16; 8] = crate::array::from_fn(|i| i as f16); + let a: float16x4x2_t = transmute(vals); + let mut tmp = [0_f16; 8]; + vst1_f16_x2(tmp.as_mut_ptr().cast(), a); + let r: float16x4x2_t = vld1_f16_x2(tmp.as_ptr().cast()); + let out: [f16; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1_f16_x3() { + let vals: [f16; 12] = crate::array::from_fn(|i| i as f16); + let a: float16x4x3_t = transmute(vals); + let mut tmp = [0_f16; 12]; + vst1_f16_x3(tmp.as_mut_ptr().cast(), a); + let r: float16x4x3_t = vld1_f16_x3(tmp.as_ptr().cast()); + let out: [f16; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1_f16_x4() { + let vals: [f16; 16] = crate::array::from_fn(|i| i as f16); + let a: float16x4x4_t = transmute(vals); + let mut tmp = [0_f16; 16]; + vst1_f16_x4(tmp.as_mut_ptr().cast(), a); + let r: float16x4x4_t = vld1_f16_x4(tmp.as_ptr().cast()); + let out: [f16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1q_f16_x2() { + let vals: [f16; 16] = crate::array::from_fn(|i| i as f16); + let a: float16x8x2_t = transmute(vals); + let mut tmp = [0_f16; 16]; + vst1q_f16_x2(tmp.as_mut_ptr().cast(), a); + let r: float16x8x2_t = vld1q_f16_x2(tmp.as_ptr().cast()); + let out: [f16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1q_f16_x3() { + let vals: [f16; 24] = crate::array::from_fn(|i| i as f16); + let a: float16x8x3_t = transmute(vals); + let mut tmp = [0_f16; 24]; + vst1q_f16_x3(tmp.as_mut_ptr().cast(), a); + let r: float16x8x3_t = vld1q_f16_x3(tmp.as_ptr().cast()); + let out: [f16; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1q_f16_x4() { + let vals: [f16; 32] = crate::array::from_fn(|i| i as f16); + let a: float16x8x4_t = transmute(vals); + let mut tmp = [0_f16; 32]; + vst1q_f16_x4(tmp.as_mut_ptr().cast(), a); + let r: float16x8x4_t = vld1q_f16_x4(tmp.as_ptr().cast()); + let out: [f16; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_f32_x2() { + let vals: [f32; 4] = crate::array::from_fn(|i| i as f32); + let a: float32x2x2_t = transmute(vals); + let mut tmp = [0_f32; 4]; + vst1_f32_x2(tmp.as_mut_ptr().cast(), a); + let r: float32x2x2_t = vld1_f32_x2(tmp.as_ptr().cast()); + let out: [f32; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_f32_x3() { + let vals: [f32; 6] = crate::array::from_fn(|i| i as f32); + let a: float32x2x3_t = transmute(vals); + let mut tmp = [0_f32; 6]; + vst1_f32_x3(tmp.as_mut_ptr().cast(), a); + let r: float32x2x3_t = vld1_f32_x3(tmp.as_ptr().cast()); + let out: [f32; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_f32_x4() { + let vals: [f32; 8] = crate::array::from_fn(|i| i as f32); + let a: float32x2x4_t = transmute(vals); + let mut tmp = [0_f32; 8]; + vst1_f32_x4(tmp.as_mut_ptr().cast(), a); + let r: float32x2x4_t = vld1_f32_x4(tmp.as_ptr().cast()); + let out: [f32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_f32_x2() { + let vals: [f32; 8] = crate::array::from_fn(|i| i as f32); + let a: float32x4x2_t = transmute(vals); + let mut tmp = [0_f32; 8]; + vst1q_f32_x2(tmp.as_mut_ptr().cast(), a); + let r: float32x4x2_t = vld1q_f32_x2(tmp.as_ptr().cast()); + let out: [f32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_f32_x3() { + let vals: [f32; 12] = crate::array::from_fn(|i| i as f32); + let a: float32x4x3_t = transmute(vals); + let mut tmp = [0_f32; 12]; + vst1q_f32_x3(tmp.as_mut_ptr().cast(), a); + let r: float32x4x3_t = vld1q_f32_x3(tmp.as_ptr().cast()); + let out: [f32; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_f32_x4() { + let vals: [f32; 16] = crate::array::from_fn(|i| i as f32); + let a: float32x4x4_t = transmute(vals); + let mut tmp = [0_f32; 16]; + vst1q_f32_x4(tmp.as_mut_ptr().cast(), a); + let r: float32x4x4_t = vld1q_f32_x4(tmp.as_ptr().cast()); + let out: [f32; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1_p64_x2() { + let vals: [p64; 2] = crate::array::from_fn(|i| i as p64); + let a: poly64x1x2_t = transmute(vals); + let mut tmp = [0 as p64; 2]; + vst1_p64_x2(tmp.as_mut_ptr().cast(), a); + let r: poly64x1x2_t = vld1_p64_x2(tmp.as_ptr().cast()); + let out: [p64; 2] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1_p64_x3() { + let vals: [p64; 3] = crate::array::from_fn(|i| i as p64); + let a: poly64x1x3_t = transmute(vals); + let mut tmp = [0 as p64; 3]; + vst1_p64_x3(tmp.as_mut_ptr().cast(), a); + let r: poly64x1x3_t = vld1_p64_x3(tmp.as_ptr().cast()); + let out: [p64; 3] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1_p64_x4() { + let vals: [p64; 4] = crate::array::from_fn(|i| i as p64); + let a: poly64x1x4_t = transmute(vals); + let mut tmp = [0 as p64; 4]; + vst1_p64_x4(tmp.as_mut_ptr().cast(), a); + let r: poly64x1x4_t = vld1_p64_x4(tmp.as_ptr().cast()); + let out: [p64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1q_p64_x2() { + let vals: [p64; 4] = crate::array::from_fn(|i| i as p64); + let a: poly64x2x2_t = transmute(vals); + let mut tmp = [0 as p64; 4]; + vst1q_p64_x2(tmp.as_mut_ptr().cast(), a); + let r: poly64x2x2_t = vld1q_p64_x2(tmp.as_ptr().cast()); + let out: [p64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1q_p64_x3() { + let vals: [p64; 6] = crate::array::from_fn(|i| i as p64); + let a: poly64x2x3_t = transmute(vals); + let mut tmp = [0 as p64; 6]; + vst1q_p64_x3(tmp.as_mut_ptr().cast(), a); + let r: poly64x2x3_t = vld1q_p64_x3(tmp.as_ptr().cast()); + let out: [p64; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1q_p64_x4() { + let vals: [p64; 8] = crate::array::from_fn(|i| i as p64); + let a: poly64x2x4_t = transmute(vals); + let mut tmp = [0 as p64; 8]; + vst1q_p64_x4(tmp.as_mut_ptr().cast(), a); + let r: poly64x2x4_t = vld1q_p64_x4(tmp.as_ptr().cast()); + let out: [p64; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s8_x2() { + let vals: [i8; 16] = crate::array::from_fn(|i| i as i8); + let a: int8x8x2_t = transmute(vals); + let mut tmp = [0_i8; 16]; + vst1_s8_x2(tmp.as_mut_ptr().cast(), a); + let r: int8x8x2_t = vld1_s8_x2(tmp.as_ptr().cast()); + let out: [i8; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s8_x3() { + let vals: [i8; 24] = crate::array::from_fn(|i| i as i8); + let a: int8x8x3_t = transmute(vals); + let mut tmp = [0_i8; 24]; + vst1_s8_x3(tmp.as_mut_ptr().cast(), a); + let r: int8x8x3_t = vld1_s8_x3(tmp.as_ptr().cast()); + let out: [i8; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s8_x4() { + let vals: [i8; 32] = crate::array::from_fn(|i| i as i8); + let a: int8x8x4_t = transmute(vals); + let mut tmp = [0_i8; 32]; + vst1_s8_x4(tmp.as_mut_ptr().cast(), a); + let r: int8x8x4_t = vld1_s8_x4(tmp.as_ptr().cast()); + let out: [i8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s8_x2() { + let vals: [i8; 32] = crate::array::from_fn(|i| i as i8); + let a: int8x16x2_t = transmute(vals); + let mut tmp = [0_i8; 32]; + vst1q_s8_x2(tmp.as_mut_ptr().cast(), a); + let r: int8x16x2_t = vld1q_s8_x2(tmp.as_ptr().cast()); + let out: [i8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s8_x3() { + let vals: [i8; 48] = crate::array::from_fn(|i| i as i8); + let a: int8x16x3_t = transmute(vals); + let mut tmp = [0_i8; 48]; + vst1q_s8_x3(tmp.as_mut_ptr().cast(), a); + let r: int8x16x3_t = vld1q_s8_x3(tmp.as_ptr().cast()); + let out: [i8; 48] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s8_x4() { + let vals: [i8; 64] = crate::array::from_fn(|i| i as i8); + let a: int8x16x4_t = transmute(vals); + let mut tmp = [0_i8; 64]; + vst1q_s8_x4(tmp.as_mut_ptr().cast(), a); + let r: int8x16x4_t = vld1q_s8_x4(tmp.as_ptr().cast()); + let out: [i8; 64] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s16_x2() { + let vals: [i16; 8] = crate::array::from_fn(|i| i as i16); + let a: int16x4x2_t = transmute(vals); + let mut tmp = [0_i16; 8]; + vst1_s16_x2(tmp.as_mut_ptr().cast(), a); + let r: int16x4x2_t = vld1_s16_x2(tmp.as_ptr().cast()); + let out: [i16; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s16_x3() { + let vals: [i16; 12] = crate::array::from_fn(|i| i as i16); + let a: int16x4x3_t = transmute(vals); + let mut tmp = [0_i16; 12]; + vst1_s16_x3(tmp.as_mut_ptr().cast(), a); + let r: int16x4x3_t = vld1_s16_x3(tmp.as_ptr().cast()); + let out: [i16; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s16_x4() { + let vals: [i16; 16] = crate::array::from_fn(|i| i as i16); + let a: int16x4x4_t = transmute(vals); + let mut tmp = [0_i16; 16]; + vst1_s16_x4(tmp.as_mut_ptr().cast(), a); + let r: int16x4x4_t = vld1_s16_x4(tmp.as_ptr().cast()); + let out: [i16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s16_x2() { + let vals: [i16; 16] = crate::array::from_fn(|i| i as i16); + let a: int16x8x2_t = transmute(vals); + let mut tmp = [0_i16; 16]; + vst1q_s16_x2(tmp.as_mut_ptr().cast(), a); + let r: int16x8x2_t = vld1q_s16_x2(tmp.as_ptr().cast()); + let out: [i16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s16_x3() { + let vals: [i16; 24] = crate::array::from_fn(|i| i as i16); + let a: int16x8x3_t = transmute(vals); + let mut tmp = [0_i16; 24]; + vst1q_s16_x3(tmp.as_mut_ptr().cast(), a); + let r: int16x8x3_t = vld1q_s16_x3(tmp.as_ptr().cast()); + let out: [i16; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s16_x4() { + let vals: [i16; 32] = crate::array::from_fn(|i| i as i16); + let a: int16x8x4_t = transmute(vals); + let mut tmp = [0_i16; 32]; + vst1q_s16_x4(tmp.as_mut_ptr().cast(), a); + let r: int16x8x4_t = vld1q_s16_x4(tmp.as_ptr().cast()); + let out: [i16; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s32_x2() { + let vals: [i32; 4] = crate::array::from_fn(|i| i as i32); + let a: int32x2x2_t = transmute(vals); + let mut tmp = [0_i32; 4]; + vst1_s32_x2(tmp.as_mut_ptr().cast(), a); + let r: int32x2x2_t = vld1_s32_x2(tmp.as_ptr().cast()); + let out: [i32; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s32_x3() { + let vals: [i32; 6] = crate::array::from_fn(|i| i as i32); + let a: int32x2x3_t = transmute(vals); + let mut tmp = [0_i32; 6]; + vst1_s32_x3(tmp.as_mut_ptr().cast(), a); + let r: int32x2x3_t = vld1_s32_x3(tmp.as_ptr().cast()); + let out: [i32; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s32_x4() { + let vals: [i32; 8] = crate::array::from_fn(|i| i as i32); + let a: int32x2x4_t = transmute(vals); + let mut tmp = [0_i32; 8]; + vst1_s32_x4(tmp.as_mut_ptr().cast(), a); + let r: int32x2x4_t = vld1_s32_x4(tmp.as_ptr().cast()); + let out: [i32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s32_x2() { + let vals: [i32; 8] = crate::array::from_fn(|i| i as i32); + let a: int32x4x2_t = transmute(vals); + let mut tmp = [0_i32; 8]; + vst1q_s32_x2(tmp.as_mut_ptr().cast(), a); + let r: int32x4x2_t = vld1q_s32_x2(tmp.as_ptr().cast()); + let out: [i32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s32_x3() { + let vals: [i32; 12] = crate::array::from_fn(|i| i as i32); + let a: int32x4x3_t = transmute(vals); + let mut tmp = [0_i32; 12]; + vst1q_s32_x3(tmp.as_mut_ptr().cast(), a); + let r: int32x4x3_t = vld1q_s32_x3(tmp.as_ptr().cast()); + let out: [i32; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s32_x4() { + let vals: [i32; 16] = crate::array::from_fn(|i| i as i32); + let a: int32x4x4_t = transmute(vals); + let mut tmp = [0_i32; 16]; + vst1q_s32_x4(tmp.as_mut_ptr().cast(), a); + let r: int32x4x4_t = vld1q_s32_x4(tmp.as_ptr().cast()); + let out: [i32; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s64_x2() { + let vals: [i64; 2] = crate::array::from_fn(|i| i as i64); + let a: int64x1x2_t = transmute(vals); + let mut tmp = [0_i64; 2]; + vst1_s64_x2(tmp.as_mut_ptr().cast(), a); + let r: int64x1x2_t = vld1_s64_x2(tmp.as_ptr().cast()); + let out: [i64; 2] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s64_x3() { + let vals: [i64; 3] = crate::array::from_fn(|i| i as i64); + let a: int64x1x3_t = transmute(vals); + let mut tmp = [0_i64; 3]; + vst1_s64_x3(tmp.as_mut_ptr().cast(), a); + let r: int64x1x3_t = vld1_s64_x3(tmp.as_ptr().cast()); + let out: [i64; 3] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s64_x4() { + let vals: [i64; 4] = crate::array::from_fn(|i| i as i64); + let a: int64x1x4_t = transmute(vals); + let mut tmp = [0_i64; 4]; + vst1_s64_x4(tmp.as_mut_ptr().cast(), a); + let r: int64x1x4_t = vld1_s64_x4(tmp.as_ptr().cast()); + let out: [i64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s64_x2() { + let vals: [i64; 4] = crate::array::from_fn(|i| i as i64); + let a: int64x2x2_t = transmute(vals); + let mut tmp = [0_i64; 4]; + vst1q_s64_x2(tmp.as_mut_ptr().cast(), a); + let r: int64x2x2_t = vld1q_s64_x2(tmp.as_ptr().cast()); + let out: [i64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s64_x3() { + let vals: [i64; 6] = crate::array::from_fn(|i| i as i64); + let a: int64x2x3_t = transmute(vals); + let mut tmp = [0_i64; 6]; + vst1q_s64_x3(tmp.as_mut_ptr().cast(), a); + let r: int64x2x3_t = vld1q_s64_x3(tmp.as_ptr().cast()); + let out: [i64; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s64_x4() { + let vals: [i64; 8] = crate::array::from_fn(|i| i as i64); + let a: int64x2x4_t = transmute(vals); + let mut tmp = [0_i64; 8]; + vst1q_s64_x4(tmp.as_mut_ptr().cast(), a); + let r: int64x2x4_t = vld1q_s64_x4(tmp.as_ptr().cast()); + let out: [i64; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u8_x2() { + let vals: [u8; 16] = crate::array::from_fn(|i| i as u8); + let a: uint8x8x2_t = transmute(vals); + let mut tmp = [0_u8; 16]; + vst1_u8_x2(tmp.as_mut_ptr().cast(), a); + let r: uint8x8x2_t = vld1_u8_x2(tmp.as_ptr().cast()); + let out: [u8; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u8_x3() { + let vals: [u8; 24] = crate::array::from_fn(|i| i as u8); + let a: uint8x8x3_t = transmute(vals); + let mut tmp = [0_u8; 24]; + vst1_u8_x3(tmp.as_mut_ptr().cast(), a); + let r: uint8x8x3_t = vld1_u8_x3(tmp.as_ptr().cast()); + let out: [u8; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u8_x4() { + let vals: [u8; 32] = crate::array::from_fn(|i| i as u8); + let a: uint8x8x4_t = transmute(vals); + let mut tmp = [0_u8; 32]; + vst1_u8_x4(tmp.as_mut_ptr().cast(), a); + let r: uint8x8x4_t = vld1_u8_x4(tmp.as_ptr().cast()); + let out: [u8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u8_x2() { + let vals: [u8; 32] = crate::array::from_fn(|i| i as u8); + let a: uint8x16x2_t = transmute(vals); + let mut tmp = [0_u8; 32]; + vst1q_u8_x2(tmp.as_mut_ptr().cast(), a); + let r: uint8x16x2_t = vld1q_u8_x2(tmp.as_ptr().cast()); + let out: [u8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u8_x3() { + let vals: [u8; 48] = crate::array::from_fn(|i| i as u8); + let a: uint8x16x3_t = transmute(vals); + let mut tmp = [0_u8; 48]; + vst1q_u8_x3(tmp.as_mut_ptr().cast(), a); + let r: uint8x16x3_t = vld1q_u8_x3(tmp.as_ptr().cast()); + let out: [u8; 48] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u8_x4() { + let vals: [u8; 64] = crate::array::from_fn(|i| i as u8); + let a: uint8x16x4_t = transmute(vals); + let mut tmp = [0_u8; 64]; + vst1q_u8_x4(tmp.as_mut_ptr().cast(), a); + let r: uint8x16x4_t = vld1q_u8_x4(tmp.as_ptr().cast()); + let out: [u8; 64] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u16_x2() { + let vals: [u16; 8] = crate::array::from_fn(|i| i as u16); + let a: uint16x4x2_t = transmute(vals); + let mut tmp = [0_u16; 8]; + vst1_u16_x2(tmp.as_mut_ptr().cast(), a); + let r: uint16x4x2_t = vld1_u16_x2(tmp.as_ptr().cast()); + let out: [u16; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u16_x3() { + let vals: [u16; 12] = crate::array::from_fn(|i| i as u16); + let a: uint16x4x3_t = transmute(vals); + let mut tmp = [0_u16; 12]; + vst1_u16_x3(tmp.as_mut_ptr().cast(), a); + let r: uint16x4x3_t = vld1_u16_x3(tmp.as_ptr().cast()); + let out: [u16; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u16_x4() { + let vals: [u16; 16] = crate::array::from_fn(|i| i as u16); + let a: uint16x4x4_t = transmute(vals); + let mut tmp = [0_u16; 16]; + vst1_u16_x4(tmp.as_mut_ptr().cast(), a); + let r: uint16x4x4_t = vld1_u16_x4(tmp.as_ptr().cast()); + let out: [u16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u16_x2() { + let vals: [u16; 16] = crate::array::from_fn(|i| i as u16); + let a: uint16x8x2_t = transmute(vals); + let mut tmp = [0_u16; 16]; + vst1q_u16_x2(tmp.as_mut_ptr().cast(), a); + let r: uint16x8x2_t = vld1q_u16_x2(tmp.as_ptr().cast()); + let out: [u16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u16_x3() { + let vals: [u16; 24] = crate::array::from_fn(|i| i as u16); + let a: uint16x8x3_t = transmute(vals); + let mut tmp = [0_u16; 24]; + vst1q_u16_x3(tmp.as_mut_ptr().cast(), a); + let r: uint16x8x3_t = vld1q_u16_x3(tmp.as_ptr().cast()); + let out: [u16; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u16_x4() { + let vals: [u16; 32] = crate::array::from_fn(|i| i as u16); + let a: uint16x8x4_t = transmute(vals); + let mut tmp = [0_u16; 32]; + vst1q_u16_x4(tmp.as_mut_ptr().cast(), a); + let r: uint16x8x4_t = vld1q_u16_x4(tmp.as_ptr().cast()); + let out: [u16; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u32_x2() { + let vals: [u32; 4] = crate::array::from_fn(|i| i as u32); + let a: uint32x2x2_t = transmute(vals); + let mut tmp = [0_u32; 4]; + vst1_u32_x2(tmp.as_mut_ptr().cast(), a); + let r: uint32x2x2_t = vld1_u32_x2(tmp.as_ptr().cast()); + let out: [u32; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u32_x3() { + let vals: [u32; 6] = crate::array::from_fn(|i| i as u32); + let a: uint32x2x3_t = transmute(vals); + let mut tmp = [0_u32; 6]; + vst1_u32_x3(tmp.as_mut_ptr().cast(), a); + let r: uint32x2x3_t = vld1_u32_x3(tmp.as_ptr().cast()); + let out: [u32; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u32_x4() { + let vals: [u32; 8] = crate::array::from_fn(|i| i as u32); + let a: uint32x2x4_t = transmute(vals); + let mut tmp = [0_u32; 8]; + vst1_u32_x4(tmp.as_mut_ptr().cast(), a); + let r: uint32x2x4_t = vld1_u32_x4(tmp.as_ptr().cast()); + let out: [u32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u32_x2() { + let vals: [u32; 8] = crate::array::from_fn(|i| i as u32); + let a: uint32x4x2_t = transmute(vals); + let mut tmp = [0_u32; 8]; + vst1q_u32_x2(tmp.as_mut_ptr().cast(), a); + let r: uint32x4x2_t = vld1q_u32_x2(tmp.as_ptr().cast()); + let out: [u32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u32_x3() { + let vals: [u32; 12] = crate::array::from_fn(|i| i as u32); + let a: uint32x4x3_t = transmute(vals); + let mut tmp = [0_u32; 12]; + vst1q_u32_x3(tmp.as_mut_ptr().cast(), a); + let r: uint32x4x3_t = vld1q_u32_x3(tmp.as_ptr().cast()); + let out: [u32; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u32_x4() { + let vals: [u32; 16] = crate::array::from_fn(|i| i as u32); + let a: uint32x4x4_t = transmute(vals); + let mut tmp = [0_u32; 16]; + vst1q_u32_x4(tmp.as_mut_ptr().cast(), a); + let r: uint32x4x4_t = vld1q_u32_x4(tmp.as_ptr().cast()); + let out: [u32; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u64_x2() { + let vals: [u64; 2] = crate::array::from_fn(|i| i as u64); + let a: uint64x1x2_t = transmute(vals); + let mut tmp = [0_u64; 2]; + vst1_u64_x2(tmp.as_mut_ptr().cast(), a); + let r: uint64x1x2_t = vld1_u64_x2(tmp.as_ptr().cast()); + let out: [u64; 2] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u64_x3() { + let vals: [u64; 3] = crate::array::from_fn(|i| i as u64); + let a: uint64x1x3_t = transmute(vals); + let mut tmp = [0_u64; 3]; + vst1_u64_x3(tmp.as_mut_ptr().cast(), a); + let r: uint64x1x3_t = vld1_u64_x3(tmp.as_ptr().cast()); + let out: [u64; 3] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u64_x4() { + let vals: [u64; 4] = crate::array::from_fn(|i| i as u64); + let a: uint64x1x4_t = transmute(vals); + let mut tmp = [0_u64; 4]; + vst1_u64_x4(tmp.as_mut_ptr().cast(), a); + let r: uint64x1x4_t = vld1_u64_x4(tmp.as_ptr().cast()); + let out: [u64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u64_x2() { + let vals: [u64; 4] = crate::array::from_fn(|i| i as u64); + let a: uint64x2x2_t = transmute(vals); + let mut tmp = [0_u64; 4]; + vst1q_u64_x2(tmp.as_mut_ptr().cast(), a); + let r: uint64x2x2_t = vld1q_u64_x2(tmp.as_ptr().cast()); + let out: [u64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u64_x3() { + let vals: [u64; 6] = crate::array::from_fn(|i| i as u64); + let a: uint64x2x3_t = transmute(vals); + let mut tmp = [0_u64; 6]; + vst1q_u64_x3(tmp.as_mut_ptr().cast(), a); + let r: uint64x2x3_t = vld1q_u64_x3(tmp.as_ptr().cast()); + let out: [u64; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u64_x4() { + let vals: [u64; 8] = crate::array::from_fn(|i| i as u64); + let a: uint64x2x4_t = transmute(vals); + let mut tmp = [0_u64; 8]; + vst1q_u64_x4(tmp.as_mut_ptr().cast(), a); + let r: uint64x2x4_t = vld1q_u64_x4(tmp.as_ptr().cast()); + let out: [u64; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p8_x2() { + let vals: [p8; 16] = crate::array::from_fn(|i| i as p8); + let a: poly8x8x2_t = transmute(vals); + let mut tmp = [0 as p8; 16]; + vst1_p8_x2(tmp.as_mut_ptr().cast(), a); + let r: poly8x8x2_t = vld1_p8_x2(tmp.as_ptr().cast()); + let out: [p8; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p8_x3() { + let vals: [p8; 24] = crate::array::from_fn(|i| i as p8); + let a: poly8x8x3_t = transmute(vals); + let mut tmp = [0 as p8; 24]; + vst1_p8_x3(tmp.as_mut_ptr().cast(), a); + let r: poly8x8x3_t = vld1_p8_x3(tmp.as_ptr().cast()); + let out: [p8; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p8_x4() { + let vals: [p8; 32] = crate::array::from_fn(|i| i as p8); + let a: poly8x8x4_t = transmute(vals); + let mut tmp = [0 as p8; 32]; + vst1_p8_x4(tmp.as_mut_ptr().cast(), a); + let r: poly8x8x4_t = vld1_p8_x4(tmp.as_ptr().cast()); + let out: [p8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p8_x2() { + let vals: [p8; 32] = crate::array::from_fn(|i| i as p8); + let a: poly8x16x2_t = transmute(vals); + let mut tmp = [0 as p8; 32]; + vst1q_p8_x2(tmp.as_mut_ptr().cast(), a); + let r: poly8x16x2_t = vld1q_p8_x2(tmp.as_ptr().cast()); + let out: [p8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p8_x3() { + let vals: [p8; 48] = crate::array::from_fn(|i| i as p8); + let a: poly8x16x3_t = transmute(vals); + let mut tmp = [0 as p8; 48]; + vst1q_p8_x3(tmp.as_mut_ptr().cast(), a); + let r: poly8x16x3_t = vld1q_p8_x3(tmp.as_ptr().cast()); + let out: [p8; 48] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p8_x4() { + let vals: [p8; 64] = crate::array::from_fn(|i| i as p8); + let a: poly8x16x4_t = transmute(vals); + let mut tmp = [0 as p8; 64]; + vst1q_p8_x4(tmp.as_mut_ptr().cast(), a); + let r: poly8x16x4_t = vld1q_p8_x4(tmp.as_ptr().cast()); + let out: [p8; 64] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p16_x2() { + let vals: [p16; 8] = crate::array::from_fn(|i| i as p16); + let a: poly16x4x2_t = transmute(vals); + let mut tmp = [0 as p16; 8]; + vst1_p16_x2(tmp.as_mut_ptr().cast(), a); + let r: poly16x4x2_t = vld1_p16_x2(tmp.as_ptr().cast()); + let out: [p16; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p16_x3() { + let vals: [p16; 12] = crate::array::from_fn(|i| i as p16); + let a: poly16x4x3_t = transmute(vals); + let mut tmp = [0 as p16; 12]; + vst1_p16_x3(tmp.as_mut_ptr().cast(), a); + let r: poly16x4x3_t = vld1_p16_x3(tmp.as_ptr().cast()); + let out: [p16; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p16_x4() { + let vals: [p16; 16] = crate::array::from_fn(|i| i as p16); + let a: poly16x4x4_t = transmute(vals); + let mut tmp = [0 as p16; 16]; + vst1_p16_x4(tmp.as_mut_ptr().cast(), a); + let r: poly16x4x4_t = vld1_p16_x4(tmp.as_ptr().cast()); + let out: [p16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p16_x2() { + let vals: [p16; 16] = crate::array::from_fn(|i| i as p16); + let a: poly16x8x2_t = transmute(vals); + let mut tmp = [0 as p16; 16]; + vst1q_p16_x2(tmp.as_mut_ptr().cast(), a); + let r: poly16x8x2_t = vld1q_p16_x2(tmp.as_ptr().cast()); + let out: [p16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p16_x3() { + let vals: [p16; 24] = crate::array::from_fn(|i| i as p16); + let a: poly16x8x3_t = transmute(vals); + let mut tmp = [0 as p16; 24]; + vst1q_p16_x3(tmp.as_mut_ptr().cast(), a); + let r: poly16x8x3_t = vld1q_p16_x3(tmp.as_ptr().cast()); + let out: [p16; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p16_x4() { + let vals: [p16; 32] = crate::array::from_fn(|i| i as p16); + let a: poly16x8x4_t = transmute(vals); + let mut tmp = [0 as p16; 32]; + vst1q_p16_x4(tmp.as_mut_ptr().cast(), a); + let r: poly16x8x4_t = vld1q_p16_x4(tmp.as_ptr().cast()); + let out: [p16; 32] = transmute(r); + assert_eq!(out, vals); + } } #[cfg(test)] From a208e6c8874c471ffa1a3d96fc7dd8913798f4c9 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 30 Jan 2026 21:35:56 +0100 Subject: [PATCH 15/47] maybe fix aarch64be unsigned vector tuple loads --- .../src/arm_shared/neon/generated.rs | 1352 ++--------------- .../spec/neon/arm_shared.spec.yml | 2 + 2 files changed, 102 insertions(+), 1252 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 3b67208182cb0..2f52e3b52b07f 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -17067,7 +17067,6 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] @@ -17087,38 +17086,10 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { transmute(vld1q_s64_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { - let mut ret_val: poly64x2x2_t = transmute(vld1q_s64_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] @@ -17138,39 +17109,10 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { transmute(vld1q_s64_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { - let mut ret_val: poly64x2x3_t = transmute(vld1q_s64_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] @@ -17189,35 +17131,6 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { transmute(vld1q_s64_x4(transmute(a))) } -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { - let mut ret_val: poly64x2x4_t = transmute(vld1q_s64_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val -} #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s8)"] #[doc = "## Safety"] @@ -18071,7 +17984,6 @@ pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18091,11 +18003,10 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { transmute(vld1_s8_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18111,18 +18022,14 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { - let mut ret_val: uint8x8x2_t = transmute(vld1_s8_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { + transmute(vld1_s8_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18138,15 +18045,14 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { - transmute(vld1_s8_x3(transmute(a))) +pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { + transmute(vld1_s8_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18162,19 +18068,14 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { - let mut ret_val: uint8x8x3_t = transmute(vld1_s8_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { + transmute(vld1q_s8_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18190,15 +18091,14 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { - transmute(vld1_s8_x4(transmute(a))) +pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { + transmute(vld1q_s8_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18214,20 +18114,14 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { - let mut ret_val: uint8x8x4_t = transmute(vld1_s8_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { + transmute(vld1q_s8_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18243,15 +18137,14 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { - transmute(vld1q_s8_x2(transmute(a))) +pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { + transmute(vld1_s16_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18267,30 +18160,14 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { - let mut ret_val: uint8x16x2_t = transmute(vld1q_s8_x2(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val +pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { + transmute(vld1_s16_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18306,15 +18183,14 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { - transmute(vld1q_s8_x3(transmute(a))) +pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { + transmute(vld1_s16_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18330,37 +18206,14 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { - let mut ret_val: uint8x16x3_t = transmute(vld1q_s8_x3(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val +pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { + transmute(vld1q_s16_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18376,15 +18229,14 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { - transmute(vld1q_s8_x4(transmute(a))) +pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { + transmute(vld1q_s16_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18400,44 +18252,14 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { - let mut ret_val: uint8x16x4_t = transmute(vld1q_s8_x4(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.3 = unsafe { - simd_shuffle!( - ret_val.3, - ret_val.3, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val +pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { + transmute(vld1q_s16_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18453,15 +18275,14 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { - transmute(vld1_s16_x2(transmute(a))) +pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { + transmute(vld1_s32_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18477,18 +18298,14 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { - let mut ret_val: uint16x4x2_t = transmute(vld1_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { + transmute(vld1_s32_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18504,840 +18321,14 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { - transmute(vld1_s16_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { - let mut ret_val: uint16x4x3_t = transmute(vld1_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { - transmute(vld1_s16_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { - let mut ret_val: uint16x4x4_t = transmute(vld1_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { - transmute(vld1q_s16_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { - let mut ret_val: uint16x8x2_t = transmute(vld1q_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { - transmute(vld1q_s16_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { - let mut ret_val: uint16x8x3_t = transmute(vld1q_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { - transmute(vld1q_s16_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { - let mut ret_val: uint16x8x4_t = transmute(vld1q_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { - transmute(vld1_s32_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { - let mut ret_val: uint32x2x2_t = transmute(vld1_s32_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { - transmute(vld1_s32_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { - let mut ret_val: uint32x2x3_t = transmute(vld1_s32_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { - transmute(vld1_s32_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { - let mut ret_val: uint32x2x4_t = transmute(vld1_s32_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { - transmute(vld1q_s32_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { - let mut ret_val: uint32x4x2_t = transmute(vld1q_s32_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { - transmute(vld1q_s32_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { - let mut ret_val: uint32x4x3_t = transmute(vld1q_s32_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { - transmute(vld1q_s32_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { - let mut ret_val: uint32x4x4_t = transmute(vld1q_s32_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { - transmute(vld1_s64_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { - transmute(vld1_s64_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { - transmute(vld1_s64_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { - transmute(vld1q_s64_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { - let mut ret_val: uint64x2x2_t = transmute(vld1q_s64_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { - transmute(vld1q_s64_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { - let mut ret_val: uint64x2x3_t = transmute(vld1q_s64_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { - transmute(vld1q_s64_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { - let mut ret_val: uint64x2x4_t = transmute(vld1q_s64_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "little")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { - transmute(vld1_s8_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { - let mut ret_val: poly8x8x2_t = transmute(vld1_s8_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { + transmute(vld1_s32_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19353,15 +18344,14 @@ pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { - transmute(vld1_s8_x3(transmute(a))) +pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { + transmute(vld1q_s32_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19377,19 +18367,14 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { - let mut ret_val: poly8x8x3_t = transmute(vld1_s8_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { + transmute(vld1q_s32_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19405,15 +18390,14 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { - transmute(vld1_s8_x4(transmute(a))) +pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { + transmute(vld1q_s32_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19429,20 +18413,14 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { - let mut ret_val: poly8x8x4_t = transmute(vld1_s8_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { + transmute(vld1_s64_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19458,15 +18436,14 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { - transmute(vld1q_s8_x2(transmute(a))) +pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { + transmute(vld1_s64_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19482,30 +18459,14 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { - let mut ret_val: poly8x16x2_t = transmute(vld1q_s8_x2(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val +pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { + transmute(vld1_s64_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19521,15 +18482,14 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { - transmute(vld1q_s8_x3(transmute(a))) +pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { + transmute(vld1q_s64_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19545,37 +18505,14 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { - let mut ret_val: poly8x16x3_t = transmute(vld1q_s8_x3(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val +pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { + transmute(vld1q_s64_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19591,15 +18528,14 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { - transmute(vld1q_s8_x4(transmute(a))) +pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { + transmute(vld1q_s64_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19615,44 +18551,14 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { - let mut ret_val: poly8x16x4_t = transmute(vld1q_s8_x4(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.3 = unsafe { - simd_shuffle!( - ret_val.3, - ret_val.3, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val +pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { + transmute(vld1_s8_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19668,15 +18574,14 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { - transmute(vld1_s16_x2(transmute(a))) +pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { + transmute(vld1_s8_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19692,18 +18597,14 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { - let mut ret_val: poly16x4x2_t = transmute(vld1_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { + transmute(vld1_s8_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19719,15 +18620,14 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { - transmute(vld1_s16_x3(transmute(a))) +pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { + transmute(vld1q_s8_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19743,19 +18643,14 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { - let mut ret_val: poly16x4x3_t = transmute(vld1_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { + transmute(vld1q_s8_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19771,15 +18666,14 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { - transmute(vld1_s16_x4(transmute(a))) +pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { + transmute(vld1q_s8_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x4)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19795,20 +18689,14 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { - let mut ret_val: poly16x4x4_t = transmute(vld1_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { + transmute(vld1_s16_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19824,15 +18712,14 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { - transmute(vld1q_s16_x2(transmute(a))) +pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { + transmute(vld1_s16_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x2)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19848,18 +18735,14 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { - let mut ret_val: poly16x8x2_t = transmute(vld1q_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val +pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { + transmute(vld1_s16_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x3)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19875,15 +18758,14 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] -pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { - transmute(vld1q_s16_x3(transmute(a))) +pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { + transmute(vld1q_s16_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19900,18 +18782,13 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { - let mut ret_val: poly16x8x3_t = transmute(vld1q_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + transmute(vld1q_s16_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19930,35 +18807,6 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { transmute(vld1q_s16_x4(transmute(a))) } -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { - let mut ret_val: poly16x8x4_t = transmute(vld1q_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} #[inline(always)] #[rustc_legacy_const_generics(1)] #[cfg(target_arch = "arm")] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 52748a4cc056d..3ec7ba8814e57 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -2681,6 +2681,7 @@ intrinsics: - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable + big_endian_inverse: false safety: unsafe: [neon] types: @@ -2740,6 +2741,7 @@ intrinsics: - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable + big_endian_inverse: false safety: unsafe: [neon] types: From 0306275849b28f23ebf9d7883317937c9aac0991 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Feb 2026 13:50:20 +0100 Subject: [PATCH 16/47] use macro for wide store/load roundtrip tests --- .../crates/core_arch/src/aarch64/neon/mod.rs | 636 +++--------------- 1 file changed, 90 insertions(+), 546 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index feaf94a7f9e01..ee27bef9738c2 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -994,868 +994,412 @@ mod tests { assert_eq!(vals[2], 2.); } + macro_rules! wide_store_load_roundtrip { + ($elem_ty:ty, $len:expr, $vec_ty:ty, $store:expr, $load:expr) => { + let vals: [$elem_ty; $len] = crate::array::from_fn(|i| i as $elem_ty); + let a: $vec_ty = transmute(vals); + let mut tmp = [0 as $elem_ty; $len]; + $store(tmp.as_mut_ptr().cast(), a); + let r: $vec_ty = $load(tmp.as_ptr().cast()); + let out: [$elem_ty; $len] = transmute(r); + assert_eq!(out, vals); + }; + } + #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1_f16_x2() { - let vals: [f16; 8] = crate::array::from_fn(|i| i as f16); - let a: float16x4x2_t = transmute(vals); - let mut tmp = [0_f16; 8]; - vst1_f16_x2(tmp.as_mut_ptr().cast(), a); - let r: float16x4x2_t = vld1_f16_x2(tmp.as_ptr().cast()); - let out: [f16; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 8, float16x4x2_t, vst1_f16_x2, vld1_f16_x2); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1_f16_x3() { - let vals: [f16; 12] = crate::array::from_fn(|i| i as f16); - let a: float16x4x3_t = transmute(vals); - let mut tmp = [0_f16; 12]; - vst1_f16_x3(tmp.as_mut_ptr().cast(), a); - let r: float16x4x3_t = vld1_f16_x3(tmp.as_ptr().cast()); - let out: [f16; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 12, float16x4x3_t, vst1_f16_x3, vld1_f16_x3); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1_f16_x4() { - let vals: [f16; 16] = crate::array::from_fn(|i| i as f16); - let a: float16x4x4_t = transmute(vals); - let mut tmp = [0_f16; 16]; - vst1_f16_x4(tmp.as_mut_ptr().cast(), a); - let r: float16x4x4_t = vld1_f16_x4(tmp.as_ptr().cast()); - let out: [f16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 16, float16x4x4_t, vst1_f16_x4, vld1_f16_x4); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1q_f16_x2() { - let vals: [f16; 16] = crate::array::from_fn(|i| i as f16); - let a: float16x8x2_t = transmute(vals); - let mut tmp = [0_f16; 16]; - vst1q_f16_x2(tmp.as_mut_ptr().cast(), a); - let r: float16x8x2_t = vld1q_f16_x2(tmp.as_ptr().cast()); - let out: [f16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 16, float16x8x2_t, vst1q_f16_x2, vld1q_f16_x2); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1q_f16_x3() { - let vals: [f16; 24] = crate::array::from_fn(|i| i as f16); - let a: float16x8x3_t = transmute(vals); - let mut tmp = [0_f16; 24]; - vst1q_f16_x3(tmp.as_mut_ptr().cast(), a); - let r: float16x8x3_t = vld1q_f16_x3(tmp.as_ptr().cast()); - let out: [f16; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 24, float16x8x3_t, vst1q_f16_x3, vld1q_f16_x3); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1q_f16_x4() { - let vals: [f16; 32] = crate::array::from_fn(|i| i as f16); - let a: float16x8x4_t = transmute(vals); - let mut tmp = [0_f16; 32]; - vst1q_f16_x4(tmp.as_mut_ptr().cast(), a); - let r: float16x8x4_t = vld1q_f16_x4(tmp.as_ptr().cast()); - let out: [f16; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 32, float16x8x4_t, vst1q_f16_x4, vld1q_f16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_f32_x2() { - let vals: [f32; 4] = crate::array::from_fn(|i| i as f32); - let a: float32x2x2_t = transmute(vals); - let mut tmp = [0_f32; 4]; - vst1_f32_x2(tmp.as_mut_ptr().cast(), a); - let r: float32x2x2_t = vld1_f32_x2(tmp.as_ptr().cast()); - let out: [f32; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 4, float32x2x2_t, vst1_f32_x2, vld1_f32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_f32_x3() { - let vals: [f32; 6] = crate::array::from_fn(|i| i as f32); - let a: float32x2x3_t = transmute(vals); - let mut tmp = [0_f32; 6]; - vst1_f32_x3(tmp.as_mut_ptr().cast(), a); - let r: float32x2x3_t = vld1_f32_x3(tmp.as_ptr().cast()); - let out: [f32; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 6, float32x2x3_t, vst1_f32_x3, vld1_f32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_f32_x4() { - let vals: [f32; 8] = crate::array::from_fn(|i| i as f32); - let a: float32x2x4_t = transmute(vals); - let mut tmp = [0_f32; 8]; - vst1_f32_x4(tmp.as_mut_ptr().cast(), a); - let r: float32x2x4_t = vld1_f32_x4(tmp.as_ptr().cast()); - let out: [f32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 8, float32x2x4_t, vst1_f32_x4, vld1_f32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_f32_x2() { - let vals: [f32; 8] = crate::array::from_fn(|i| i as f32); - let a: float32x4x2_t = transmute(vals); - let mut tmp = [0_f32; 8]; - vst1q_f32_x2(tmp.as_mut_ptr().cast(), a); - let r: float32x4x2_t = vld1q_f32_x2(tmp.as_ptr().cast()); - let out: [f32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 8, float32x4x2_t, vst1q_f32_x2, vld1q_f32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_f32_x3() { - let vals: [f32; 12] = crate::array::from_fn(|i| i as f32); - let a: float32x4x3_t = transmute(vals); - let mut tmp = [0_f32; 12]; - vst1q_f32_x3(tmp.as_mut_ptr().cast(), a); - let r: float32x4x3_t = vld1q_f32_x3(tmp.as_ptr().cast()); - let out: [f32; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 12, float32x4x3_t, vst1q_f32_x3, vld1q_f32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_f32_x4() { - let vals: [f32; 16] = crate::array::from_fn(|i| i as f32); - let a: float32x4x4_t = transmute(vals); - let mut tmp = [0_f32; 16]; - vst1q_f32_x4(tmp.as_mut_ptr().cast(), a); - let r: float32x4x4_t = vld1q_f32_x4(tmp.as_ptr().cast()); - let out: [f32; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 16, float32x4x4_t, vst1q_f32_x4, vld1q_f32_x4); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1_p64_x2() { - let vals: [p64; 2] = crate::array::from_fn(|i| i as p64); - let a: poly64x1x2_t = transmute(vals); - let mut tmp = [0 as p64; 2]; - vst1_p64_x2(tmp.as_mut_ptr().cast(), a); - let r: poly64x1x2_t = vld1_p64_x2(tmp.as_ptr().cast()); - let out: [p64; 2] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 2, poly64x1x2_t, vst1_p64_x2, vld1_p64_x2); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1_p64_x3() { - let vals: [p64; 3] = crate::array::from_fn(|i| i as p64); - let a: poly64x1x3_t = transmute(vals); - let mut tmp = [0 as p64; 3]; - vst1_p64_x3(tmp.as_mut_ptr().cast(), a); - let r: poly64x1x3_t = vld1_p64_x3(tmp.as_ptr().cast()); - let out: [p64; 3] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 3, poly64x1x3_t, vst1_p64_x3, vld1_p64_x3); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1_p64_x4() { - let vals: [p64; 4] = crate::array::from_fn(|i| i as p64); - let a: poly64x1x4_t = transmute(vals); - let mut tmp = [0 as p64; 4]; - vst1_p64_x4(tmp.as_mut_ptr().cast(), a); - let r: poly64x1x4_t = vld1_p64_x4(tmp.as_ptr().cast()); - let out: [p64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 4, poly64x1x4_t, vst1_p64_x4, vld1_p64_x4); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1q_p64_x2() { - let vals: [p64; 4] = crate::array::from_fn(|i| i as p64); - let a: poly64x2x2_t = transmute(vals); - let mut tmp = [0 as p64; 4]; - vst1q_p64_x2(tmp.as_mut_ptr().cast(), a); - let r: poly64x2x2_t = vld1q_p64_x2(tmp.as_ptr().cast()); - let out: [p64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 4, poly64x2x2_t, vst1q_p64_x2, vld1q_p64_x2); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1q_p64_x3() { - let vals: [p64; 6] = crate::array::from_fn(|i| i as p64); - let a: poly64x2x3_t = transmute(vals); - let mut tmp = [0 as p64; 6]; - vst1q_p64_x3(tmp.as_mut_ptr().cast(), a); - let r: poly64x2x3_t = vld1q_p64_x3(tmp.as_ptr().cast()); - let out: [p64; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 6, poly64x2x3_t, vst1q_p64_x3, vld1q_p64_x3); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1q_p64_x4() { - let vals: [p64; 8] = crate::array::from_fn(|i| i as p64); - let a: poly64x2x4_t = transmute(vals); - let mut tmp = [0 as p64; 8]; - vst1q_p64_x4(tmp.as_mut_ptr().cast(), a); - let r: poly64x2x4_t = vld1q_p64_x4(tmp.as_ptr().cast()); - let out: [p64; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 8, poly64x2x4_t, vst1q_p64_x4, vld1q_p64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s8_x2() { - let vals: [i8; 16] = crate::array::from_fn(|i| i as i8); - let a: int8x8x2_t = transmute(vals); - let mut tmp = [0_i8; 16]; - vst1_s8_x2(tmp.as_mut_ptr().cast(), a); - let r: int8x8x2_t = vld1_s8_x2(tmp.as_ptr().cast()); - let out: [i8; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 16, int8x8x2_t, vst1_s8_x2, vld1_s8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s8_x3() { - let vals: [i8; 24] = crate::array::from_fn(|i| i as i8); - let a: int8x8x3_t = transmute(vals); - let mut tmp = [0_i8; 24]; - vst1_s8_x3(tmp.as_mut_ptr().cast(), a); - let r: int8x8x3_t = vld1_s8_x3(tmp.as_ptr().cast()); - let out: [i8; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 24, int8x8x3_t, vst1_s8_x3, vld1_s8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s8_x4() { - let vals: [i8; 32] = crate::array::from_fn(|i| i as i8); - let a: int8x8x4_t = transmute(vals); - let mut tmp = [0_i8; 32]; - vst1_s8_x4(tmp.as_mut_ptr().cast(), a); - let r: int8x8x4_t = vld1_s8_x4(tmp.as_ptr().cast()); - let out: [i8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 32, int8x8x4_t, vst1_s8_x4, vld1_s8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s8_x2() { - let vals: [i8; 32] = crate::array::from_fn(|i| i as i8); - let a: int8x16x2_t = transmute(vals); - let mut tmp = [0_i8; 32]; - vst1q_s8_x2(tmp.as_mut_ptr().cast(), a); - let r: int8x16x2_t = vld1q_s8_x2(tmp.as_ptr().cast()); - let out: [i8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 32, int8x16x2_t, vst1q_s8_x2, vld1q_s8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s8_x3() { - let vals: [i8; 48] = crate::array::from_fn(|i| i as i8); - let a: int8x16x3_t = transmute(vals); - let mut tmp = [0_i8; 48]; - vst1q_s8_x3(tmp.as_mut_ptr().cast(), a); - let r: int8x16x3_t = vld1q_s8_x3(tmp.as_ptr().cast()); - let out: [i8; 48] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 48, int8x16x3_t, vst1q_s8_x3, vld1q_s8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s8_x4() { - let vals: [i8; 64] = crate::array::from_fn(|i| i as i8); - let a: int8x16x4_t = transmute(vals); - let mut tmp = [0_i8; 64]; - vst1q_s8_x4(tmp.as_mut_ptr().cast(), a); - let r: int8x16x4_t = vld1q_s8_x4(tmp.as_ptr().cast()); - let out: [i8; 64] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 64, int8x16x4_t, vst1q_s8_x4, vld1q_s8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s16_x2() { - let vals: [i16; 8] = crate::array::from_fn(|i| i as i16); - let a: int16x4x2_t = transmute(vals); - let mut tmp = [0_i16; 8]; - vst1_s16_x2(tmp.as_mut_ptr().cast(), a); - let r: int16x4x2_t = vld1_s16_x2(tmp.as_ptr().cast()); - let out: [i16; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 8, int16x4x2_t, vst1_s16_x2, vld1_s16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s16_x3() { - let vals: [i16; 12] = crate::array::from_fn(|i| i as i16); - let a: int16x4x3_t = transmute(vals); - let mut tmp = [0_i16; 12]; - vst1_s16_x3(tmp.as_mut_ptr().cast(), a); - let r: int16x4x3_t = vld1_s16_x3(tmp.as_ptr().cast()); - let out: [i16; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 12, int16x4x3_t, vst1_s16_x3, vld1_s16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s16_x4() { - let vals: [i16; 16] = crate::array::from_fn(|i| i as i16); - let a: int16x4x4_t = transmute(vals); - let mut tmp = [0_i16; 16]; - vst1_s16_x4(tmp.as_mut_ptr().cast(), a); - let r: int16x4x4_t = vld1_s16_x4(tmp.as_ptr().cast()); - let out: [i16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 16, int16x4x4_t, vst1_s16_x4, vld1_s16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s16_x2() { - let vals: [i16; 16] = crate::array::from_fn(|i| i as i16); - let a: int16x8x2_t = transmute(vals); - let mut tmp = [0_i16; 16]; - vst1q_s16_x2(tmp.as_mut_ptr().cast(), a); - let r: int16x8x2_t = vld1q_s16_x2(tmp.as_ptr().cast()); - let out: [i16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 16, int16x8x2_t, vst1q_s16_x2, vld1q_s16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s16_x3() { - let vals: [i16; 24] = crate::array::from_fn(|i| i as i16); - let a: int16x8x3_t = transmute(vals); - let mut tmp = [0_i16; 24]; - vst1q_s16_x3(tmp.as_mut_ptr().cast(), a); - let r: int16x8x3_t = vld1q_s16_x3(tmp.as_ptr().cast()); - let out: [i16; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 24, int16x8x3_t, vst1q_s16_x3, vld1q_s16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s16_x4() { - let vals: [i16; 32] = crate::array::from_fn(|i| i as i16); - let a: int16x8x4_t = transmute(vals); - let mut tmp = [0_i16; 32]; - vst1q_s16_x4(tmp.as_mut_ptr().cast(), a); - let r: int16x8x4_t = vld1q_s16_x4(tmp.as_ptr().cast()); - let out: [i16; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 32, int16x8x4_t, vst1q_s16_x4, vld1q_s16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s32_x2() { - let vals: [i32; 4] = crate::array::from_fn(|i| i as i32); - let a: int32x2x2_t = transmute(vals); - let mut tmp = [0_i32; 4]; - vst1_s32_x2(tmp.as_mut_ptr().cast(), a); - let r: int32x2x2_t = vld1_s32_x2(tmp.as_ptr().cast()); - let out: [i32; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 4, int32x2x2_t, vst1_s32_x2, vld1_s32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s32_x3() { - let vals: [i32; 6] = crate::array::from_fn(|i| i as i32); - let a: int32x2x3_t = transmute(vals); - let mut tmp = [0_i32; 6]; - vst1_s32_x3(tmp.as_mut_ptr().cast(), a); - let r: int32x2x3_t = vld1_s32_x3(tmp.as_ptr().cast()); - let out: [i32; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 6, int32x2x3_t, vst1_s32_x3, vld1_s32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s32_x4() { - let vals: [i32; 8] = crate::array::from_fn(|i| i as i32); - let a: int32x2x4_t = transmute(vals); - let mut tmp = [0_i32; 8]; - vst1_s32_x4(tmp.as_mut_ptr().cast(), a); - let r: int32x2x4_t = vld1_s32_x4(tmp.as_ptr().cast()); - let out: [i32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 8, int32x2x4_t, vst1_s32_x4, vld1_s32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s32_x2() { - let vals: [i32; 8] = crate::array::from_fn(|i| i as i32); - let a: int32x4x2_t = transmute(vals); - let mut tmp = [0_i32; 8]; - vst1q_s32_x2(tmp.as_mut_ptr().cast(), a); - let r: int32x4x2_t = vld1q_s32_x2(tmp.as_ptr().cast()); - let out: [i32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 8, int32x4x2_t, vst1q_s32_x2, vld1q_s32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s32_x3() { - let vals: [i32; 12] = crate::array::from_fn(|i| i as i32); - let a: int32x4x3_t = transmute(vals); - let mut tmp = [0_i32; 12]; - vst1q_s32_x3(tmp.as_mut_ptr().cast(), a); - let r: int32x4x3_t = vld1q_s32_x3(tmp.as_ptr().cast()); - let out: [i32; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 12, int32x4x3_t, vst1q_s32_x3, vld1q_s32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s32_x4() { - let vals: [i32; 16] = crate::array::from_fn(|i| i as i32); - let a: int32x4x4_t = transmute(vals); - let mut tmp = [0_i32; 16]; - vst1q_s32_x4(tmp.as_mut_ptr().cast(), a); - let r: int32x4x4_t = vld1q_s32_x4(tmp.as_ptr().cast()); - let out: [i32; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 16, int32x4x4_t, vst1q_s32_x4, vld1q_s32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s64_x2() { - let vals: [i64; 2] = crate::array::from_fn(|i| i as i64); - let a: int64x1x2_t = transmute(vals); - let mut tmp = [0_i64; 2]; - vst1_s64_x2(tmp.as_mut_ptr().cast(), a); - let r: int64x1x2_t = vld1_s64_x2(tmp.as_ptr().cast()); - let out: [i64; 2] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 2, int64x1x2_t, vst1_s64_x2, vld1_s64_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s64_x3() { - let vals: [i64; 3] = crate::array::from_fn(|i| i as i64); - let a: int64x1x3_t = transmute(vals); - let mut tmp = [0_i64; 3]; - vst1_s64_x3(tmp.as_mut_ptr().cast(), a); - let r: int64x1x3_t = vld1_s64_x3(tmp.as_ptr().cast()); - let out: [i64; 3] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 3, int64x1x3_t, vst1_s64_x3, vld1_s64_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s64_x4() { - let vals: [i64; 4] = crate::array::from_fn(|i| i as i64); - let a: int64x1x4_t = transmute(vals); - let mut tmp = [0_i64; 4]; - vst1_s64_x4(tmp.as_mut_ptr().cast(), a); - let r: int64x1x4_t = vld1_s64_x4(tmp.as_ptr().cast()); - let out: [i64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 4, int64x1x4_t, vst1_s64_x4, vld1_s64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s64_x2() { - let vals: [i64; 4] = crate::array::from_fn(|i| i as i64); - let a: int64x2x2_t = transmute(vals); - let mut tmp = [0_i64; 4]; - vst1q_s64_x2(tmp.as_mut_ptr().cast(), a); - let r: int64x2x2_t = vld1q_s64_x2(tmp.as_ptr().cast()); - let out: [i64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 4, int64x2x2_t, vst1q_s64_x2, vld1q_s64_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s64_x3() { - let vals: [i64; 6] = crate::array::from_fn(|i| i as i64); - let a: int64x2x3_t = transmute(vals); - let mut tmp = [0_i64; 6]; - vst1q_s64_x3(tmp.as_mut_ptr().cast(), a); - let r: int64x2x3_t = vld1q_s64_x3(tmp.as_ptr().cast()); - let out: [i64; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 6, int64x2x3_t, vst1q_s64_x3, vld1q_s64_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s64_x4() { - let vals: [i64; 8] = crate::array::from_fn(|i| i as i64); - let a: int64x2x4_t = transmute(vals); - let mut tmp = [0_i64; 8]; - vst1q_s64_x4(tmp.as_mut_ptr().cast(), a); - let r: int64x2x4_t = vld1q_s64_x4(tmp.as_ptr().cast()); - let out: [i64; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 8, int64x2x4_t, vst1q_s64_x4, vld1q_s64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u8_x2() { - let vals: [u8; 16] = crate::array::from_fn(|i| i as u8); - let a: uint8x8x2_t = transmute(vals); - let mut tmp = [0_u8; 16]; - vst1_u8_x2(tmp.as_mut_ptr().cast(), a); - let r: uint8x8x2_t = vld1_u8_x2(tmp.as_ptr().cast()); - let out: [u8; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 16, uint8x8x2_t, vst1_u8_x2, vld1_u8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u8_x3() { - let vals: [u8; 24] = crate::array::from_fn(|i| i as u8); - let a: uint8x8x3_t = transmute(vals); - let mut tmp = [0_u8; 24]; - vst1_u8_x3(tmp.as_mut_ptr().cast(), a); - let r: uint8x8x3_t = vld1_u8_x3(tmp.as_ptr().cast()); - let out: [u8; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 24, uint8x8x3_t, vst1_u8_x3, vld1_u8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u8_x4() { - let vals: [u8; 32] = crate::array::from_fn(|i| i as u8); - let a: uint8x8x4_t = transmute(vals); - let mut tmp = [0_u8; 32]; - vst1_u8_x4(tmp.as_mut_ptr().cast(), a); - let r: uint8x8x4_t = vld1_u8_x4(tmp.as_ptr().cast()); - let out: [u8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 32, uint8x8x4_t, vst1_u8_x4, vld1_u8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u8_x2() { - let vals: [u8; 32] = crate::array::from_fn(|i| i as u8); - let a: uint8x16x2_t = transmute(vals); - let mut tmp = [0_u8; 32]; - vst1q_u8_x2(tmp.as_mut_ptr().cast(), a); - let r: uint8x16x2_t = vld1q_u8_x2(tmp.as_ptr().cast()); - let out: [u8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 32, uint8x16x2_t, vst1q_u8_x2, vld1q_u8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u8_x3() { - let vals: [u8; 48] = crate::array::from_fn(|i| i as u8); - let a: uint8x16x3_t = transmute(vals); - let mut tmp = [0_u8; 48]; - vst1q_u8_x3(tmp.as_mut_ptr().cast(), a); - let r: uint8x16x3_t = vld1q_u8_x3(tmp.as_ptr().cast()); - let out: [u8; 48] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 48, uint8x16x3_t, vst1q_u8_x3, vld1q_u8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u8_x4() { - let vals: [u8; 64] = crate::array::from_fn(|i| i as u8); - let a: uint8x16x4_t = transmute(vals); - let mut tmp = [0_u8; 64]; - vst1q_u8_x4(tmp.as_mut_ptr().cast(), a); - let r: uint8x16x4_t = vld1q_u8_x4(tmp.as_ptr().cast()); - let out: [u8; 64] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 64, uint8x16x4_t, vst1q_u8_x4, vld1q_u8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u16_x2() { - let vals: [u16; 8] = crate::array::from_fn(|i| i as u16); - let a: uint16x4x2_t = transmute(vals); - let mut tmp = [0_u16; 8]; - vst1_u16_x2(tmp.as_mut_ptr().cast(), a); - let r: uint16x4x2_t = vld1_u16_x2(tmp.as_ptr().cast()); - let out: [u16; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 8, uint16x4x2_t, vst1_u16_x2, vld1_u16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u16_x3() { - let vals: [u16; 12] = crate::array::from_fn(|i| i as u16); - let a: uint16x4x3_t = transmute(vals); - let mut tmp = [0_u16; 12]; - vst1_u16_x3(tmp.as_mut_ptr().cast(), a); - let r: uint16x4x3_t = vld1_u16_x3(tmp.as_ptr().cast()); - let out: [u16; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 12, uint16x4x3_t, vst1_u16_x3, vld1_u16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u16_x4() { - let vals: [u16; 16] = crate::array::from_fn(|i| i as u16); - let a: uint16x4x4_t = transmute(vals); - let mut tmp = [0_u16; 16]; - vst1_u16_x4(tmp.as_mut_ptr().cast(), a); - let r: uint16x4x4_t = vld1_u16_x4(tmp.as_ptr().cast()); - let out: [u16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 16, uint16x4x4_t, vst1_u16_x4, vld1_u16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u16_x2() { - let vals: [u16; 16] = crate::array::from_fn(|i| i as u16); - let a: uint16x8x2_t = transmute(vals); - let mut tmp = [0_u16; 16]; - vst1q_u16_x2(tmp.as_mut_ptr().cast(), a); - let r: uint16x8x2_t = vld1q_u16_x2(tmp.as_ptr().cast()); - let out: [u16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 16, uint16x8x2_t, vst1q_u16_x2, vld1q_u16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u16_x3() { - let vals: [u16; 24] = crate::array::from_fn(|i| i as u16); - let a: uint16x8x3_t = transmute(vals); - let mut tmp = [0_u16; 24]; - vst1q_u16_x3(tmp.as_mut_ptr().cast(), a); - let r: uint16x8x3_t = vld1q_u16_x3(tmp.as_ptr().cast()); - let out: [u16; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 24, uint16x8x3_t, vst1q_u16_x3, vld1q_u16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u16_x4() { - let vals: [u16; 32] = crate::array::from_fn(|i| i as u16); - let a: uint16x8x4_t = transmute(vals); - let mut tmp = [0_u16; 32]; - vst1q_u16_x4(tmp.as_mut_ptr().cast(), a); - let r: uint16x8x4_t = vld1q_u16_x4(tmp.as_ptr().cast()); - let out: [u16; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 32, uint16x8x4_t, vst1q_u16_x4, vld1q_u16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u32_x2() { - let vals: [u32; 4] = crate::array::from_fn(|i| i as u32); - let a: uint32x2x2_t = transmute(vals); - let mut tmp = [0_u32; 4]; - vst1_u32_x2(tmp.as_mut_ptr().cast(), a); - let r: uint32x2x2_t = vld1_u32_x2(tmp.as_ptr().cast()); - let out: [u32; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 4, uint32x2x2_t, vst1_u32_x2, vld1_u32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u32_x3() { - let vals: [u32; 6] = crate::array::from_fn(|i| i as u32); - let a: uint32x2x3_t = transmute(vals); - let mut tmp = [0_u32; 6]; - vst1_u32_x3(tmp.as_mut_ptr().cast(), a); - let r: uint32x2x3_t = vld1_u32_x3(tmp.as_ptr().cast()); - let out: [u32; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 6, uint32x2x3_t, vst1_u32_x3, vld1_u32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u32_x4() { - let vals: [u32; 8] = crate::array::from_fn(|i| i as u32); - let a: uint32x2x4_t = transmute(vals); - let mut tmp = [0_u32; 8]; - vst1_u32_x4(tmp.as_mut_ptr().cast(), a); - let r: uint32x2x4_t = vld1_u32_x4(tmp.as_ptr().cast()); - let out: [u32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 8, uint32x2x4_t, vst1_u32_x4, vld1_u32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u32_x2() { - let vals: [u32; 8] = crate::array::from_fn(|i| i as u32); - let a: uint32x4x2_t = transmute(vals); - let mut tmp = [0_u32; 8]; - vst1q_u32_x2(tmp.as_mut_ptr().cast(), a); - let r: uint32x4x2_t = vld1q_u32_x2(tmp.as_ptr().cast()); - let out: [u32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 8, uint32x4x2_t, vst1q_u32_x2, vld1q_u32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u32_x3() { - let vals: [u32; 12] = crate::array::from_fn(|i| i as u32); - let a: uint32x4x3_t = transmute(vals); - let mut tmp = [0_u32; 12]; - vst1q_u32_x3(tmp.as_mut_ptr().cast(), a); - let r: uint32x4x3_t = vld1q_u32_x3(tmp.as_ptr().cast()); - let out: [u32; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 12, uint32x4x3_t, vst1q_u32_x3, vld1q_u32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u32_x4() { - let vals: [u32; 16] = crate::array::from_fn(|i| i as u32); - let a: uint32x4x4_t = transmute(vals); - let mut tmp = [0_u32; 16]; - vst1q_u32_x4(tmp.as_mut_ptr().cast(), a); - let r: uint32x4x4_t = vld1q_u32_x4(tmp.as_ptr().cast()); - let out: [u32; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 16, uint32x4x4_t, vst1q_u32_x4, vld1q_u32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u64_x2() { - let vals: [u64; 2] = crate::array::from_fn(|i| i as u64); - let a: uint64x1x2_t = transmute(vals); - let mut tmp = [0_u64; 2]; - vst1_u64_x2(tmp.as_mut_ptr().cast(), a); - let r: uint64x1x2_t = vld1_u64_x2(tmp.as_ptr().cast()); - let out: [u64; 2] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 2, uint64x1x2_t, vst1_u64_x2, vld1_u64_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u64_x3() { - let vals: [u64; 3] = crate::array::from_fn(|i| i as u64); - let a: uint64x1x3_t = transmute(vals); - let mut tmp = [0_u64; 3]; - vst1_u64_x3(tmp.as_mut_ptr().cast(), a); - let r: uint64x1x3_t = vld1_u64_x3(tmp.as_ptr().cast()); - let out: [u64; 3] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 3, uint64x1x3_t, vst1_u64_x3, vld1_u64_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u64_x4() { - let vals: [u64; 4] = crate::array::from_fn(|i| i as u64); - let a: uint64x1x4_t = transmute(vals); - let mut tmp = [0_u64; 4]; - vst1_u64_x4(tmp.as_mut_ptr().cast(), a); - let r: uint64x1x4_t = vld1_u64_x4(tmp.as_ptr().cast()); - let out: [u64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 4, uint64x1x4_t, vst1_u64_x4, vld1_u64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u64_x2() { - let vals: [u64; 4] = crate::array::from_fn(|i| i as u64); - let a: uint64x2x2_t = transmute(vals); - let mut tmp = [0_u64; 4]; - vst1q_u64_x2(tmp.as_mut_ptr().cast(), a); - let r: uint64x2x2_t = vld1q_u64_x2(tmp.as_ptr().cast()); - let out: [u64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 4, uint64x2x2_t, vst1q_u64_x2, vld1q_u64_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u64_x3() { - let vals: [u64; 6] = crate::array::from_fn(|i| i as u64); - let a: uint64x2x3_t = transmute(vals); - let mut tmp = [0_u64; 6]; - vst1q_u64_x3(tmp.as_mut_ptr().cast(), a); - let r: uint64x2x3_t = vld1q_u64_x3(tmp.as_ptr().cast()); - let out: [u64; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 6, uint64x2x3_t, vst1q_u64_x3, vld1q_u64_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u64_x4() { - let vals: [u64; 8] = crate::array::from_fn(|i| i as u64); - let a: uint64x2x4_t = transmute(vals); - let mut tmp = [0_u64; 8]; - vst1q_u64_x4(tmp.as_mut_ptr().cast(), a); - let r: uint64x2x4_t = vld1q_u64_x4(tmp.as_ptr().cast()); - let out: [u64; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 8, uint64x2x4_t, vst1q_u64_x4, vld1q_u64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p8_x2() { - let vals: [p8; 16] = crate::array::from_fn(|i| i as p8); - let a: poly8x8x2_t = transmute(vals); - let mut tmp = [0 as p8; 16]; - vst1_p8_x2(tmp.as_mut_ptr().cast(), a); - let r: poly8x8x2_t = vld1_p8_x2(tmp.as_ptr().cast()); - let out: [p8; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 16, poly8x8x2_t, vst1_p8_x2, vld1_p8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p8_x3() { - let vals: [p8; 24] = crate::array::from_fn(|i| i as p8); - let a: poly8x8x3_t = transmute(vals); - let mut tmp = [0 as p8; 24]; - vst1_p8_x3(tmp.as_mut_ptr().cast(), a); - let r: poly8x8x3_t = vld1_p8_x3(tmp.as_ptr().cast()); - let out: [p8; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 24, poly8x8x3_t, vst1_p8_x3, vld1_p8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p8_x4() { - let vals: [p8; 32] = crate::array::from_fn(|i| i as p8); - let a: poly8x8x4_t = transmute(vals); - let mut tmp = [0 as p8; 32]; - vst1_p8_x4(tmp.as_mut_ptr().cast(), a); - let r: poly8x8x4_t = vld1_p8_x4(tmp.as_ptr().cast()); - let out: [p8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 32, poly8x8x4_t, vst1_p8_x4, vld1_p8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p8_x2() { - let vals: [p8; 32] = crate::array::from_fn(|i| i as p8); - let a: poly8x16x2_t = transmute(vals); - let mut tmp = [0 as p8; 32]; - vst1q_p8_x2(tmp.as_mut_ptr().cast(), a); - let r: poly8x16x2_t = vld1q_p8_x2(tmp.as_ptr().cast()); - let out: [p8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 32, poly8x16x2_t, vst1q_p8_x2, vld1q_p8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p8_x3() { - let vals: [p8; 48] = crate::array::from_fn(|i| i as p8); - let a: poly8x16x3_t = transmute(vals); - let mut tmp = [0 as p8; 48]; - vst1q_p8_x3(tmp.as_mut_ptr().cast(), a); - let r: poly8x16x3_t = vld1q_p8_x3(tmp.as_ptr().cast()); - let out: [p8; 48] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 48, poly8x16x3_t, vst1q_p8_x3, vld1q_p8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p8_x4() { - let vals: [p8; 64] = crate::array::from_fn(|i| i as p8); - let a: poly8x16x4_t = transmute(vals); - let mut tmp = [0 as p8; 64]; - vst1q_p8_x4(tmp.as_mut_ptr().cast(), a); - let r: poly8x16x4_t = vld1q_p8_x4(tmp.as_ptr().cast()); - let out: [p8; 64] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 64, poly8x16x4_t, vst1q_p8_x4, vld1q_p8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p16_x2() { - let vals: [p16; 8] = crate::array::from_fn(|i| i as p16); - let a: poly16x4x2_t = transmute(vals); - let mut tmp = [0 as p16; 8]; - vst1_p16_x2(tmp.as_mut_ptr().cast(), a); - let r: poly16x4x2_t = vld1_p16_x2(tmp.as_ptr().cast()); - let out: [p16; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 8, poly16x4x2_t, vst1_p16_x2, vld1_p16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p16_x3() { - let vals: [p16; 12] = crate::array::from_fn(|i| i as p16); - let a: poly16x4x3_t = transmute(vals); - let mut tmp = [0 as p16; 12]; - vst1_p16_x3(tmp.as_mut_ptr().cast(), a); - let r: poly16x4x3_t = vld1_p16_x3(tmp.as_ptr().cast()); - let out: [p16; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 12, poly16x4x3_t, vst1_p16_x3, vld1_p16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p16_x4() { - let vals: [p16; 16] = crate::array::from_fn(|i| i as p16); - let a: poly16x4x4_t = transmute(vals); - let mut tmp = [0 as p16; 16]; - vst1_p16_x4(tmp.as_mut_ptr().cast(), a); - let r: poly16x4x4_t = vld1_p16_x4(tmp.as_ptr().cast()); - let out: [p16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 16, poly16x4x4_t, vst1_p16_x4, vld1_p16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p16_x2() { - let vals: [p16; 16] = crate::array::from_fn(|i| i as p16); - let a: poly16x8x2_t = transmute(vals); - let mut tmp = [0 as p16; 16]; - vst1q_p16_x2(tmp.as_mut_ptr().cast(), a); - let r: poly16x8x2_t = vld1q_p16_x2(tmp.as_ptr().cast()); - let out: [p16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 16, poly16x8x2_t, vst1q_p16_x2, vld1q_p16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p16_x3() { - let vals: [p16; 24] = crate::array::from_fn(|i| i as p16); - let a: poly16x8x3_t = transmute(vals); - let mut tmp = [0 as p16; 24]; - vst1q_p16_x3(tmp.as_mut_ptr().cast(), a); - let r: poly16x8x3_t = vld1q_p16_x3(tmp.as_ptr().cast()); - let out: [p16; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 24, poly16x8x3_t, vst1q_p16_x3, vld1q_p16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p16_x4() { - let vals: [p16; 32] = crate::array::from_fn(|i| i as p16); - let a: poly16x8x4_t = transmute(vals); - let mut tmp = [0 as p16; 32]; - vst1q_p16_x4(tmp.as_mut_ptr().cast(), a); - let r: poly16x8x4_t = vld1q_p16_x4(tmp.as_ptr().cast()); - let out: [p16; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 32, poly16x8x4_t, vst1q_p16_x4, vld1q_p16_x4); } } From 794810f897559a86d2de36344e13ad3c065d5217 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Feb 2026 14:17:35 +0100 Subject: [PATCH 17/47] use more capable macro for wide store/load roundtrip tests --- .../crates/core_arch/src/aarch64/neon/mod.rs | 470 ++++-------------- 1 file changed, 109 insertions(+), 361 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index ee27bef9738c2..580f203ef0662 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -1006,400 +1006,148 @@ mod tests { }; } - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1_f16_x2() { - wide_store_load_roundtrip!(f16, 8, float16x4x2_t, vst1_f16_x2, vld1_f16_x2); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1_f16_x3() { - wide_store_load_roundtrip!(f16, 12, float16x4x3_t, vst1_f16_x3, vld1_f16_x3); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1_f16_x4() { - wide_store_load_roundtrip!(f16, 16, float16x4x4_t, vst1_f16_x4, vld1_f16_x4); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1q_f16_x2() { - wide_store_load_roundtrip!(f16, 16, float16x8x2_t, vst1q_f16_x2, vld1q_f16_x2); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1q_f16_x3() { - wide_store_load_roundtrip!(f16, 24, float16x8x3_t, vst1q_f16_x3, vld1q_f16_x3); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1q_f16_x4() { - wide_store_load_roundtrip!(f16, 32, float16x8x4_t, vst1q_f16_x4, vld1q_f16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x2() { - wide_store_load_roundtrip!(f32, 4, float32x2x2_t, vst1_f32_x2, vld1_f32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x3() { - wide_store_load_roundtrip!(f32, 6, float32x2x3_t, vst1_f32_x3, vld1_f32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x4() { - wide_store_load_roundtrip!(f32, 8, float32x2x4_t, vst1_f32_x4, vld1_f32_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x2() { - wide_store_load_roundtrip!(f32, 8, float32x4x2_t, vst1q_f32_x2, vld1q_f32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x3() { - wide_store_load_roundtrip!(f32, 12, float32x4x3_t, vst1q_f32_x3, vld1q_f32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x4() { - wide_store_load_roundtrip!(f32, 16, float32x4x4_t, vst1q_f32_x4, vld1q_f32_x4); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1_p64_x2() { - wide_store_load_roundtrip!(p64, 2, poly64x1x2_t, vst1_p64_x2, vld1_p64_x2); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1_p64_x3() { - wide_store_load_roundtrip!(p64, 3, poly64x1x3_t, vst1_p64_x3, vld1_p64_x3); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1_p64_x4() { - wide_store_load_roundtrip!(p64, 4, poly64x1x4_t, vst1_p64_x4, vld1_p64_x4); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1q_p64_x2() { - wide_store_load_roundtrip!(p64, 4, poly64x2x2_t, vst1q_p64_x2, vld1q_p64_x2); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1q_p64_x3() { - wide_store_load_roundtrip!(p64, 6, poly64x2x3_t, vst1q_p64_x3, vld1q_p64_x3); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1q_p64_x4() { - wide_store_load_roundtrip!(p64, 8, poly64x2x4_t, vst1q_p64_x4, vld1q_p64_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x2() { - wide_store_load_roundtrip!(i8, 16, int8x8x2_t, vst1_s8_x2, vld1_s8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x3() { - wide_store_load_roundtrip!(i8, 24, int8x8x3_t, vst1_s8_x3, vld1_s8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x4() { - wide_store_load_roundtrip!(i8, 32, int8x8x4_t, vst1_s8_x4, vld1_s8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x2() { - wide_store_load_roundtrip!(i8, 32, int8x16x2_t, vst1q_s8_x2, vld1q_s8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x3() { - wide_store_load_roundtrip!(i8, 48, int8x16x3_t, vst1q_s8_x3, vld1q_s8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x4() { - wide_store_load_roundtrip!(i8, 64, int8x16x4_t, vst1q_s8_x4, vld1q_s8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x2() { - wide_store_load_roundtrip!(i16, 8, int16x4x2_t, vst1_s16_x2, vld1_s16_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x3() { - wide_store_load_roundtrip!(i16, 12, int16x4x3_t, vst1_s16_x3, vld1_s16_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x4() { - wide_store_load_roundtrip!(i16, 16, int16x4x4_t, vst1_s16_x4, vld1_s16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x2() { - wide_store_load_roundtrip!(i16, 16, int16x8x2_t, vst1q_s16_x2, vld1q_s16_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x3() { - wide_store_load_roundtrip!(i16, 24, int16x8x3_t, vst1q_s16_x3, vld1q_s16_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x4() { - wide_store_load_roundtrip!(i16, 32, int16x8x4_t, vst1q_s16_x4, vld1q_s16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x2() { - wide_store_load_roundtrip!(i32, 4, int32x2x2_t, vst1_s32_x2, vld1_s32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x3() { - wide_store_load_roundtrip!(i32, 6, int32x2x3_t, vst1_s32_x3, vld1_s32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x4() { - wide_store_load_roundtrip!(i32, 8, int32x2x4_t, vst1_s32_x4, vld1_s32_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x2() { - wide_store_load_roundtrip!(i32, 8, int32x4x2_t, vst1q_s32_x2, vld1q_s32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x3() { - wide_store_load_roundtrip!(i32, 12, int32x4x3_t, vst1q_s32_x3, vld1q_s32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x4() { - wide_store_load_roundtrip!(i32, 16, int32x4x4_t, vst1q_s32_x4, vld1q_s32_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x2() { - wide_store_load_roundtrip!(i64, 2, int64x1x2_t, vst1_s64_x2, vld1_s64_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x3() { - wide_store_load_roundtrip!(i64, 3, int64x1x3_t, vst1_s64_x3, vld1_s64_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x4() { - wide_store_load_roundtrip!(i64, 4, int64x1x4_t, vst1_s64_x4, vld1_s64_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x2() { - wide_store_load_roundtrip!(i64, 4, int64x2x2_t, vst1q_s64_x2, vld1q_s64_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x3() { - wide_store_load_roundtrip!(i64, 6, int64x2x3_t, vst1q_s64_x3, vld1q_s64_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x4() { - wide_store_load_roundtrip!(i64, 8, int64x2x4_t, vst1q_s64_x4, vld1q_s64_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x2() { - wide_store_load_roundtrip!(u8, 16, uint8x8x2_t, vst1_u8_x2, vld1_u8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x3() { - wide_store_load_roundtrip!(u8, 24, uint8x8x3_t, vst1_u8_x3, vld1_u8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x4() { - wide_store_load_roundtrip!(u8, 32, uint8x8x4_t, vst1_u8_x4, vld1_u8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x2() { - wide_store_load_roundtrip!(u8, 32, uint8x16x2_t, vst1q_u8_x2, vld1q_u8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x3() { - wide_store_load_roundtrip!(u8, 48, uint8x16x3_t, vst1q_u8_x3, vld1q_u8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x4() { - wide_store_load_roundtrip!(u8, 64, uint8x16x4_t, vst1q_u8_x4, vld1q_u8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x2() { - wide_store_load_roundtrip!(u16, 8, uint16x4x2_t, vst1_u16_x2, vld1_u16_x2); + macro_rules! wide_store_load_roundtrip_fp16 { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; } - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x3() { - wide_store_load_roundtrip!(u16, 12, uint16x4x3_t, vst1_u16_x3, vld1_u16_x3); - } + wide_store_load_roundtrip_fp16! { + test_vld1_f16_x2(f16, 8, float16x4x2_t, vst1_f16_x2, vld1_f16_x2); + test_vld1_f16_x3(f16, 12, float16x4x3_t, vst1_f16_x3, vld1_f16_x3); + test_vld1_f16_x4(f16, 16, float16x4x4_t, vst1_f16_x4, vld1_f16_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x4() { - wide_store_load_roundtrip!(u16, 16, uint16x4x4_t, vst1_u16_x4, vld1_u16_x4); + test_vld1q_f16_x2(f16, 16, float16x8x2_t, vst1q_f16_x2, vld1q_f16_x2); + test_vld1q_f16_x3(f16, 24, float16x8x3_t, vst1q_f16_x3, vld1q_f16_x3); + test_vld1q_f16_x4(f16, 32, float16x8x4_t, vst1q_f16_x4, vld1q_f16_x4); } - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x2() { - wide_store_load_roundtrip!(u16, 16, uint16x8x2_t, vst1q_u16_x2, vld1q_u16_x2); + macro_rules! wide_store_load_roundtrip_aes { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon,aes")] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; } - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x3() { - wide_store_load_roundtrip!(u16, 24, uint16x8x3_t, vst1q_u16_x3, vld1q_u16_x3); - } + wide_store_load_roundtrip_aes! { + test_vld1_p64_x2(p64, 2, poly64x1x2_t, vst1_p64_x2, vld1_p64_x2); + test_vld1_p64_x3(p64, 3, poly64x1x3_t, vst1_p64_x3, vld1_p64_x3); + test_vld1_p64_x4(p64, 4, poly64x1x4_t, vst1_p64_x4, vld1_p64_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x4() { - wide_store_load_roundtrip!(u16, 32, uint16x8x4_t, vst1q_u16_x4, vld1q_u16_x4); + test_vld1q_p64_x2(p64, 4, poly64x2x2_t, vst1q_p64_x2, vld1q_p64_x2); + test_vld1q_p64_x3(p64, 6, poly64x2x3_t, vst1q_p64_x3, vld1q_p64_x3); + test_vld1q_p64_x4(p64, 8, poly64x2x4_t, vst1q_p64_x4, vld1q_p64_x4); } - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x2() { - wide_store_load_roundtrip!(u32, 4, uint32x2x2_t, vst1_u32_x2, vld1_u32_x2); + macro_rules! wide_store_load_roundtrip_neon { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon")] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; } - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x3() { - wide_store_load_roundtrip!(u32, 6, uint32x2x3_t, vst1_u32_x3, vld1_u32_x3); - } + wide_store_load_roundtrip_neon! { + test_vld1_f32_x2(f32, 4, float32x2x2_t, vst1_f32_x2, vld1_f32_x2); + test_vld1_f32_x3(f32, 6, float32x2x3_t, vst1_f32_x3, vld1_f32_x3); + test_vld1_f32_x4(f32, 8, float32x2x4_t, vst1_f32_x4, vld1_f32_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x4() { - wide_store_load_roundtrip!(u32, 8, uint32x2x4_t, vst1_u32_x4, vld1_u32_x4); - } + test_vld1q_f32_x2(f32, 8, float32x4x2_t, vst1q_f32_x2, vld1q_f32_x2); + test_vld1q_f32_x3(f32, 12, float32x4x3_t, vst1q_f32_x3, vld1q_f32_x3); + test_vld1q_f32_x4(f32, 16, float32x4x4_t, vst1q_f32_x4, vld1q_f32_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x2() { - wide_store_load_roundtrip!(u32, 8, uint32x4x2_t, vst1q_u32_x2, vld1q_u32_x2); - } + test_vld1_s8_x2(i8, 16, int8x8x2_t, vst1_s8_x2, vld1_s8_x2); + test_vld1_s8_x3(i8, 24, int8x8x3_t, vst1_s8_x3, vld1_s8_x3); + test_vld1_s8_x4(i8, 32, int8x8x4_t, vst1_s8_x4, vld1_s8_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x3() { - wide_store_load_roundtrip!(u32, 12, uint32x4x3_t, vst1q_u32_x3, vld1q_u32_x3); - } + test_vld1q_s8_x2(i8, 32, int8x16x2_t, vst1q_s8_x2, vld1q_s8_x2); + test_vld1q_s8_x3(i8, 48, int8x16x3_t, vst1q_s8_x3, vld1q_s8_x3); + test_vld1q_s8_x4(i8, 64, int8x16x4_t, vst1q_s8_x4, vld1q_s8_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x4() { - wide_store_load_roundtrip!(u32, 16, uint32x4x4_t, vst1q_u32_x4, vld1q_u32_x4); - } + test_vld1_s16_x2(i16, 8, int16x4x2_t, vst1_s16_x2, vld1_s16_x2); + test_vld1_s16_x3(i16, 12, int16x4x3_t, vst1_s16_x3, vld1_s16_x3); + test_vld1_s16_x4(i16, 16, int16x4x4_t, vst1_s16_x4, vld1_s16_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x2() { - wide_store_load_roundtrip!(u64, 2, uint64x1x2_t, vst1_u64_x2, vld1_u64_x2); - } + test_vld1q_s16_x2(i16, 16, int16x8x2_t, vst1q_s16_x2, vld1q_s16_x2); + test_vld1q_s16_x3(i16, 24, int16x8x3_t, vst1q_s16_x3, vld1q_s16_x3); + test_vld1q_s16_x4(i16, 32, int16x8x4_t, vst1q_s16_x4, vld1q_s16_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x3() { - wide_store_load_roundtrip!(u64, 3, uint64x1x3_t, vst1_u64_x3, vld1_u64_x3); - } + test_vld1_s32_x2(i32, 4, int32x2x2_t, vst1_s32_x2, vld1_s32_x2); + test_vld1_s32_x3(i32, 6, int32x2x3_t, vst1_s32_x3, vld1_s32_x3); + test_vld1_s32_x4(i32, 8, int32x2x4_t, vst1_s32_x4, vld1_s32_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x4() { - wide_store_load_roundtrip!(u64, 4, uint64x1x4_t, vst1_u64_x4, vld1_u64_x4); - } + test_vld1q_s32_x2(i32, 8, int32x4x2_t, vst1q_s32_x2, vld1q_s32_x2); + test_vld1q_s32_x3(i32, 12, int32x4x3_t, vst1q_s32_x3, vld1q_s32_x3); + test_vld1q_s32_x4(i32, 16, int32x4x4_t, vst1q_s32_x4, vld1q_s32_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x2() { - wide_store_load_roundtrip!(u64, 4, uint64x2x2_t, vst1q_u64_x2, vld1q_u64_x2); - } + test_vld1_s64_x2(i64, 2, int64x1x2_t, vst1_s64_x2, vld1_s64_x2); + test_vld1_s64_x3(i64, 3, int64x1x3_t, vst1_s64_x3, vld1_s64_x3); + test_vld1_s64_x4(i64, 4, int64x1x4_t, vst1_s64_x4, vld1_s64_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x3() { - wide_store_load_roundtrip!(u64, 6, uint64x2x3_t, vst1q_u64_x3, vld1q_u64_x3); - } + test_vld1q_s64_x2(i64, 4, int64x2x2_t, vst1q_s64_x2, vld1q_s64_x2); + test_vld1q_s64_x3(i64, 6, int64x2x3_t, vst1q_s64_x3, vld1q_s64_x3); + test_vld1q_s64_x4(i64, 8, int64x2x4_t, vst1q_s64_x4, vld1q_s64_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x4() { - wide_store_load_roundtrip!(u64, 8, uint64x2x4_t, vst1q_u64_x4, vld1q_u64_x4); - } + test_vld1_u8_x2(u8, 16, uint8x8x2_t, vst1_u8_x2, vld1_u8_x2); + test_vld1_u8_x3(u8, 24, uint8x8x3_t, vst1_u8_x3, vld1_u8_x3); + test_vld1_u8_x4(u8, 32, uint8x8x4_t, vst1_u8_x4, vld1_u8_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x2() { - wide_store_load_roundtrip!(p8, 16, poly8x8x2_t, vst1_p8_x2, vld1_p8_x2); - } + test_vld1q_u8_x2(u8, 32, uint8x16x2_t, vst1q_u8_x2, vld1q_u8_x2); + test_vld1q_u8_x3(u8, 48, uint8x16x3_t, vst1q_u8_x3, vld1q_u8_x3); + test_vld1q_u8_x4(u8, 64, uint8x16x4_t, vst1q_u8_x4, vld1q_u8_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x3() { - wide_store_load_roundtrip!(p8, 24, poly8x8x3_t, vst1_p8_x3, vld1_p8_x3); - } + test_vld1_u16_x2(u16, 8, uint16x4x2_t, vst1_u16_x2, vld1_u16_x2); + test_vld1_u16_x3(u16, 12, uint16x4x3_t, vst1_u16_x3, vld1_u16_x3); + test_vld1_u16_x4(u16, 16, uint16x4x4_t, vst1_u16_x4, vld1_u16_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x4() { - wide_store_load_roundtrip!(p8, 32, poly8x8x4_t, vst1_p8_x4, vld1_p8_x4); - } + test_vld1q_u16_x2(u16, 16, uint16x8x2_t, vst1q_u16_x2, vld1q_u16_x2); + test_vld1q_u16_x3(u16, 24, uint16x8x3_t, vst1q_u16_x3, vld1q_u16_x3); + test_vld1q_u16_x4(u16, 32, uint16x8x4_t, vst1q_u16_x4, vld1q_u16_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x2() { - wide_store_load_roundtrip!(p8, 32, poly8x16x2_t, vst1q_p8_x2, vld1q_p8_x2); - } + test_vld1_u32_x2(u32, 4, uint32x2x2_t, vst1_u32_x2, vld1_u32_x2); + test_vld1_u32_x3(u32, 6, uint32x2x3_t, vst1_u32_x3, vld1_u32_x3); + test_vld1_u32_x4(u32, 8, uint32x2x4_t, vst1_u32_x4, vld1_u32_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x3() { - wide_store_load_roundtrip!(p8, 48, poly8x16x3_t, vst1q_p8_x3, vld1q_p8_x3); - } + test_vld1q_u32_x2(u32, 8, uint32x4x2_t, vst1q_u32_x2, vld1q_u32_x2); + test_vld1q_u32_x3(u32, 12, uint32x4x3_t, vst1q_u32_x3, vld1q_u32_x3); + test_vld1q_u32_x4(u32, 16, uint32x4x4_t, vst1q_u32_x4, vld1q_u32_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x4() { - wide_store_load_roundtrip!(p8, 64, poly8x16x4_t, vst1q_p8_x4, vld1q_p8_x4); - } + test_vld1_u64_x2(u64, 2, uint64x1x2_t, vst1_u64_x2, vld1_u64_x2); + test_vld1_u64_x3(u64, 3, uint64x1x3_t, vst1_u64_x3, vld1_u64_x3); + test_vld1_u64_x4(u64, 4, uint64x1x4_t, vst1_u64_x4, vld1_u64_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x2() { - wide_store_load_roundtrip!(p16, 8, poly16x4x2_t, vst1_p16_x2, vld1_p16_x2); - } + test_vld1q_u64_x2(u64, 4, uint64x2x2_t, vst1q_u64_x2, vld1q_u64_x2); + test_vld1q_u64_x3(u64, 6, uint64x2x3_t, vst1q_u64_x3, vld1q_u64_x3); + test_vld1q_u64_x4(u64, 8, uint64x2x4_t, vst1q_u64_x4, vld1q_u64_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x3() { - wide_store_load_roundtrip!(p16, 12, poly16x4x3_t, vst1_p16_x3, vld1_p16_x3); - } + test_vld1_p8_x2(p8, 16, poly8x8x2_t, vst1_p8_x2, vld1_p8_x2); + test_vld1_p8_x3(p8, 24, poly8x8x3_t, vst1_p8_x3, vld1_p8_x3); + test_vld1_p8_x4(p8, 32, poly8x8x4_t, vst1_p8_x4, vld1_p8_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x4() { - wide_store_load_roundtrip!(p16, 16, poly16x4x4_t, vst1_p16_x4, vld1_p16_x4); - } + test_vld1q_p8_x2(p8, 32, poly8x16x2_t, vst1q_p8_x2, vld1q_p8_x2); + test_vld1q_p8_x3(p8, 48, poly8x16x3_t, vst1q_p8_x3, vld1q_p8_x3); + test_vld1q_p8_x4(p8, 64, poly8x16x4_t, vst1q_p8_x4, vld1q_p8_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x2() { - wide_store_load_roundtrip!(p16, 16, poly16x8x2_t, vst1q_p16_x2, vld1q_p16_x2); - } + test_vld1_p16_x2(p16, 8, poly16x4x2_t, vst1_p16_x2, vld1_p16_x2); + test_vld1_p16_x3(p16, 12, poly16x4x3_t, vst1_p16_x3, vld1_p16_x3); + test_vld1_p16_x4(p16, 16, poly16x4x4_t, vst1_p16_x4, vld1_p16_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x3() { - wide_store_load_roundtrip!(p16, 24, poly16x8x3_t, vst1q_p16_x3, vld1q_p16_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x4() { - wide_store_load_roundtrip!(p16, 32, poly16x8x4_t, vst1q_p16_x4, vld1q_p16_x4); + test_vld1q_p16_x2(p16, 16, poly16x8x2_t, vst1q_p16_x2, vld1q_p16_x2); + test_vld1q_p16_x3(p16, 24, poly16x8x3_t, vst1q_p16_x3, vld1q_p16_x3); + test_vld1q_p16_x4(p16, 32, poly16x8x4_t, vst1q_p16_x4, vld1q_p16_x4); } } From 141a867b02e090c432895779812948f2c354efa7 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Feb 2026 01:40:06 +0100 Subject: [PATCH 18/47] Revert "Use LLVM intrinsics for `madd` intrinsics" This reverts commit 32146718741ee22ff0d54d21b9ab60353014c980. --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 26 +++----- .../crates/core_arch/src/x86/avx512bw.rs | 64 ++++++++++--------- .../stdarch/crates/core_arch/src/x86/sse2.rs | 26 +++----- 3 files changed, 53 insertions(+), 63 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 83aef753c9d93..8e9a56bb85189 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -1841,20 +1841,14 @@ pub const fn _mm256_inserti128_si256(a: __m256i, b: __m128i) -> #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpmaddwd))] #[stable(feature = "simd_x86", since = "1.27.0")] -pub fn _mm256_madd_epi16(a: __m256i, b: __m256i) -> __m256i { - // It's a trick used in the Adler-32 algorithm to perform a widening addition. - // - // ```rust - // #[target_feature(enable = "avx2")] - // unsafe fn widening_add(mad: __m256i) -> __m256i { - // _mm256_madd_epi16(mad, _mm256_set1_epi16(1)) - // } - // ``` - // - // If we implement this using generic vector intrinsics, the optimizer - // will eliminate this pattern, and `vpmaddwd` will no longer be emitted. - // For this reason, we use x86 intrinsics. - unsafe { transmute(pmaddwd(a.as_i16x16(), b.as_i16x16())) } +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_madd_epi16(a: __m256i, b: __m256i) -> __m256i { + unsafe { + let r: i32x16 = simd_mul(simd_cast(a.as_i16x16()), simd_cast(b.as_i16x16())); + let even: i32x8 = simd_shuffle!(r, r, [0, 2, 4, 6, 8, 10, 12, 14]); + let odd: i32x8 = simd_shuffle!(r, r, [1, 3, 5, 7, 9, 11, 13, 15]); + simd_add(even, odd).as_m256i() + } } /// Vertically multiplies each unsigned 8-bit integer from `a` with the @@ -3819,8 +3813,6 @@ pub const fn _mm256_extract_epi16(a: __m256i) -> i32 { #[allow(improper_ctypes)] unsafe extern "C" { - #[link_name = "llvm.x86.avx2.pmadd.wd"] - fn pmaddwd(a: i16x16, b: i16x16) -> i32x8; #[link_name = "llvm.x86.avx2.pmadd.ub.sw"] fn pmaddubsw(a: u8x32, b: i8x32) -> i16x16; #[link_name = "llvm.x86.avx2.mpsadbw"] @@ -4669,7 +4661,7 @@ mod tests { } #[simd_test(enable = "avx2")] - fn test_mm256_madd_epi16() { + const fn test_mm256_madd_epi16() { let a = _mm256_set1_epi16(2); let b = _mm256_set1_epi16(4); let r = _mm256_madd_epi16(a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 8e074fdcfa486..e2d12cd97264b 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -6321,20 +6321,22 @@ pub const unsafe fn _mm_mask_storeu_epi8(mem_addr: *mut i8, mask: __mmask16, a: #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { - // It's a trick used in the Adler-32 algorithm to perform a widening addition. - // - // ```rust - // #[target_feature(enable = "avx512bw")] - // unsafe fn widening_add(mad: __m512i) -> __m512i { - // _mm512_madd_epi16(mad, _mm512_set1_epi16(1)) - // } - // ``` - // - // If we implement this using generic vector intrinsics, the optimizer - // will eliminate this pattern, and `vpmaddwd` will no longer be emitted. - // For this reason, we use x86 intrinsics. - unsafe { transmute(vpmaddwd(a.as_i16x32(), b.as_i16x32())) } +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { + unsafe { + let r: i32x32 = simd_mul(simd_cast(a.as_i16x32()), simd_cast(b.as_i16x32())); + let even: i32x16 = simd_shuffle!( + r, + r, + [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30] + ); + let odd: i32x16 = simd_shuffle!( + r, + r, + [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31] + ); + simd_add(even, odd).as_m512i() + } } /// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -6344,7 +6346,8 @@ pub fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { unsafe { let madd = _mm512_madd_epi16(a, b).as_i32x16(); transmute(simd_select_bitmask(k, madd, src.as_i32x16())) @@ -6358,7 +6361,8 @@ pub fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { unsafe { let madd = _mm512_madd_epi16(a, b).as_i32x16(); transmute(simd_select_bitmask(k, madd, i32x16::ZERO)) @@ -6372,7 +6376,8 @@ pub fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { unsafe { let madd = _mm256_madd_epi16(a, b).as_i32x8(); transmute(simd_select_bitmask(k, madd, src.as_i32x8())) @@ -6386,7 +6391,8 @@ pub fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { unsafe { let madd = _mm256_madd_epi16(a, b).as_i32x8(); transmute(simd_select_bitmask(k, madd, i32x8::ZERO)) @@ -6400,7 +6406,8 @@ pub fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let madd = _mm_madd_epi16(a, b).as_i32x4(); transmute(simd_select_bitmask(k, madd, src.as_i32x4())) @@ -6414,7 +6421,8 @@ pub fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let madd = _mm_madd_epi16(a, b).as_i32x4(); transmute(simd_select_bitmask(k, madd, i32x4::ZERO)) @@ -12574,8 +12582,6 @@ unsafe extern "C" { #[link_name = "llvm.x86.avx512.pmul.hr.sw.512"] fn vpmulhrsw(a: i16x32, b: i16x32) -> i16x32; - #[link_name = "llvm.x86.avx512.pmaddw.d.512"] - fn vpmaddwd(a: i16x32, b: i16x32) -> i32x16; #[link_name = "llvm.x86.avx512.pmaddubs.w.512"] fn vpmaddubsw(a: u8x64, b: i8x64) -> i16x32; @@ -17500,7 +17506,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - fn test_mm512_madd_epi16() { + const fn test_mm512_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_madd_epi16(a, b); @@ -17509,7 +17515,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - fn test_mm512_mask_madd_epi16() { + const fn test_mm512_mask_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_mask_madd_epi16(a, 0, a, b); @@ -17537,7 +17543,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - fn test_mm512_maskz_madd_epi16() { + const fn test_mm512_maskz_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_maskz_madd_epi16(0, a, b); @@ -17548,7 +17554,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - fn test_mm256_mask_madd_epi16() { + const fn test_mm256_mask_madd_epi16() { let a = _mm256_set1_epi16(1); let b = _mm256_set1_epi16(1); let r = _mm256_mask_madd_epi16(a, 0, a, b); @@ -17568,7 +17574,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - fn test_mm256_maskz_madd_epi16() { + const fn test_mm256_maskz_madd_epi16() { let a = _mm256_set1_epi16(1); let b = _mm256_set1_epi16(1); let r = _mm256_maskz_madd_epi16(0, a, b); @@ -17579,7 +17585,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - fn test_mm_mask_madd_epi16() { + const fn test_mm_mask_madd_epi16() { let a = _mm_set1_epi16(1); let b = _mm_set1_epi16(1); let r = _mm_mask_madd_epi16(a, 0, a, b); @@ -17590,7 +17596,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - fn test_mm_maskz_madd_epi16() { + const fn test_mm_maskz_madd_epi16() { let a = _mm_set1_epi16(1); let b = _mm_set1_epi16(1); let r = _mm_maskz_madd_epi16(0, a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs index f339a003df4d1..ecd478511b064 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs @@ -210,20 +210,14 @@ pub const fn _mm_avg_epu16(a: __m128i, b: __m128i) -> __m128i { #[target_feature(enable = "sse2")] #[cfg_attr(test, assert_instr(pmaddwd))] #[stable(feature = "simd_x86", since = "1.27.0")] -pub fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i { - // It's a trick used in the Adler-32 algorithm to perform a widening addition. - // - // ```rust - // #[target_feature(enable = "sse2")] - // unsafe fn widening_add(mad: __m128i) -> __m128i { - // _mm_madd_epi16(mad, _mm_set1_epi16(1)) - // } - // ``` - // - // If we implement this using generic vector intrinsics, the optimizer - // will eliminate this pattern, and `pmaddwd` will no longer be emitted. - // For this reason, we use x86 intrinsics. - unsafe { transmute(pmaddwd(a.as_i16x8(), b.as_i16x8())) } +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i { + unsafe { + let r: i32x8 = simd_mul(simd_cast(a.as_i16x8()), simd_cast(b.as_i16x8())); + let even: i32x4 = simd_shuffle!(r, r, [0, 2, 4, 6]); + let odd: i32x4 = simd_shuffle!(r, r, [1, 3, 5, 7]); + simd_add(even, odd).as_m128i() + } } /// Compares packed 16-bit integers in `a` and `b`, and returns the packed @@ -3193,8 +3187,6 @@ unsafe extern "C" { fn lfence(); #[link_name = "llvm.x86.sse2.mfence"] fn mfence(); - #[link_name = "llvm.x86.sse2.pmadd.wd"] - fn pmaddwd(a: i16x8, b: i16x8) -> i32x4; #[link_name = "llvm.x86.sse2.psad.bw"] fn psadbw(a: u8x16, b: u8x16) -> u64x2; #[link_name = "llvm.x86.sse2.psll.w"] @@ -3473,7 +3465,7 @@ mod tests { } #[simd_test(enable = "sse2")] - fn test_mm_madd_epi16() { + const fn test_mm_madd_epi16() { let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); let b = _mm_setr_epi16(9, 10, 11, 12, 13, 14, 15, 16); let r = _mm_madd_epi16(a, b); From f5540adde9c7a731b1a5bac4b8157975910a54d6 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Feb 2026 01:52:52 +0100 Subject: [PATCH 19/47] add test for multiply by one pattern --- library/stdarch/crates/core_arch/src/x86/avx2.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 8e9a56bb85189..e9463d4331807 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -4669,6 +4669,16 @@ mod tests { assert_eq_m256i(r, e); } + #[target_feature(enable = "avx2")] + #[cfg_attr(test, assert_instr(vpmaddwd))] + unsafe fn test_mm256_madd_epi16_mul_one(mad: __m256i) -> __m256i { + // This is a trick used in the adler32 algorithm to get a widening addition. The + // multiplication by 1 is trivial, but must not be optimized out because then the vpmaddwd + // instruction is no longer selected. The assert_instr verifies that this is the case. + let one_v = _mm256_set1_epi16(1); + _mm256_madd_epi16(mad, one_v) + } + #[simd_test(enable = "avx2")] const fn test_mm256_inserti128_si256() { let a = _mm256_setr_epi64x(1, 2, 3, 4); From 7b62d97abdd38850621153e806cc7b0ee6ab4289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 17 Jan 2026 00:19:20 +0000 Subject: [PATCH 20/47] Mention implicit bounds from `#[derive(Clone)]` on moved value When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the `derive(Clone)` doesn't apply: ``` note: if `TypedAddress` implemented `Clone`, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] | ----- derived `Clone` adds implicit bounds on type parameters LL | pub struct TypedAddress{ | ^^^^^^^^^^^^^^^^^^^^^^^^-^ | | | | | introduces an implicit `T: Clone` bound | consider manually implementing `Clone` for this type ... LL | let old = self.return_value(offset); | ------ you could clone this value ``` --- .../src/diagnostics/conflict_errors.rs | 37 +++++++++++++++++- .../borrowck/derive-clone-implicit-bound.rs | 32 ++++++++++++++++ .../derive-clone-implicit-bound.stderr | 38 +++++++++++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 tests/ui/borrowck/derive-clone-implicit-bound.rs create mode 100644 tests/ui/borrowck/derive-clone-implicit-bound.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index caf6a86af098a..692ce240e36f8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1256,7 +1256,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning_inner(err, ty, expr); } } else if let ty::Adt(def, args) = ty.kind() - && def.did().as_local().is_some() + && let Some(local_did) = def.did().as_local() && def.variants().iter().all(|variant| { variant .fields @@ -1266,7 +1266,40 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { { let ty_span = self.infcx.tcx.def_span(def.did()); let mut span: MultiSpan = ty_span.into(); - span.push_span_label(ty_span, "consider implementing `Clone` for this type"); + let mut derive_clone = false; + self.infcx.tcx.for_each_relevant_impl( + self.infcx.tcx.lang_items().clone_trait().unwrap(), + ty, + |def_id| { + if self.infcx.tcx.is_automatically_derived(def_id) { + derive_clone = true; + span.push_span_label( + self.infcx.tcx.def_span(def_id), + "derived `Clone` adds implicit bounds on type parameters", + ); + if let Some(generics) = self.infcx.tcx.hir_get_generics(local_did) { + for param in generics.params { + if let hir::GenericParamKind::Type { .. } = param.kind { + span.push_span_label( + param.span, + format!( + "introduces an implicit `{}: Clone` bound", + param.name.ident() + ), + ); + } + } + } + } + }, + ); + span.push_span_label( + ty_span, + format!( + "consider {}implementing `Clone` for this type", + if derive_clone { "manually " } else { "" } + ), + ); span.push_span_label(expr.span, "you could clone this value"); err.span_note( span, diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs new file mode 100644 index 0000000000000..a20e04d3afdce --- /dev/null +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -0,0 +1,32 @@ +// Issue #108894 + +use std::marker::PhantomData; + +#[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters +pub struct TypedAddress{ +//~^ NOTE if `TypedAddress` implemented `Clone`, you could clone the value +//~| NOTE consider manually implementing `Clone` for this type +//~| NOTE introduces an implicit `T: Clone` bound + inner: u64, + phantom: PhantomData, +} + +pub trait Memory { + fn write_value(&self, offset: TypedAddress, value: &T); + fn return_value(&self, offset: TypedAddress) -> T; + //~^ NOTE consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + //~| NOTE in this method + //~| NOTE this parameter takes ownership of the value + fn update_value(&self, offset: TypedAddress, update: F) + //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait + where F: FnOnce(T) -> T + { + let old = self.return_value(offset); //~ NOTE value moved here + //~^ NOTE you could clone this value + let new = update(old); + self.write_value(offset, &new); //~ ERROR use of moved value: `offset` + //~^ NOTE value used here after move + } +} + +fn main() {} diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr new file mode 100644 index 0000000000000..b10e3a92c96b0 --- /dev/null +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -0,0 +1,38 @@ +error[E0382]: use of moved value: `offset` + --> $DIR/derive-clone-implicit-bound.rs:27:26 + | +LL | fn update_value(&self, offset: TypedAddress, update: F) + | ------ move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait +... +LL | let old = self.return_value(offset); + | ------ value moved here +... +LL | self.write_value(offset, &new); + | ^^^^^^ value used here after move + | +note: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + --> $DIR/derive-clone-implicit-bound.rs:16:39 + | +LL | fn return_value(&self, offset: TypedAddress) -> T; + | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value +note: if `TypedAddress` implemented `Clone`, you could clone the value + --> $DIR/derive-clone-implicit-bound.rs:6:1 + | +LL | #[derive(Clone, Copy)] + | ----- derived `Clone` adds implicit bounds on type parameters +LL | pub struct TypedAddress{ + | ^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | | + | | introduces an implicit `T: Clone` bound + | consider manually implementing `Clone` for this type +... +LL | let old = self.return_value(offset); + | ------ you could clone this value +help: consider further restricting type parameter `T` with trait `Copy` + | +LL | where F: FnOnce(T) -> T, T: Copy + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. From 679f38c1259d96463c5f04f175846501fbca2a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 02:29:33 +0000 Subject: [PATCH 21/47] On E0277 pointing at bound in derive, suggest manual impl When encountering a bound coming from a derive macro, suggest manual impl of the trait. Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself. ``` error[E0277]: can't compare `SomeNode` with `SomeNode` --> f29.rs:24:15 | 24 | accept_eq(&node); | --------- ^^^^^ no implementation for `SomeNode == SomeNode` | | | required by a bound introduced by this call | = note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs:279:39 = help: the trait `PartialEq` is not implemented for `SomeNode` note: required for `Id` to implement `PartialEq` --> f29.rs:3:10 | 3 | #[derive(PartialEq, Eq)] | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro 4 | pub struct Id(PhantomData); | - = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> f29.rs:15:23 | 15 | fn accept_eq(_: &impl PartialEq) { } | ^^^^^^^^^ required by this bound in `accept_eq` help: consider annotating `SomeNode` with `#[derive(PartialEq)]` | 13 + #[derive(PartialEq)] 14 | struct SomeNode(); | ``` --- .../src/deriving/generic/mod.rs | 18 +++++----- compiler/rustc_hir/src/hir.rs | 11 ++++-- compiler/rustc_middle/src/ty/diagnostics.rs | 15 ++++---- .../src/error_reporting/traits/suggestions.rs | 8 +++++ tests/ui/associated-types/issue-38821.stderr | 3 ++ .../unsizing-wfcheck-issue-126272.stderr | 6 +++- .../ui/consts/const-blocks/trait-error.stderr | 5 ++- tests/ui/derives/deriving-copyclone.stderr | 15 ++++++-- .../impl_bounds.stderr | 10 ++++-- .../issue-104884-trait-impl-sugg-err.stderr | 6 +++- ...missing-bound-in-derive-copy-impl-2.stderr | 2 ++ .../missing-bound-in-derive-copy-impl.stderr | 2 ++ tests/ui/traits/derive-implicit-bound.rs | 34 +++++++++++++++++++ tests/ui/traits/derive-implicit-bound.stderr | 31 +++++++++++++++++ 14 files changed, 140 insertions(+), 26 deletions(-) create mode 100644 tests/ui/traits/derive-implicit-bound.rs create mode 100644 tests/ui/traits/derive-implicit-bound.stderr diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index c2260a4590975..665e0ddab1949 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -638,27 +638,27 @@ impl<'a> TraitDef<'a> { GenericParamKind::Type { .. } => { // Extra restrictions on the generics parameters to the // type being derived upon. + let span = param.ident.span.with_ctxt(ctxt); let bounds: Vec<_> = self .additional_bounds .iter() .map(|p| { - cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), - self.is_const, - ) + cx.trait_bound(p.to_path(cx, span, type_ident, generics), self.is_const) }) .chain( // Add a bound for the current trait. - self.skip_path_as_bound - .not() - .then(|| cx.trait_bound(trait_path.clone(), self.is_const)), + self.skip_path_as_bound.not().then(|| { + let mut trait_path = trait_path.clone(); + trait_path.span = span; + cx.trait_bound(trait_path, self.is_const) + }), ) .chain({ // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { let p = deriving::path_std!(marker::Copy); Some(cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), + p.to_path(cx, span, type_ident, generics), self.is_const, )) } else { @@ -671,7 +671,7 @@ impl<'a> TraitDef<'a> { ) .collect(); - cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None) + cx.typaram(span, param.ident, bounds, None) } GenericParamKind::Const { ty, span, .. } => { let const_nodefault_kind = GenericParamKind::Const { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c1bcffa1cf4c..b117fa8327296 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,7 @@ // ignore-tidy-filelength use std::borrow::Cow; use std::fmt; +use std::ops::Not; use rustc_abi::ExternAbi; use rustc_ast::attr::AttributeExt; @@ -1012,10 +1013,14 @@ impl<'hir> Generics<'hir> { span_for_parentheses.map_or_else( || { - // We include bounds that come from a `#[derive(_)]` but point at the user's code, - // as we use this method to get a span appropriate for suggestions. + // We include bounds that come from a `#[derive(_)]` but point at the user's + // code, as we use this method to get a span appropriate for suggestions. let bs = bound.span(); - bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None)) + // We use `from_expansion` instead of `can_be_used_for_suggestions` because + // the trait bound from imperfect derives do point at the type parameter, + // but expanded to a where clause, so we want to ignore those. This is only + // true for derive intrinsics. + bs.from_expansion().not().then(|| (bs.shrink_to_hi(), None)) }, |span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))), ) diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 279c34cb275d9..b3b06314e1a0f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -526,12 +526,15 @@ pub fn suggest_constraining_type_params<'a>( // // fn foo(t: T) { ... } // - help: consider restricting this type parameter with `T: Foo` - suggestions.push(( - param.span.shrink_to_hi(), - post, - format!(": {constraint}"), - SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, - )); + let span = param.span.shrink_to_hi(); + if span.can_be_used_for_suggestions() { + suggestions.push(( + span, + post, + format!(": {constraint}"), + SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, + )); + } } // FIXME: remove the suggestions that are from derive, as the span is not correct diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index d54f3812350d9..94876c6dd89f2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3586,6 +3586,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } spans.push(self_ty.span); let mut spans: MultiSpan = spans.into(); + let mut derived = false; if matches!( self_ty.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _) @@ -3593,6 +3594,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind), Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { + derived = true; spans.push_span_label( data.span, "unsatisfied trait bound introduced in this `derive` macro", @@ -3621,6 +3623,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.span_note(spans, msg); + if derived { + err.help(format!( + "consider manually implementing `{trait_name}` to avoid undesired \ + bounds", + )); + } point_at_assoc_type_restriction( tcx, err, diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 01329f69c3bef..3c5f67fee26a9 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -102,6 +102,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, @@ -146,6 +147,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, @@ -219,6 +221,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index aecd97ef7763c..ea411741536f5 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -65,6 +65,7 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^^^^ LL | struct Bar(T); | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` = note: required for the cast from `&&&'static Bar<(dyn Debug + 'static)>` to `&dyn Debug` @@ -96,7 +97,10 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ unsatisfied trait bound introduced in this `derive` macro + | ^^ +LL | struct Bar(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` note: required by a bound in `std::cmp::AssertParamIsEq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 601d067e3d849..1e66daa7132d8 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,7 +8,10 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Foo(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block | diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index befff8802804e..f4cd4cff7f444 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,7 +10,10 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | @@ -33,7 +36,10 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 | @@ -56,7 +62,10 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 7847bbd813cd5..d6a794fa0b19e 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,7 +32,10 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Fooy(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 | @@ -56,7 +59,10 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Fooy(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 | diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index b7aed4a8485a8..93fd2df0398e4 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,7 +37,11 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^^ +... +LL | struct PriorityQueue(BinaryHeap>); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index a48dd30d008a6..2b8c6baeeafe2 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -30,6 +30,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` | @@ -71,6 +72,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 645d6ebb3961f..2bd56b7688f40 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -65,6 +65,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` | @@ -134,6 +135,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { diff --git a/tests/ui/traits/derive-implicit-bound.rs b/tests/ui/traits/derive-implicit-bound.rs new file mode 100644 index 0000000000000..22fb68f37c5c4 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound.rs @@ -0,0 +1,34 @@ +// Second case reported in issue #108894. + +use std::marker::PhantomData; + +#[derive(PartialEq, Eq)] +pub struct Id(PhantomData); + +// manual implementation which would break the usage of const patterns +// impl PartialEq for Id { fn eq(&self, _: &Id) -> bool { true } } +// impl Eq for Id {} + +// This derive is undesired but cannot be removed without +// breaking the usages below +// #[derive(PartialEq, Eq)] +struct SomeNode(); + +fn accept_eq(_: &impl PartialEq) { } + +fn main() { + let node = Id::(PhantomData); + + // this will only work if + // - `Partial/Eq` is implemented manually, or + // - `SomeNode` also needlessly(?) implements `Partial/Eq` + accept_eq(&node); //~ ERROR can't compare `SomeNode` with `SomeNode` + + const CONST_ID: Id:: = Id::(PhantomData); + // this will work only when `Partial/Eq` is being derived + // otherwise: error: to use a constant of type `Id` in a pattern, + // `Id` must be annotated with `#[derive(PartialEq, Eq)]` + match node { + CONST_ID => {} + } +} diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr new file mode 100644 index 0000000000000..9805835bb07f5 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -0,0 +1,31 @@ +error[E0277]: can't compare `SomeNode` with `SomeNode` + --> $DIR/derive-implicit-bound.rs:25:15 + | +LL | accept_eq(&node); + | --------- ^^^^^ no implementation for `SomeNode == SomeNode` + | | + | required by a bound introduced by this call + | + = help: the trait `PartialEq` is not implemented for `SomeNode` +note: required for `Id` to implement `PartialEq` + --> $DIR/derive-implicit-bound.rs:5:10 + | +LL | #[derive(PartialEq, Eq)] + | ^^^^^^^^^ +LL | pub struct Id(PhantomData); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `PartialEq` to avoid undesired bounds +note: required by a bound in `accept_eq` + --> $DIR/derive-implicit-bound.rs:17:23 + | +LL | fn accept_eq(_: &impl PartialEq) { } + | ^^^^^^^^^ required by this bound in `accept_eq` +help: consider annotating `SomeNode` with `#[derive(PartialEq)]` + | +LL + #[derive(PartialEq)] +LL | struct SomeNode(); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 54fe73fd6d3d0b2935977016039ded8d6a0d4772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 05:43:19 +0000 Subject: [PATCH 22/47] Tweak span labels caused by trait bound coming from derive expansion ``` note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { | - would need to be `Copy` ``` --- .../src/error_reporting/traits/suggestions.rs | 12 +++++++++++- tests/ui/associated-types/issue-38821.stderr | 12 ++++++------ .../unsizing-wfcheck-issue-126272.stderr | 8 ++++---- tests/ui/consts/const-blocks/trait-error.stderr | 4 ++-- tests/ui/derives/deriving-copyclone.stderr | 12 ++++++------ tests/ui/generic-associated-types/impl_bounds.stderr | 8 ++++---- .../issue-104884-trait-impl-sugg-err.stderr | 4 ++-- .../missing-bound-in-derive-copy-impl-2.stderr | 8 ++++---- .../missing-bound-in-derive-copy-impl.stderr | 8 ++++---- tests/ui/traits/derive-implicit-bound.stderr | 4 ++-- 10 files changed, 45 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 94876c6dd89f2..c9dc390ea0be8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3595,9 +3595,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { derived = true; + spans.push_span_label( + data.span.ctxt().outer_expn_data().call_site, + format!( + "unsatisfied trait bound introduced in this `derive` macro" + ), + ); spans.push_span_label( data.span, - "unsatisfied trait bound introduced in this `derive` macro", + if data.span.in_derive_expansion() { + format!("would need to be `{trait_name}`") + } else { + format!("") + }, ); } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) { // `Sized` may be an explicit or implicit trait bound. If it is diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 3c5f67fee26a9..11d0c9d514ff5 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -98,10 +98,10 @@ note: required for `ColumnInsertValue` to implement `Debug` --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | @@ -143,10 +143,10 @@ note: required for `ColumnInsertValue` to implement `Copy` --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | @@ -217,10 +217,10 @@ note: required for `ColumnInsertValue` to implement `Clone` --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index ea411741536f5..1aaa7591a7bed 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -62,9 +62,9 @@ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Bar(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -97,9 +97,9 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ + | ^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Bar(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 1e66daa7132d8..991a48917efb8 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,9 +8,9 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Foo(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index f4cd4cff7f444..1baacf85f6a21 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,9 +10,9 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -36,9 +36,9 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -62,9 +62,9 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index d6a794fa0b19e..fd7dd774cf087 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,9 +32,9 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Fooy(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -59,9 +59,9 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Fooy(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index 93fd2df0398e4..c3513e19981fd 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,10 +37,10 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ + | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | struct PriorityQueue(BinaryHeap>); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 2b8c6baeeafe2..800f07054af73 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -27,9 +27,9 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,9 +69,9 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 2bd56b7688f40..3f889f31484b5 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -62,9 +62,9 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -132,9 +132,9 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 9805835bb07f5..275cef7a94fd5 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -11,9 +11,9 @@ note: required for `Id` to implement `PartialEq` --> $DIR/derive-implicit-bound.rs:5:10 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Id(PhantomData); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 From b88fb8a0b0422697a8fe1573598795d7052e936c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 07:22:00 +0000 Subject: [PATCH 23/47] Mention that the trait could be manually impld in E0599 --- compiler/rustc_hir_typeck/src/method/suggest.rs | 5 +++++ tests/ui/derives/derive-assoc-type-not-impl.stderr | 1 + tests/ui/derives/deriving-with-repr-packed-2.stderr | 1 + tests/ui/union/union-derive-clone.stderr | 1 + 4 files changed, 8 insertions(+) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cd25b866b0983..f5ef5adff6bd1 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1748,6 +1748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find all the requirements that come from a local `impl` block. let mut skip_list: UnordSet<_> = Default::default(); let mut spanned_predicates = FxIndexMap::default(); + let mut manually_impl = false; for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. @@ -1798,6 +1799,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); entry.2.push(p); skip_list.insert(p); + manually_impl = true; } // Unmet obligation coming from an `impl`. @@ -2083,6 +2085,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *suggested_derive = self.suggest_derive(err, unsatisfied_predicates); *unsatisfied_bounds = true; } + if manually_impl { + err.help("consider manually implementing the trait to avoid undesired bounds"); + } } /// If an appropriate error source is not found, check method chain for possible candidates diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 13ba80243a5eb..e239ad4ef2091 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -15,6 +15,7 @@ note: trait bound `NotClone: Clone` was not satisfied | LL | #[derive(Clone)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NotClone` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index b62c67d9a9da1..fff6269472bd3 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -25,6 +25,7 @@ note: the following trait bounds were not satisfied: | LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NonCopy` with `#[derive(Clone, Copy)]` | LL + #[derive(Clone, Copy)] diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index 18f862aaa7d6e..65488629b629b 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -29,6 +29,7 @@ note: trait bound `CloneNoCopy: Copy` was not satisfied | LL | #[derive(Clone, Copy)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | LL + #[derive(Clone, Copy)] From 085da0cee4e6de6408c401ea2a807eff6b701307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:23:18 +0000 Subject: [PATCH 24/47] On E0308 caused by cloning a reference due to missing bounds, account for derive On type errors where the difference is expecting an owned type and getting a reference, if the expression is a `.clone()` call and the type is annotated with `#[derive(Clone)]`, we now explain implicit bounds and suggest manually implementing `Clone`. ``` error[E0308]: mismatched types --> $DIR/derive-implicit-bound-on-clone.rs:10:5 | LL | fn clone_me(x: &ContainsRc) -> ContainsRc { | ---------------- expected `ContainsRc` because of return type LL | x.clone() | ^^^^^^^^^ expected `ContainsRc`, found `&ContainsRc` | = note: expected struct `ContainsRc<_, _>` found reference `&ContainsRc<_, _>` note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead --> $DIR/derive-implicit-bound-on-clone.rs:10:5 | LL | x.clone() | ^ help: `Clone` is not implemented because the some trait bounds could not be satisfied --> $DIR/derive-implicit-bound-on-clone.rs:5:19 | LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct ContainsRc { | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` | | | derive introduces an implicit unsatisfied trait bound `T: Clone` = help: consider manually implementing `Clone` to avoid the implict type parameter bounds ``` --- .../src/fn_ctxt/suggestions.rs | 97 ++++++++++++++++--- ...on-ref-due-to-missing-bound.current.stderr | 3 +- ...ll-on-ref-due-to-missing-bound.next.stderr | 3 +- .../traits/derive-implicit-bound-on-clone.rs | 24 +++++ .../derive-implicit-bound-on-clone.stderr | 53 ++++++++++ 5 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 tests/ui/traits/derive-implicit-bound-on-clone.rs create mode 100644 tests/ui/traits/derive-implicit-bound-on-clone.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3e4c194147f9f..285288e87ee00 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1932,25 +1932,96 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ); } else { + let mut suggest_derive = true; if let Some(errors) = self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { + let manually_impl = "consider manually implementing `Clone` to avoid the \ + implict type parameter bounds"; match &errors[..] { [] => {} [error] => { - diag.help(format!( - "`Clone` is not implemented because the trait bound `{}` is \ - not satisfied", - error.obligation.predicate, - )); + // diag.note("{error:#?}"); + // diag.note(format!("{:#?} {:#?} {:#?}", error.obligation, error.obligation.cause, error.obligation.cause.code())); + let msg = "`Clone` is not implemented because a trait bound is not \ + satisfied"; + if let traits::ObligationCauseCode::ImplDerived(data) = + error.obligation.cause.code() + { + let mut span: MultiSpan = data.span.into(); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) { + span.push_span_label( + data.span, + format!( + "derive introduces an implicit `{}` bound", + error.obligation.predicate + ), + ); + } + diag.span_help(span, msg); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(msg); + } } _ => { - diag.help(format!( - "`Clone` is not implemented because the following trait bounds \ - could not be satisfied: {}", - listify(&errors, |e| format!("`{}`", e.obligation.predicate)) - .unwrap(), - )); + let unsatisfied_bounds: Vec<_> = errors + .iter() + .filter_map(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + let pre = if self + .tcx + .is_automatically_derived(data.impl_or_alias_def_id) + { + "derive introduces an implicit " + } else { + "" + }; + Some(( + data.span, + format!( + "{pre}unsatisfied trait bound `{}`", + error.obligation.predicate + ), + )) + } + _ => None, + }) + .collect(); + let msg = "`Clone` is not implemented because the some trait bounds \ + could not be satisfied"; + if errors.len() == unsatisfied_bounds.len() { + let mut unsatisfied_bounds_spans: MultiSpan = unsatisfied_bounds + .iter() + .map(|(span, _)| *span) + .collect::>() + .into(); + for (span, label) in unsatisfied_bounds { + unsatisfied_bounds_spans.push_span_label(span, label); + } + diag.span_help(unsatisfied_bounds_spans, msg); + if errors.iter().all(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + } + _ => false, + }) { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(format!( + "{msg}: {}", + listify(&errors, |e| format!("`{}`", e.obligation.predicate)) + .unwrap(), + )); + } } } for error in errors { @@ -1968,7 +2039,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + if suggest_derive { + self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + } } } } diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr index 301f3c3a458de..5de99cc6ca6ae 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr @@ -13,7 +13,8 @@ note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned i | LL | let mut x: HashSet = v.clone(); | ^ - = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: `Clone` is not implemented because a trait bound is not satisfied + --> $SRC_DIR/std/src/collections/hash/set.rs:LL:COL help: consider annotating `Day` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr index 301f3c3a458de..5de99cc6ca6ae 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr @@ -13,7 +13,8 @@ note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned i | LL | let mut x: HashSet = v.clone(); | ^ - = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: `Clone` is not implemented because a trait bound is not satisfied + --> $SRC_DIR/std/src/collections/hash/set.rs:LL:COL help: consider annotating `Day` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.rs b/tests/ui/traits/derive-implicit-bound-on-clone.rs new file mode 100644 index 0000000000000..a4c9e88ef5765 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound-on-clone.rs @@ -0,0 +1,24 @@ +// Issue #146515 +use std::rc::Rc; + +#[derive(Clone)] +struct ContainsRc { //~ HELP `Clone` is not implemented + value: Rc<(T, K)>, +} + +fn clone_me(x: &ContainsRc) -> ContainsRc { + x.clone() //~ ERROR E0308 + //~^ HELP consider manually implementing `Clone` +} + +#[derive(Clone)] +struct ContainsRcSingle { //~ HELP `Clone` is not implemented + value: Rc, +} + +fn clone_me_single(x: &ContainsRcSingle) -> ContainsRcSingle { + x.clone() //~ ERROR E0308 + //~^ HELP consider manually implementing `Clone` +} + +fn main() {} diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.stderr b/tests/ui/traits/derive-implicit-bound-on-clone.stderr new file mode 100644 index 0000000000000..0cec4ef7c6096 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound-on-clone.stderr @@ -0,0 +1,53 @@ +error[E0308]: mismatched types + --> $DIR/derive-implicit-bound-on-clone.rs:10:5 + | +LL | fn clone_me(x: &ContainsRc) -> ContainsRc { + | ---------------- expected `ContainsRc` because of return type +LL | x.clone() + | ^^^^^^^^^ expected `ContainsRc`, found `&ContainsRc` + | + = note: expected struct `ContainsRc<_, _>` + found reference `&ContainsRc<_, _>` +note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead + --> $DIR/derive-implicit-bound-on-clone.rs:10:5 + | +LL | x.clone() + | ^ +help: `Clone` is not implemented because the some trait bounds could not be satisfied + --> $DIR/derive-implicit-bound-on-clone.rs:5:19 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRc { + | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` + | | + | derive introduces an implicit unsatisfied trait bound `T: Clone` + = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + +error[E0308]: mismatched types + --> $DIR/derive-implicit-bound-on-clone.rs:20:5 + | +LL | fn clone_me_single(x: &ContainsRcSingle) -> ContainsRcSingle { + | ------------------- expected `ContainsRcSingle` because of return type +LL | x.clone() + | ^^^^^^^^^ expected `ContainsRcSingle`, found `&ContainsRcSingle` + | + = note: expected struct `ContainsRcSingle<_>` + found reference `&ContainsRcSingle<_>` +note: `ContainsRcSingle` does not implement `Clone`, so `&ContainsRcSingle` was cloned instead + --> $DIR/derive-implicit-bound-on-clone.rs:20:5 + | +LL | x.clone() + | ^ +help: `Clone` is not implemented because a trait bound is not satisfied + --> $DIR/derive-implicit-bound-on-clone.rs:15:25 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRcSingle { + | ^ derive introduces an implicit `T: Clone` bound + = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From aebf1fdcf9c3b1e7b674499ce10aee43960569a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:40:29 +0000 Subject: [PATCH 25/47] Keep span of type in builtin derive macros expansions --- .../src/deriving/generic/mod.rs | 3 +- tests/ui/associated-types/issue-38821.rs | 4 +- tests/ui/associated-types/issue-38821.stderr | 47 +++++++++++++++---- .../const_param_ty_impl_bad_field.rs | 4 +- .../const_param_ty_impl_bad_field.stderr | 7 ++- .../const_param_ty_impl_no_structural_eq.rs | 8 ++-- ...onst_param_ty_impl_no_structural_eq.stderr | 14 ++++-- .../nested_bad_const_param_ty.rs | 6 +-- .../nested_bad_const_param_ty.stderr | 27 +++++------ .../adt_const_params/unsized_field-1.rs | 6 +-- .../adt_const_params/unsized_field-1.stderr | 27 +++++------ .../unsizing-wfcheck-issue-126272.rs | 2 +- .../unsizing-wfcheck-issue-126272.stderr | 22 ++++++--- .../ui/consts/const-blocks/trait-error.stderr | 7 ++- .../derives/copy-drop-mutually-exclusive.rs | 8 ++-- .../copy-drop-mutually-exclusive.stderr | 12 +++-- tests/ui/derives/deriving-copyclone.stderr | 21 ++++++--- tests/ui/derives/issue-97343.stderr | 9 ++-- ...ith-same-name-and-derive-default-133965.rs | 12 ++--- ...same-name-and-derive-default-133965.stderr | 23 ++++----- ...ultiple-types-with-same-name-and-derive.rs | 12 ++--- ...ple-types-with-same-name-and-derive.stderr | 24 +++++----- tests/ui/error-codes/E0184.rs | 4 +- tests/ui/error-codes/E0184.stderr | 6 ++- .../impl_bounds.stderr | 14 ++++-- tests/ui/issues/issue-27340.rs | 4 +- tests/ui/issues/issue-27340.stderr | 10 ++-- tests/ui/malformed/malformed-derive-entry.rs | 10 ++-- .../malformed/malformed-derive-entry.stderr | 14 ++++-- .../issue-104884-trait-impl-sugg-err.rs | 13 +++-- .../issue-104884-trait-impl-sugg-err.stderr | 20 +++++--- tests/ui/range/range_traits-2.rs | 4 +- tests/ui/range/range_traits-2.stderr | 6 +-- tests/ui/range/range_traits-3.rs | 4 +- tests/ui/range/range_traits-3.stderr | 6 +-- tests/ui/range/range_traits-6.rs | 4 +- tests/ui/range/range_traits-6.stderr | 6 +-- tests/ui/span/E0204.rs | 8 ++-- tests/ui/span/E0204.stderr | 10 ++-- .../ui/suggestions/derive-clone-for-eq.fixed | 4 +- tests/ui/suggestions/derive-clone-for-eq.rs | 4 +- .../ui/suggestions/derive-clone-for-eq.stderr | 6 ++- ...missing-bound-in-derive-copy-impl-2.stderr | 14 ++++-- .../missing-bound-in-derive-copy-impl-3.fixed | 4 +- .../missing-bound-in-derive-copy-impl-3.rs | 4 +- ...missing-bound-in-derive-copy-impl-3.stderr | 17 +++---- .../missing-bound-in-derive-copy-impl.rs | 4 +- .../missing-bound-in-derive-copy-impl.stderr | 19 +++++--- tests/ui/traits/derive-implicit-bound.stderr | 7 ++- tests/ui/traits/issue-106072.rs | 8 ++-- tests/ui/traits/issue-106072.stderr | 15 ++++-- tests/ui/traits/issue-50480.rs | 11 ++--- tests/ui/traits/issue-50480.stderr | 35 +++++++------- .../global-cache-and-parallel-frontend.rs | 4 +- .../global-cache-and-parallel-frontend.stderr | 6 ++- 55 files changed, 347 insertions(+), 263 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 665e0ddab1949..bc86cdbc9f7ef 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -791,7 +791,8 @@ impl<'a> TraitDef<'a> { .collect(); // Create the type of `self`. - let path = cx.path_all(self.span, false, vec![type_ident], self_params); + let path = + cx.path_all(type_ident.span.with_ctxt(ctxt), false, vec![type_ident], self_params); let self_type = cx.ty_path(path); let rustc_const_unstable = cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); diff --git a/tests/ui/associated-types/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs index 5212bc886f0df..35c371235e640 100644 --- a/tests/ui/associated-types/issue-38821.rs +++ b/tests/ui/associated-types/issue-38821.rs @@ -34,11 +34,11 @@ pub trait Column: Expression {} //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied +pub enum ColumnInsertValue where +//~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -pub enum ColumnInsertValue where -//~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied Col: Column, Expr: Expression::Nullable>, //~^ ERROR the trait bound `::SqlType: IntoNullable` is not satisfied diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 11d0c9d514ff5..58d06860fe301 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:40:1 + --> $DIR/issue-38821.rs:37:1 | LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` @@ -82,10 +82,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -98,7 +101,13 @@ note: required for `ColumnInsertValue` to implement `Debug` --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ @@ -127,10 +136,13 @@ LL | Expr: Expression::Nullable>, ::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:17 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ---- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -143,7 +155,13 @@ note: required for `ColumnInsertValue` to implement `Copy` --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ @@ -201,10 +219,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -217,7 +238,13 @@ note: required for `ColumnInsertValue` to implement `Clone` --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs index 0614ea97b1add..1900931b3f35e 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs @@ -8,10 +8,10 @@ struct NotParam; struct CantParam(NotParam); impl std::marker::ConstParamTy_ for CantParam {} -//~^ error: the trait `ConstParamTy_` cannot be implemented for this type +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(std::marker::ConstParamTy, Eq, PartialEq)] -//~^ error: the trait `ConstParamTy_` cannot be implemented for this type struct CantParamDerive(NotParam); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr index fd1836802c4ae..084c64d273355 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr @@ -8,13 +8,12 @@ LL | impl std::marker::ConstParamTy_ for CantParam {} | ^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/const_param_ty_impl_bad_field.rs:13:10 + --> $DIR/const_param_ty_impl_bad_field.rs:14:8 | LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | + | ------------------------- in this derive macro expansion LL | struct CantParamDerive(NotParam); - | -------- this field does not implement `ConstParamTy_` + | ^^^^^^^^^^^^^^^ -------- this field does not implement `ConstParamTy_` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs index a1c8eccfb095f..a8f190609c043 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs @@ -8,13 +8,13 @@ impl std::marker::ConstParamTy_ for ImplementsConstParamTy {} struct CantParam(ImplementsConstParamTy); impl std::marker::ConstParamTy_ for CantParam {} -//~^ error: the type `CantParam` does not `#[derive(PartialEq)]` -//~| ERROR the trait bound `CantParam: Eq` is not satisfied +//~^ ERROR: the type `CantParam` does not `#[derive(PartialEq)]` +//~| ERROR: the trait bound `CantParam: Eq` is not satisfied #[derive(std::marker::ConstParamTy)] -//~^ error: the type `CantParamDerive` does not `#[derive(PartialEq)]` -//~| ERROR the trait bound `CantParamDerive: Eq` is not satisfied struct CantParamDerive(ImplementsConstParamTy); +//~^ ERROR: the type `CantParamDerive` does not `#[derive(PartialEq)]` +//~| ERROR: the trait bound `CantParamDerive: Eq` is not satisfied fn check() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr index ca2a693d48ceb..1219d5f04380a 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr @@ -27,10 +27,12 @@ note: required by a bound in `ConstParamTy_` --> $SRC_DIR/core/src/marker.rs:LL:COL error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:8 | LL | #[derive(std::marker::ConstParamTy)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` + | ------------------------- in this derive macro expansion +LL | struct CantParamDerive(ImplementsConstParamTy); + | ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` | note: required by a bound in `ConstParamTy_` --> $SRC_DIR/core/src/marker.rs:LL:COL @@ -41,13 +43,15 @@ LL | struct CantParamDerive(ImplementsConstParamTy); | error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:8 | LL | #[derive(std::marker::ConstParamTy)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | ------------------------- in this derive macro expansion +LL | struct CantParamDerive(ImplementsConstParamTy); + | ^^^^^^^^^^^^^^^ unsatisfied trait bound | help: the nightly-only, unstable trait `StructuralPartialEq` is not implemented for `CantParamDerive` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:17:1 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:1 | LL | struct CantParamDerive(ImplementsConstParamTy); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs index d42ef90e1b180..e8a16be2197b2 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs @@ -4,15 +4,15 @@ use std::marker::ConstParamTy; #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo([*const u8; 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo2([*mut u8; 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo3([fn(); 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr index 442ec6b96cefa..6c8a506d1f40a 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr @@ -1,44 +1,41 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:6:10 + --> $DIR/nested_bad_const_param_ty.rs:7:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo([*const u8; 1]); - | -------------- this field does not implement `ConstParamTy_` + | ^^^ -------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:8:12 + --> $DIR/nested_bad_const_param_ty.rs:7:12 | LL | struct Foo([*const u8; 1]); | ^^^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:10:10 + --> $DIR/nested_bad_const_param_ty.rs:11:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo2([*mut u8; 1]); - | ------------ this field does not implement `ConstParamTy_` + | ^^^^ ------------ this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:12:13 + --> $DIR/nested_bad_const_param_ty.rs:11:13 | LL | struct Foo2([*mut u8; 1]); | ^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:14:10 + --> $DIR/nested_bad_const_param_ty.rs:15:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo3([fn(); 1]); - | --------- this field does not implement `ConstParamTy_` + | ^^^^ --------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:16:13 + --> $DIR/nested_bad_const_param_ty.rs:15:13 | LL | struct Foo3([fn(); 1]); | ^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs index 5db031cb900fc..f2d972612dc64 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs @@ -6,18 +6,18 @@ extern crate unsized_const_param; use std::marker::ConstParamTy; #[derive(ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct A([u8]); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct B(&'static [u8]); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(ConstParamTy, Eq, PartialEq)] struct C(unsized_const_param::Foo); #[derive(std::marker::ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr index 134dbba0d63ab..2538b811618bb 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr @@ -1,44 +1,41 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:8:10 + --> $DIR/unsized_field-1.rs:9:8 | LL | #[derive(ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct A([u8]); - | ---- this field does not implement `ConstParamTy_` + | ^ ---- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[u8]` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:10:10 + --> $DIR/unsized_field-1.rs:9:10 | LL | struct A([u8]); | ^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:12:10 + --> $DIR/unsized_field-1.rs:13:8 | LL | #[derive(ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct B(&'static [u8]); - | ------------- this field does not implement `ConstParamTy_` + | ^ ------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `&'static [u8]` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:14:10 + --> $DIR/unsized_field-1.rs:13:10 | LL | struct B(&'static [u8]); | ^^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:19:10 + --> $DIR/unsized_field-1.rs:20:8 | LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | + | ------------------------- in this derive macro expansion LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); - | ---------------------------------------------------------- this field does not implement `ConstParamTy_` + | ^ ---------------------------------------------------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `GenericNotUnsizedParam<&'static [u8]>` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:21:10 + --> $DIR/unsized_field-1.rs:20:10 | LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs index 500e8e22b0e3d..71ac662cf580e 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs @@ -6,8 +6,8 @@ use std::marker::ConstParamTy; #[derive(Debug, PartialEq, Eq, ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` struct Foo { +//~^ ERROR the trait `ConstParamTy_` nested: &'static Bar, //~^ ERROR the size for values //~| ERROR the size for values diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index 1aaa7591a7bed..f90f0b45d967a 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -19,11 +19,13 @@ LL | struct Bar(T); | this could be changed to `T: ?Sized`... error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsizing-wfcheck-issue-126272.rs:8:32 + --> $DIR/unsizing-wfcheck-issue-126272.rs:9:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^^^^^^^^ -... + | ------------ in this derive macro expansion +LL | struct Foo { + | ^^^ +LL | LL | nested: &'static Bar, | ----------------------------------------- this field does not implement `ConstParamTy_` | @@ -62,9 +64,12 @@ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Bar(T); - | - + | ^^^ - = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -97,9 +102,12 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ unsatisfied trait bound introduced in this `derive` macro + | ^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Bar(T); - | - would need to be `Eq` + | ^^^ - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 991a48917efb8..aa9177d2b017b 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,9 +8,12 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Foo(T); - | - would need to be `Copy` + | ^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.rs b/tests/ui/derives/copy-drop-mutually-exclusive.rs index 5147605910d7b..64cd5bf594b01 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.rs +++ b/tests/ui/derives/copy-drop-mutually-exclusive.rs @@ -1,14 +1,14 @@ //! Regression test for issue #20126: Copy and Drop traits are mutually exclusive -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented -struct Foo; +#[derive(Copy, Clone)] +struct Foo; //~ ERROR the trait `Copy` cannot be implemented impl Drop for Foo { fn drop(&mut self) {} } -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented -struct Bar(::std::marker::PhantomData); +#[derive(Copy, Clone)] +struct Bar(::std::marker::PhantomData); //~ ERROR the trait `Copy` cannot be implemented impl Drop for Bar { fn drop(&mut self) {} diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.stderr b/tests/ui/derives/copy-drop-mutually-exclusive.stderr index 771bbc9256958..f17d33ffbfedc 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.stderr +++ b/tests/ui/derives/copy-drop-mutually-exclusive.stderr @@ -1,14 +1,18 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/copy-drop-mutually-exclusive.rs:3:10 + --> $DIR/copy-drop-mutually-exclusive.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Foo; + | ^^^ `Copy` not allowed on types with destructors error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/copy-drop-mutually-exclusive.rs:10:10 + --> $DIR/copy-drop-mutually-exclusive.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Bar(::std::marker::PhantomData); + | ^^^ `Copy` not allowed on types with destructors error: aborting due to 2 previous errors diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 1baacf85f6a21..2261634744822 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,9 +10,12 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Copy` + | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -36,9 +39,12 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Clone` + | ^ - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -62,9 +68,12 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Copy` + | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr index 27691f5718849..c033a3d227c12 100644 --- a/tests/ui/derives/issue-97343.stderr +++ b/tests/ui/derives/issue-97343.stderr @@ -2,12 +2,11 @@ error[E0109]: type arguments are not allowed on type parameter `Irrelevant` --> $DIR/issue-97343.rs:4:23 | LL | #[derive(Debug)] - | ----- - | | - | not allowed on type parameter `Irrelevant` - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Irrelevant { - | ^^^^^^^^^^ type argument not allowed + | ---------- ^^^^^^^^^^ type argument not allowed + | | + | not allowed on type parameter `Irrelevant` | note: type parameter `Irrelevant` defined here --> $DIR/issue-97343.rs:4:23 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs index 8e5cd4248f149..f4193f18352d0 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs @@ -3,12 +3,12 @@ struct NonGeneric {} #[derive(Default)] -//~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~^^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied -//~^^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied +//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied struct NonGeneric<'a, const N: usize> {} -//~^ ERROR lifetime parameter `'a` is never used -//~^^ ERROR the name `NonGeneric` is defined multiple times +//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied +//~| ERROR: lifetime parameter `'a` is never used +//~| ERROR: the name `NonGeneric` is defined multiple times pub fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr index cf9c0d0ad3bee..0d6aaaf5186d3 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NonGeneric` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:1 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:1 | LL | struct NonGeneric {} | ----------------- previous definition of the type `NonGeneric` here @@ -37,7 +37,7 @@ LL | struct NonGeneric {} | ^^^^^^^^^^ error[E0392]: lifetime parameter `'a` is never used - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:19 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:19 | LL | struct NonGeneric<'a, const N: usize> {} | ^^ unused lifetime parameter @@ -45,29 +45,26 @@ LL | struct NonGeneric<'a, const N: usize> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 lifetime arguments -... LL | struct NonGeneric<'a, const N: usize> {} - | -- help: remove the lifetime argument + | ^^^^^^^^^^ -- help: remove the lifetime argument + | | + | expected 0 lifetime arguments | note: struct defined here, with 0 lifetime parameters --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 | LL | struct NonGeneric {} | ^^^^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 generic arguments -... LL | struct NonGeneric<'a, const N: usize> {} - | - help: remove the unnecessary generic argument + | ^^^^^^^^^^ - help: remove the unnecessary generic argument + | | + | expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs index f3bf299aa65f4..e946c0c5350ed 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs @@ -8,12 +8,12 @@ struct NotSM; #[derive(PartialEq, Eq)] -//~^ ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments +//~^ ERROR: struct takes 0 generic arguments struct NotSM(T); -//~^ ERROR the name `NotSM` is defined multiple times -//~| ERROR no field `0` +//~^ ERROR: struct takes 0 generic arguments +//~| ERROR: struct takes 0 generic arguments +//~| ERROR: struct takes 0 generic arguments +//~| ERROR: the name `NotSM` is defined multiple times +//~| ERROR: no field `0` fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr index 32c3cf4403169..e80cf35d81e1d 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NotSM` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive.rs:15:1 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:1 | LL | struct NotSM; | ------------- previous definition of the type `NotSM` here @@ -10,10 +10,10 @@ LL | struct NotSM(T); = note: `NotSM` must be defined only once in the type namespace of this module error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 @@ -32,25 +32,25 @@ note: struct defined here, with 0 generic parameters | LL | struct NotSM; | ^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:21 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 | LL | struct NotSM; | ^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 @@ -60,7 +60,7 @@ LL | struct NotSM; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0609]: no field `0` on type `&NotSM` - --> $DIR/multiple-types-with-same-name-and-derive.rs:15:17 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:17 | LL | struct NotSM(T); | ^ unknown field diff --git a/tests/ui/error-codes/E0184.rs b/tests/ui/error-codes/E0184.rs index 0c448e4ad8bcf..64cc1f0d15382 100644 --- a/tests/ui/error-codes/E0184.rs +++ b/tests/ui/error-codes/E0184.rs @@ -1,5 +1,5 @@ -#[derive(Copy)] //~ ERROR E0184 -struct Foo; +#[derive(Copy)] +struct Foo; //~ ERROR E0184 impl Drop for Foo { fn drop(&mut self) { diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 1a7df9ac095ad..98b5305ad0dcd 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -1,8 +1,10 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/E0184.rs:1:10 + --> $DIR/E0184.rs:2:8 | LL | #[derive(Copy)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Foo; + | ^^^ `Copy` not allowed on types with destructors error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index fd7dd774cf087..d918bd62c2d72 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,9 +32,12 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Fooy(T); - | - would need to be `Copy` + | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -59,9 +62,12 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Fooy(T); - | - would need to be `Copy` + | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/issues/issue-27340.rs b/tests/ui/issues/issue-27340.rs index 53ca2bc973ff8..9966c24a7441e 100644 --- a/tests/ui/issues/issue-27340.rs +++ b/tests/ui/issues/issue-27340.rs @@ -1,7 +1,7 @@ struct Foo; #[derive(Copy, Clone)] -//~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar(Foo); -//~^ ERROR `Foo: Clone` is not satisfied +//~^ ERROR: the trait `Copy` cannot be implemented for this type +//~| ERROR: `Foo: Clone` is not satisfied fn main() {} diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/issues/issue-27340.stderr index 7cde901ffd95a..3b4ad58b1f080 100644 --- a/tests/ui/issues/issue-27340.stderr +++ b/tests/ui/issues/issue-27340.stderr @@ -1,18 +1,16 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-27340.rs:2:10 + --> $DIR/issue-27340.rs:3:8 | LL | #[derive(Copy, Clone)] - | ^^^^ -LL | + | ---- in this derive macro expansion LL | struct Bar(Foo); - | --- this field does not implement `Copy` + | ^^^ --- this field does not implement `Copy` error[E0277]: the trait bound `Foo: Clone` is not satisfied - --> $DIR/issue-27340.rs:4:12 + --> $DIR/issue-27340.rs:3:12 | LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion -LL | LL | struct Bar(Foo); | ^^^ the trait `Clone` is not implemented for `Foo` | diff --git a/tests/ui/malformed/malformed-derive-entry.rs b/tests/ui/malformed/malformed-derive-entry.rs index 77fa2f566a8fc..f9dc98d9d270f 100644 --- a/tests/ui/malformed/malformed-derive-entry.rs +++ b/tests/ui/malformed/malformed-derive-entry.rs @@ -1,14 +1,14 @@ #[derive(Copy(Bad))] -//~^ ERROR traits in `#[derive(...)]` don't accept arguments -//~| ERROR the trait bound +//~^ ERROR: traits in `#[derive(...)]` don't accept arguments struct Test1; +//~^ ERROR: the trait bound #[derive(Copy="bad")] -//~^ ERROR traits in `#[derive(...)]` don't accept values -//~| ERROR the trait bound +//~^ ERROR: traits in `#[derive(...)]` don't accept values struct Test2; +//~^ ERROR: the trait bound -#[derive] //~ ERROR malformed `derive` attribute input +#[derive] //~ ERROR: malformed `derive` attribute input struct Test4; fn main() {} diff --git a/tests/ui/malformed/malformed-derive-entry.stderr b/tests/ui/malformed/malformed-derive-entry.stderr index 02036e8d4c90b..a5d7c3a4f8aaa 100644 --- a/tests/ui/malformed/malformed-derive-entry.stderr +++ b/tests/ui/malformed/malformed-derive-entry.stderr @@ -17,10 +17,13 @@ LL | #[derive] | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` error[E0277]: the trait bound `Test1: Clone` is not satisfied - --> $DIR/malformed-derive-entry.rs:1:10 + --> $DIR/malformed-derive-entry.rs:3:8 | LL | #[derive(Copy(Bad))] - | ^^^^ the trait `Clone` is not implemented for `Test1` + | ---- in this derive macro expansion +LL | +LL | struct Test1; + | ^^^^^ the trait `Clone` is not implemented for `Test1` | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL @@ -31,10 +34,13 @@ LL | struct Test1; | error[E0277]: the trait bound `Test2: Clone` is not satisfied - --> $DIR/malformed-derive-entry.rs:6:10 + --> $DIR/malformed-derive-entry.rs:8:8 | LL | #[derive(Copy="bad")] - | ^^^^ the trait `Clone` is not implemented for `Test2` + | ---- in this derive macro expansion +LL | +LL | struct Test2; + | ^^^^^ the trait `Clone` is not implemented for `Test2` | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index d420f2641daf5..0c66b47b39418 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -12,12 +12,11 @@ struct PriorityQueueEntry { } #[derive(PartialOrd, AddImpl)] -//~^ ERROR can't compare `PriorityQueue` with `PriorityQueue` -//~| ERROR the trait bound `PriorityQueue: Eq` is not satisfied -//~| ERROR can't compare `T` with `T` -//~| ERROR no method named `cmp` found for struct `BinaryHeap>` -//~| ERROR no field `height` on type `&PriorityQueue` - +//~^ ERROR: the trait bound `PriorityQueue: Eq` is not satisfied +//~| ERROR: can't compare `T` with `T` +//~| ERROR: no method named `cmp` found for struct `BinaryHeap>` +//~| ERROR: no field `height` on type `&PriorityQueue` struct PriorityQueue(BinaryHeap>); -//~^ ERROR can't compare `BinaryHeap>` with `_` +//~^ ERROR: can't compare `PriorityQueue` with `PriorityQueue` +//~| ERROR: can't compare `BinaryHeap>` with `_` fn main() {} diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index c3513e19981fd..e49cf6256cb26 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -1,11 +1,14 @@ error[E0277]: can't compare `PriorityQueue` with `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:8 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` + | ---------- in this derive macro expansion +... +LL | struct PriorityQueue(BinaryHeap>); + | ^^^^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` | help: the trait `PartialEq` is not implemented for `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:1 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:1 | LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +22,7 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ unsatisfied trait bound | help: the trait `Eq` is not implemented for `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:1 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:1 | LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,16 +40,19 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); - | - would need to be `PartialOrd` + | ^^^^^^^^^^^^^ - would need to be `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL error[E0277]: can't compare `BinaryHeap>` with `_` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:25 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:25 | LL | #[derive(PartialOrd, AddImpl)] | ---------- in this derive macro expansion diff --git a/tests/ui/range/range_traits-2.rs b/tests/ui/range/range_traits-2.rs index 234d7a64dc8b0..7dd91243082c5 100644 --- a/tests/ui/range/range_traits-2.rs +++ b/tests/ui/range/range_traits-2.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(Range); +#[derive(Copy, Clone)] +struct R(Range); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr index 2001c85c4348a..f38539cc648c0 100644 --- a/tests/ui/range/range_traits-2.stderr +++ b/tests/ui/range/range_traits-2.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-2.rs:3:10 + --> $DIR/range_traits-2.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(Range); - | ------------ this field does not implement `Copy` + | ^ ------------ this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-3.rs b/tests/ui/range/range_traits-3.rs index 2d597cce5ad56..79ba1842f62f5 100644 --- a/tests/ui/range/range_traits-3.rs +++ b/tests/ui/range/range_traits-3.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeFrom); +#[derive(Copy, Clone)] +struct R(RangeFrom); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr index 71210379c79cd..1f3768ad8d84b 100644 --- a/tests/ui/range/range_traits-3.stderr +++ b/tests/ui/range/range_traits-3.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-3.rs:3:10 + --> $DIR/range_traits-3.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(RangeFrom); - | ---------------- this field does not implement `Copy` + | ^ ---------------- this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-6.rs b/tests/ui/range/range_traits-6.rs index bce106bbfe79b..72c6cecc88d69 100644 --- a/tests/ui/range/range_traits-6.rs +++ b/tests/ui/range/range_traits-6.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeInclusive); +#[derive(Copy, Clone)] +struct R(RangeInclusive); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr index a58022ef7e4fd..53fe2fed0a616 100644 --- a/tests/ui/range/range_traits-6.stderr +++ b/tests/ui/range/range_traits-6.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-6.rs:3:10 + --> $DIR/range_traits-6.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(RangeInclusive); - | --------------------- this field does not implement `Copy` + | ^ --------------------- this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/span/E0204.rs b/tests/ui/span/E0204.rs index 8793a05c8a85a..841bd5e32b8a1 100644 --- a/tests/ui/span/E0204.rs +++ b/tests/ui/span/E0204.rs @@ -4,8 +4,8 @@ struct Foo { impl Copy for Foo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR cannot be implemented for this type -struct Foo2<'a> { +#[derive(Copy)] +struct Foo2<'a> { //~ ERROR cannot be implemented for this type ty: &'a mut bool, } @@ -16,8 +16,8 @@ enum EFoo { impl Copy for EFoo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR cannot be implemented for this type -enum EFoo2<'a> { +#[derive(Copy)] +enum EFoo2<'a> { //~ ERROR cannot be implemented for this type Bar(&'a mut bool), Baz, } diff --git a/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr index fe375b94781b5..a0b51be178634 100644 --- a/tests/ui/span/E0204.stderr +++ b/tests/ui/span/E0204.stderr @@ -8,11 +8,12 @@ LL | impl Copy for Foo { } | ^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/E0204.rs:7:10 + --> $DIR/E0204.rs:8:8 | LL | #[derive(Copy)] - | ^^^^ + | ---- in this derive macro expansion LL | struct Foo2<'a> { + | ^^^^ LL | ty: &'a mut bool, | ---------------- this field does not implement `Copy` @@ -26,11 +27,12 @@ LL | impl Copy for EFoo { } | ^^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/E0204.rs:19:10 + --> $DIR/E0204.rs:20:6 | LL | #[derive(Copy)] - | ^^^^ + | ---- in this derive macro expansion LL | enum EFoo2<'a> { + | ^^^^^ LL | Bar(&'a mut bool), | ------------ this field does not implement `Copy` diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed index 4dc362f947875..17259dd687c6c 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.fixed +++ b/tests/ui/suggestions/derive-clone-for-eq.fixed @@ -1,8 +1,8 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs index b3635000f1658..3e4331745be87 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.rs +++ b/tests/ui/suggestions/derive-clone-for-eq.rs @@ -1,8 +1,8 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index eb0355853daac..bed5ff90c1949 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/derive-clone-for-eq.rs:4:17 + --> $DIR/derive-clone-for-eq.rs:5:12 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | -- in this derive macro expansion +LL | pub struct Struct(T); + | ^^^^^^ the trait `Clone` is not implemented for `T` | note: required for `Struct` to implement `PartialEq` --> $DIR/derive-clone-for-eq.rs:7:19 diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 800f07054af73..872ce7105ce8c 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -27,9 +27,12 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,9 +72,12 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed index 74df1d7c7cfdd..bd1785e351123 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -7,8 +7,8 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` //~^ ERROR `K` doesn't implement `Debug` pub size: Vector2 //~ ERROR `K` doesn't implement `Debug` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs index 8550a4d724761..36502044bd467 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -7,8 +7,8 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` //~^ ERROR `K` doesn't implement `Debug` pub size: Vector2 //~ ERROR `K` doesn't implement `Debug` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index e3375b67c86dd..cc80e7297e48a 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -1,9 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17 + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:11:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ -LL | pub struct AABB{ + | ---- in this derive macro expansion +LL | pub struct AABB { + | ^^^^ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` | @@ -14,7 +15,7 @@ LL | pub loc: Vector2, | ^^^^^^^^^^ help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++ error[E0277]: `K` doesn't implement `Debug` @@ -30,7 +31,7 @@ LL | pub struct Vector2{ | ^^^^^ required by this bound in `Vector2` help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error[E0277]: `K` doesn't implement `Debug` @@ -38,13 +39,13 @@ error[E0277]: `K` doesn't implement `Debug` | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion -LL | pub struct AABB{ +LL | pub struct AABB { LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `K` | help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error[E0277]: `K` doesn't implement `Debug` @@ -58,7 +59,7 @@ LL | pub size: Vector2 | help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs index 0ffc1b8f7a25e..60a9074e5c0d9 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -6,8 +6,8 @@ pub struct Vector2 { pub y: T, } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB { +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~^ ERROR doesn't implement `Debug` //~| ERROR `K: Copy` is not satisfied diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 3f889f31484b5..f843fb0d6d7ea 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -1,9 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17 + --> $DIR/missing-bound-in-derive-copy-impl.rs:10:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | pub struct AABB { + | ^^^^ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` | @@ -62,9 +63,12 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -132,9 +136,12 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 275cef7a94fd5..02c7fe9e689e6 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -11,9 +11,12 @@ note: required for `Id` to implement `PartialEq` --> $DIR/derive-implicit-bound.rs:5:10 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Id(PhantomData); - | - would need to be `PartialEq` + | ^^ - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index d45668312218b..6b04004621d82 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,4 @@ -#[derive(Clone)] -//~^ ERROR expected a type, found a trait -//~| ERROR expected a type, found a trait -struct Foo; -trait Foo {} //~ ERROR the name `Foo` is defined multiple times +#[derive(Clone)] //~ ERROR: expected a type, found a trait +struct Foo; //~ ERROR: expected a type, found a trait +trait Foo {} //~ ERROR: the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 815787c3bfecb..ebb22cb9cd745 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-106072.rs:5:1 + --> $DIR/issue-106072.rs:3:1 | LL | struct Foo; | ----------- previous definition of the type `Foo` here @@ -9,18 +9,23 @@ LL | trait Foo {} = note: `Foo` must be defined only once in the type namespace of this module error[E0782]: expected a type, found a trait - --> $DIR/issue-106072.rs:1:10 + --> $DIR/issue-106072.rs:2:8 | LL | #[derive(Clone)] - | ^^^^^ + | ----- in this derive macro expansion +LL | struct Foo; + | ^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | struct dyn Foo; + | +++ error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 | LL | #[derive(Clone)] | ^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs index ccd35a850f2d7..2f62906e9df3d 100644 --- a/tests/ui/traits/issue-50480.rs +++ b/tests/ui/traits/issue-50480.rs @@ -1,18 +1,17 @@ #[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` cannot be implemented for this type struct Foo(N, NotDefined, ::Item, Vec, String); -//~^ ERROR cannot find type `NotDefined` in this scope +//~^ ERROR the trait `Copy` cannot be implemented for this type +//~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator //~| ERROR `i32` is not an iterator -#[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` cannot be implemented for this type -//~| ERROR `i32` is not an iterator +#[derive(Clone, Copy)] //~ ERROR `i32` is not an iterator struct Bar(T, N, NotDefined, ::Item, Vec, String); -//~^ ERROR cannot find type `NotDefined` in this scope +//~^ ERROR the trait `Copy` cannot be implemented for this type +//~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator //~| ERROR `i32` is not an iterator diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 32c8b2cf3ac1f..1fb5e8b007830 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:3:12 + --> $DIR/issue-50480.rs:2:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^ not found in this scope @@ -10,13 +10,13 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:3:15 + --> $DIR/issue-50480.rs:2:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:3:12 + --> $DIR/issue-50480.rs:2:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^ not found in this scope @@ -27,7 +27,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:3:15 + --> $DIR/issue-50480.rs:2:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope @@ -38,7 +38,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, St | ++++++++++++ error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:14:18 + --> $DIR/issue-50480.rs:12:18 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | - ^ @@ -56,13 +56,13 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, Strin | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:14:21 + --> $DIR/issue-50480.rs:12:21 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:27 + --> $DIR/issue-50480.rs:2:27 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator @@ -70,29 +70,27 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); = help: the trait `Iterator` is not implemented for `i32` error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:1:17 + --> $DIR/issue-50480.rs:2:8 | LL | #[derive(Clone, Copy)] - | ^^^^ -LL | + | ---- in this derive macro expansion LL | struct Foo(N, NotDefined, ::Item, Vec, String); - | -------- ------ this field does not implement `Copy` + | ^^^ -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:11:17 + --> $DIR/issue-50480.rs:12:8 | LL | #[derive(Clone, Copy)] - | ^^^^ -... + | ---- in this derive macro expansion LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); - | -------- ------ this field does not implement `Copy` + | ^^^ -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:14:33 + --> $DIR/issue-50480.rs:12:33 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator @@ -100,7 +98,7 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); = help: the trait `Iterator` is not implemented for `i32` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:28 + --> $DIR/issue-50480.rs:2:28 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^ `i32` is not an iterator @@ -116,11 +114,10 @@ LL | #[derive(Clone, Copy)] = help: the trait `Iterator` is not implemented for `i32` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:14:33 + --> $DIR/issue-50480.rs:12:33 | LL | #[derive(Clone, Copy)] | ----- in this derive macro expansion -... LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs index 2b4f7ba9fa29e..ceef87d76abb6 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs @@ -12,8 +12,8 @@ // we already face this difficulty, probably. If we need to fix this by reducing the error margin, // we should improve compiletest. -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr index 290b1df1665d3..912286a48fafe 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/global-cache-and-parallel-frontend.rs:15:17 + --> $DIR/global-cache-and-parallel-frontend.rs:16:12 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | -- in this derive macro expansion +LL | pub struct Struct(T); + | ^^^^^^ the trait `Clone` is not implemented for `T` | note: required for `Struct` to implement `PartialEq` --> $DIR/global-cache-and-parallel-frontend.rs:18:19 From b9e5cf7806b824c1080b66755701840f9d88f80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:57:27 +0000 Subject: [PATCH 26/47] Fix incorrect suggestion caused by change in derive expansion Span --- .../rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs | 6 +++++- tests/ui/traits/issue-106072.stderr | 5 ----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 29f29761b6055..57defac577d8a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -592,7 +592,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if span.can_be_used_for_suggestions() && poly_trait_ref.trait_ref.trait_def_id().is_some() && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag) - && !self.maybe_suggest_dyn_trait(hir_id, sugg, &mut diag) + && !self.maybe_suggest_dyn_trait(hir_id, span, sugg, &mut diag) { self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag); } @@ -750,10 +750,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn maybe_suggest_dyn_trait( &self, hir_id: hir::HirId, + span: Span, sugg: Vec<(Span, String)>, diag: &mut Diag<'_>, ) -> bool { let tcx = self.tcx(); + if span.in_derive_expansion() { + return false; + } // Look at the direct HIR parent, since we care about the relationship between // the type and the thing that directly encloses it. diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index ebb22cb9cd745..57661fda73079 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -15,11 +15,6 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct Foo; | ^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | struct dyn Foo; - | +++ error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 From dd8148373fa376541b40e24129251153e0bf5271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:16:39 +0000 Subject: [PATCH 27/47] Tweak span labels --- .../src/error_reporting/traits/suggestions.rs | 12 +++------ tests/ui/associated-types/issue-38821.stderr | 27 +++++++------------ .../unsizing-wfcheck-issue-126272.stderr | 16 ++++------- .../ui/consts/const-blocks/trait-error.stderr | 7 ++--- tests/ui/derives/deriving-copyclone.stderr | 21 +++++---------- .../impl_bounds.stderr | 14 +++------- .../issue-104884-trait-impl-sugg-err.stderr | 7 ++--- ...missing-bound-in-derive-copy-impl-2.stderr | 18 +++++-------- .../missing-bound-in-derive-copy-impl.stderr | 18 +++++-------- tests/ui/traits/derive-implicit-bound.stderr | 7 ++--- 10 files changed, 46 insertions(+), 101 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index c9dc390ea0be8..70a16b23d2764 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3581,7 +3581,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. })) => { let mut spans = Vec::with_capacity(2); - if let Some(of_trait) = of_trait { + if let Some(of_trait) = of_trait + && !of_trait.trait_ref.path.span.in_derive_expansion() + { spans.push(of_trait.trait_ref.path.span); } spans.push(self_ty.span); @@ -3595,18 +3597,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { derived = true; - spans.push_span_label( - data.span.ctxt().outer_expn_data().call_site, - format!( - "unsatisfied trait bound introduced in this `derive` macro" - ), - ); spans.push_span_label( data.span, if data.span.in_derive_expansion() { format!("would need to be `{trait_name}`") } else { - format!("") + format!("unsatisfied trait bound") }, ); } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) { diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 58d06860fe301..fae388c98d36f 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -98,19 +98,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Debug` - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | @@ -152,19 +149,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Copy` - --> $DIR/issue-38821.rs:23:17 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | @@ -235,19 +229,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Clone` - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index f90f0b45d967a..fc681e655e1a6 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -61,15 +61,12 @@ help: the trait `Debug` is implemented for `Bar` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^^^^ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` - --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 + --> $DIR/unsizing-wfcheck-issue-126272.rs:20:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | struct Bar(T); - | ^^^ - + | ^^^ - unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -99,13 +96,10 @@ help: the trait `Eq` is implemented for `Bar` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^ note: required for `Bar` to implement `Eq` - --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 + --> $DIR/unsizing-wfcheck-issue-126272.rs:20:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | -- in this derive macro expansion LL | struct Bar(T); | ^^^ - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index aa9177d2b017b..60402a4123626 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -5,13 +5,10 @@ LL | [Foo(String::new()); 4]; | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | note: required for `Foo` to implement `Copy` - --> $DIR/trait-error.rs:1:10 + --> $DIR/trait-error.rs:2:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Foo(T); | ^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 2261634744822..f8d2859f211ed 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -7,13 +7,10 @@ LL | is_copy(B { a: 1, b: C }); | required by a bound introduced by this call | note: required for `B` to implement `Copy` - --> $DIR/deriving-copyclone.rs:9:10 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct B { | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds @@ -36,13 +33,10 @@ LL | is_clone(B { a: 1, b: C }); | required by a bound introduced by this call | note: required for `B` to implement `Clone` - --> $DIR/deriving-copyclone.rs:9:16 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | struct B { | ^ - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds @@ -65,13 +59,10 @@ LL | is_copy(B { a: 1, b: D }); | required by a bound introduced by this call | note: required for `B` to implement `Copy` - --> $DIR/deriving-copyclone.rs:9:10 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct B { | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index d918bd62c2d72..f656756865329 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -29,13 +29,10 @@ LL | type C = String where Self: Copy; | ^^^^ the trait `Copy` is not implemented for `T` | note: required for `Fooy` to implement `Copy` - --> $DIR/impl_bounds.rs:10:10 + --> $DIR/impl_bounds.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds @@ -59,13 +56,10 @@ LL | fn d() where Self: Copy {} | ^^^^ the trait `Copy` is not implemented for `T` | note: required for `Fooy` to implement `Copy` - --> $DIR/impl_bounds.rs:10:10 + --> $DIR/impl_bounds.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index e49cf6256cb26..d14f9eae69502 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,13 +37,10 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ no implementation for `T < T` and `T > T` | note: required for `PriorityQueue` to implement `PartialOrd` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:8 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---------- in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^ - would need to be `PartialOrd` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 872ce7105ce8c..791e2d19f2f96 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -24,15 +24,12 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Debug` - --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,15 +66,12 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Clone` - --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index f843fb0d6d7ea..55d6391f975e6 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -60,15 +60,12 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Debug` - --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -133,15 +130,12 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Clone` - --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 02c7fe9e689e6..ee78cba5af27c 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -8,13 +8,10 @@ LL | accept_eq(&node); | = help: the trait `PartialEq` is not implemented for `SomeNode` note: required for `Id` to implement `PartialEq` - --> $DIR/derive-implicit-bound.rs:5:10 + --> $DIR/derive-implicit-bound.rs:6:12 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | --------- in this derive macro expansion LL | pub struct Id(PhantomData); | ^^ - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds From 20000ca25a90c1704e02e349b9583b0bb00086b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:28:58 +0000 Subject: [PATCH 28/47] Point at destructor when denying deriving `Copy` --- compiler/rustc_hir_analysis/messages.ftl | 1 + compiler/rustc_hir_analysis/src/coherence/builtin.rs | 5 +++-- compiler/rustc_hir_analysis/src/errors.rs | 2 ++ compiler/rustc_trait_selection/src/traits/misc.rs | 6 +++--- tests/ui/derives/copy-drop-mutually-exclusive.stderr | 12 ++++++++++++ tests/ui/error-codes/E0184.stderr | 6 ++++++ 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index d9f8eba65c4a2..611aa070124a4 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -142,6 +142,7 @@ hir_analysis_copy_impl_on_non_adt = hir_analysis_copy_impl_on_type_with_dtor = the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors + .note = destructor declared here hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}` .label = can't implement cross-crate trait with a default impl for non-struct/enum type diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 61562cc1e4f30..558d2ec84e4bd 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -121,9 +121,10 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span })) } - Err(CopyImplementationError::HasDestructor) => { + Err(CopyImplementationError::HasDestructor(did)) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; - Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span })) + let impl_ = tcx.def_span(did); + Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span, impl_ })) } Err(CopyImplementationError::HasUnsafeFields) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2a77d0b997e2c..b90ccc6716d04 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -278,6 +278,8 @@ pub(crate) struct CopyImplOnTypeWithDtor { #[primary_span] #[label] pub span: Span, + #[note] + pub impl_: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index f33196bab6470..2fd3a6e738cfe 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -13,7 +13,7 @@ use crate::traits::{self, FulfillmentError, Obligation, ObligationCause}; pub enum CopyImplementationError<'tcx> { InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>), NotAnAdt, - HasDestructor, + HasDestructor(hir::def_id::DefId), HasUnsafeFields, } @@ -76,8 +76,8 @@ pub fn type_allowed_to_implement_copy<'tcx>( ) .map_err(CopyImplementationError::InfringingFields)?; - if adt.has_dtor(tcx) { - return Err(CopyImplementationError::HasDestructor); + if let Some(did) = adt.destructor(tcx).map(|dtor| dtor.did) { + return Err(CopyImplementationError::HasDestructor(did)); } if impl_safety.is_safe() && self_type.has_unsafe_fields() { diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.stderr b/tests/ui/derives/copy-drop-mutually-exclusive.stderr index f17d33ffbfedc..ab2d086c7f5fc 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.stderr +++ b/tests/ui/derives/copy-drop-mutually-exclusive.stderr @@ -5,6 +5,12 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo; | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/copy-drop-mutually-exclusive.rs:7:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor --> $DIR/copy-drop-mutually-exclusive.rs:11:8 @@ -13,6 +19,12 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Bar(::std::marker::PhantomData); | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/copy-drop-mutually-exclusive.rs:14:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 98b5305ad0dcd..13294959bc3cf 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -5,6 +5,12 @@ LL | #[derive(Copy)] | ---- in this derive macro expansion LL | struct Foo; | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/E0184.rs:5:5 + | +LL | fn drop(&mut self) { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error From 23b766ce631dc90c89f1c71878058a2618b7b8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:43:18 +0000 Subject: [PATCH 29/47] fix typo --- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- tests/ui/traits/derive-implicit-bound-on-clone.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 285288e87ee00..349b2c756b644 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1937,7 +1937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { let manually_impl = "consider manually implementing `Clone` to avoid the \ - implict type parameter bounds"; + implicit type parameter bounds"; match &errors[..] { [] => {} [error] => { diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.stderr b/tests/ui/traits/derive-implicit-bound-on-clone.stderr index 0cec4ef7c6096..2fb039f965288 100644 --- a/tests/ui/traits/derive-implicit-bound-on-clone.stderr +++ b/tests/ui/traits/derive-implicit-bound-on-clone.stderr @@ -22,7 +22,7 @@ LL | struct ContainsRc { | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` | | | derive introduces an implicit unsatisfied trait bound `T: Clone` - = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error[E0308]: mismatched types --> $DIR/derive-implicit-bound-on-clone.rs:20:5 @@ -46,7 +46,7 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct ContainsRcSingle { | ^ derive introduces an implicit `T: Clone` bound - = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error: aborting due to 2 previous errors From b534229a3ace7e39381efb8941d8277d17a985f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 18:49:12 +0000 Subject: [PATCH 30/47] remove commented out code --- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 349b2c756b644..b8f99bbd7e17a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1941,8 +1941,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &errors[..] { [] => {} [error] => { - // diag.note("{error:#?}"); - // diag.note(format!("{:#?} {:#?} {:#?}", error.obligation, error.obligation.cause, error.obligation.cause.code())); let msg = "`Clone` is not implemented because a trait bound is not \ satisfied"; if let traits::ObligationCauseCode::ImplDerived(data) = From 6c8eee82970d4b1659329a8ff1f9bad7ac66e152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 18:59:32 +0000 Subject: [PATCH 31/47] reword span label --- .../src/error_reporting/traits/suggestions.rs | 2 +- .../adt_const_params/unsizing-wfcheck-issue-126272.stderr | 2 +- tests/ui/consts/const-blocks/trait-error.stderr | 2 +- tests/ui/derives/deriving-copyclone.stderr | 6 +++--- tests/ui/generic-associated-types/impl_bounds.stderr | 4 ++-- tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr | 2 +- tests/ui/traits/derive-implicit-bound.stderr | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 70a16b23d2764..1880465eff54c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3600,7 +3600,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { spans.push_span_label( data.span, if data.span.in_derive_expansion() { - format!("would need to be `{trait_name}`") + format!("type parameter would need to implement `{trait_name}`") } else { format!("unsatisfied trait bound") }, diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index fc681e655e1a6..f520413927c36 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -101,7 +101,7 @@ note: required for `Bar` to implement `Eq` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | -- in this derive macro expansion LL | struct Bar(T); - | ^^^ - would need to be `Eq` + | ^^^ - type parameter would need to implement `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 60402a4123626..853e10e0b35a3 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -10,7 +10,7 @@ note: required for `Foo` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo(T); - | ^^^ - would need to be `Copy` + | ^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index f8d2859f211ed..40f96919121f4 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -12,7 +12,7 @@ note: required for `B` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { - | ^ - would need to be `Copy` + | ^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -38,7 +38,7 @@ note: required for `B` to implement `Clone` LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion LL | struct B { - | ^ - would need to be `Clone` + | ^ - type parameter would need to implement `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -64,7 +64,7 @@ note: required for `B` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { - | ^ - would need to be `Copy` + | ^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index f656756865329..63c4ba9008291 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -34,7 +34,7 @@ note: required for `Fooy` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); - | ^^^^ - would need to be `Copy` + | ^^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -61,7 +61,7 @@ note: required for `Fooy` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); - | ^^^^ - would need to be `Copy` + | ^^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index d14f9eae69502..b53ebe9f72718 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -43,7 +43,7 @@ LL | #[derive(PartialOrd, AddImpl)] | ---------- in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); - | ^^^^^^^^^^^^^ - would need to be `PartialOrd` + | ^^^^^^^^^^^^^ - type parameter would need to implement `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index ee78cba5af27c..fe2bc77b9529c 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -13,7 +13,7 @@ note: required for `Id` to implement `PartialEq` LL | #[derive(PartialEq, Eq)] | --------- in this derive macro expansion LL | pub struct Id(PhantomData); - | ^^ - would need to be `PartialEq` + | ^^ - type parameter would need to implement `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 From 879633f97b3affafd87a8726240b8109a7bc8363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 19:24:10 +0000 Subject: [PATCH 32/47] Change note to help --- .../src/diagnostics/conflict_errors.rs | 2 +- tests/ui/associated-types/issue-25700.stderr | 2 +- .../closure-shim-borrowck-error.stderr | 2 +- .../async-closures/move-out-of-ref.stderr | 2 +- .../borrowck-move-out-of-static-item.stderr | 2 +- .../borrowck-move-subcomponent.stderr | 2 +- .../borrowck/borrowck-overloaded-call.stderr | 2 +- tests/ui/borrowck/clone-on-ref.stderr | 2 +- .../borrowck/derive-clone-implicit-bound.rs | 4 ++-- .../derive-clone-implicit-bound.stderr | 2 +- tests/ui/borrowck/issue-103624.stderr | 2 +- .../issue-119915-bad-clone-suggestion.stderr | 2 +- .../borrowck/issue-17718-static-move.stderr | 2 +- tests/ui/borrowck/issue-20801.stderr | 8 +++---- .../borrowck/move-error-in-promoted-2.stderr | 2 +- tests/ui/borrowck/move-error-snippets.stderr | 2 +- ...e-in-static-initializer-issue-38520.stderr | 4 ++-- tests/ui/box/leak-alloc.stderr | 2 +- .../closure-move-use-after-move-diagnostic.rs | 2 +- ...sure-move-use-after-move-diagnostic.stderr | 2 +- tests/ui/coroutine/moved-twice.stderr | 2 +- .../derives/deriving-with-repr-packed.stderr | 2 +- tests/ui/error-codes/E0504.stderr | 2 +- tests/ui/error-codes/E0505.stderr | 2 +- tests/ui/error-codes/E0507.stderr | 2 +- tests/ui/error-codes/E0508-fail.stderr | 2 +- tests/ui/error-codes/E0508.stderr | 2 +- tests/ui/error-codes/E0509.stderr | 2 +- tests/ui/mir/issue-102389.stderr | 2 +- tests/ui/moves/issue-72649-uninit-in-loop.rs | 10 ++++---- .../moves/issue-72649-uninit-in-loop.stderr | 15 ++++++------ .../issue-75904-move-closure-loop.stderr | 2 +- ...atching-partially-moved-value-17385.stderr | 4 ++-- tests/ui/moves/move-fn-self-receiver.stderr | 2 +- tests/ui/moves/move-out-of-array-1.stderr | 2 +- .../ui/moves/moved-value-on-as-ref-arg.stderr | 4 ++-- .../issue-21232-partial-init-and-use.stderr | 4 ++-- tests/ui/nll/move-errors.stderr | 12 +++++----- .../pin-ergonomics/borrow-unpin.pinned.stderr | 24 +++++++++---------- .../pin-ergonomics/borrow-unpin.unpin.stderr | 6 ++--- tests/ui/pin-macro/pin_move.stderr | 4 ++-- .../non_copy_move_out_of_tuple.stderr | 2 +- .../suggestions/option-content-move3.stderr | 4 ++-- .../union-borrow-move-parent-sibling.stderr | 2 +- tests/ui/union/union-move.stderr | 4 ++-- tests/ui/variance/variance-issue-20533.stderr | 8 +++---- 46 files changed, 90 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 692ce240e36f8..72a35de73f322 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1301,7 +1301,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ), ); span.push_span_label(expr.span, "you could clone this value"); - err.span_note( + err.span_help( span, format!("if `{ty}` implemented `Clone`, you could clone the value"), ); diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr index 8d40e6905e07f..595aefc9a2150 100644 --- a/tests/ui/associated-types/issue-25700.stderr +++ b/tests/ui/associated-types/issue-25700.stderr @@ -8,7 +8,7 @@ LL | drop(t); LL | drop(t); | ^ value used here after move | -note: if `S<()>` implemented `Clone`, you could clone the value +help: if `S<()>` implemented `Clone`, you could clone the value --> $DIR/issue-25700.rs:1:1 | LL | struct S(#[allow(dead_code)] Option<&'static T>); diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr index 3fe1431fda714..a4d239090830c 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr @@ -9,7 +9,7 @@ LL | LL | x.hello(); | - variable moved due to use in coroutine | -note: if `Ty` implemented `Clone`, you could clone the value +help: if `Ty` implemented `Clone`, you could clone the value --> $DIR/closure-shim-borrowck-error.rs:17:1 | LL | x.hello(); diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.stderr b/tests/ui/async-await/async-closures/move-out-of-ref.stderr index d443dc9d4831b..c516597c81f95 100644 --- a/tests/ui/async-await/async-closures/move-out-of-ref.stderr +++ b/tests/ui/async-await/async-closures/move-out-of-ref.stderr @@ -7,7 +7,7 @@ LL | let c = async || { LL | *x; | ^^ `*x` is moved here | -note: if `Ty` implemented `Clone`, you could clone the value +help: if `Ty` implemented `Clone`, you could clone the value --> $DIR/move-out-of-ref.rs:5:1 | LL | struct Ty; diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr index b4b60d40d9143..9eb90e169fd39 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `BAR` LL | test(BAR); | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-out-of-static-item.rs:3:1 | LL | struct Foo { diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr index b5dc01f180b2f..8dcb81273f897 100644 --- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -10,7 +10,7 @@ LL | let S { x: ax } = a; LL | f(pb); | -- borrow later used here | -note: if `S` implemented `Clone`, you could clone the value +help: if `S` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-subcomponent.rs:6:1 | LL | struct S { diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr index c3b7b0b6080c6..c838c6512bc42 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -30,7 +30,7 @@ LL | s(" world".to_string()); LL | s(" world".to_string()); | ^ value used here after move | -note: if `SFnOnce` implemented `Clone`, you could clone the value +help: if `SFnOnce` implemented `Clone`, you could clone the value --> $DIR/borrowck-overloaded-call.rs:41:1 | LL | struct SFnOnce { diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index 72580e7464b72..535550409dd87 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -59,7 +59,7 @@ LL | LL | println!("{b:?}"); | - borrow later used here | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:19:1 | LL | struct A; diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs index a20e04d3afdce..12fd2129331b9 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.rs +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; #[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters pub struct TypedAddress{ -//~^ NOTE if `TypedAddress` implemented `Clone`, you could clone the value +//~^ HELP if `TypedAddress` implemented `Clone`, you could clone the value //~| NOTE consider manually implementing `Clone` for this type //~| NOTE introduces an implicit `T: Clone` bound inner: u64, @@ -19,7 +19,7 @@ pub trait Memory { //~| NOTE this parameter takes ownership of the value fn update_value(&self, offset: TypedAddress, update: F) //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait - where F: FnOnce(T) -> T + where F: FnOnce(T) -> T //~ HELP consider further restricting type parameter `T` { let old = self.return_value(offset); //~ NOTE value moved here //~^ NOTE you could clone this value diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr index b10e3a92c96b0..31a55b448eb6d 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.stderr +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -15,7 +15,7 @@ note: consider changing this parameter type in method `return_value` to borrow i | LL | fn return_value(&self, offset: TypedAddress) -> T; | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value -note: if `TypedAddress` implemented `Clone`, you could clone the value +help: if `TypedAddress` implemented `Clone`, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index bd6c1c44bfb36..85769e187691e 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -18,7 +18,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { | ^^^^^^^^^^^ -note: if `StructB` implemented `Clone`, you could clone the value +help: if `StructB` implemented `Clone`, you could clone the value --> $DIR/issue-103624.rs:23:1 | LL | self.b; diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr index dde17d1f6523c..a5a218a0641d0 100644 --- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -11,7 +11,7 @@ note: `Example::::change` takes ownership of the receiver `self`, | LL | unsafe fn change(self) -> Example { | ^^^^ -note: if `Example` implemented `Clone`, you could clone the value +help: if `Example` implemented `Clone`, you could clone the value --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1 | LL | struct Example(PhantomData<(fn(E), fn(FakeParam))>); diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr index 057ac6d7e3df9..959b1d1a3b840 100644 --- a/tests/ui/borrowck/issue-17718-static-move.stderr +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `FOO` LL | let _a = FOO; | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 5fda92634d8f3..5336352e0dbde 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a mutable reference LL | let a = unsafe { *mut_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -24,7 +24,7 @@ error[E0507]: cannot move out of a shared reference LL | let b = unsafe { *imm_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -44,7 +44,7 @@ error[E0507]: cannot move out of a raw pointer LL | let c = unsafe { *mut_ptr() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -59,7 +59,7 @@ error[E0507]: cannot move out of a raw pointer LL | let d = unsafe { *const_ptr() }; | ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr index 1e9b1d5209cb6..f2bc6bd4760a1 100644 --- a/tests/ui/borrowck/move-error-in-promoted-2.stderr +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -7,7 +7,7 @@ LL | &([S][0],); | cannot move out of here | move occurs because value has type `S`, which does not implement the `Copy` trait | -note: if `S` implemented `Clone`, you could clone the value +help: if `S` implemented `Clone`, you could clone the value --> $DIR/move-error-in-promoted-2.rs:3:1 | LL | struct S; diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 97d140515184a..3796b7e05fb4d 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -9,7 +9,7 @@ LL | let a = $c; LL | sss!(); | ------ in this macro invocation | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-error-snippets.rs:9:1 | LL | struct A; diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr index 009e85a8031ee..af5cbdcf150f3 100644 --- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | static Y: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); @@ -19,7 +19,7 @@ error[E0507]: cannot move out of a shared reference LL | const Z: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr index bdaa9449f913e..f0d6dd3d46927 100644 --- a/tests/ui/box/leak-alloc.stderr +++ b/tests/ui/box/leak-alloc.stderr @@ -12,7 +12,7 @@ LL | LL | use_value(*theref) | ------- borrow later used here | -note: if `Alloc` implemented `Clone`, you could clone the value +help: if `Alloc` implemented `Clone`, you could clone the value --> $DIR/leak-alloc.rs:8:1 | LL | struct Alloc {} diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs index 3326af7486c5e..b55c8c16f611c 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs @@ -1,5 +1,5 @@ //! regression test for -struct NoCopy; //~ NOTE if `NoCopy` implemented `Clone`, you could clone the value +struct NoCopy; //~ HELP if `NoCopy` implemented `Clone`, you could clone the value //~^ NOTE consider implementing `Clone` for this type fn main() { let x = NoCopy; diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr index 94f80da1b10a4..bde39ca6ca71e 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr @@ -13,7 +13,7 @@ LL | let y = x; LL | let z = x; | ^ value used here after move | -note: if `NoCopy` implemented `Clone`, you could clone the value +help: if `NoCopy` implemented `Clone`, you could clone the value --> $DIR/closure-move-use-after-move-diagnostic.rs:2:1 | LL | struct NoCopy; diff --git a/tests/ui/coroutine/moved-twice.stderr b/tests/ui/coroutine/moved-twice.stderr index 2b21f6c59f0bc..561b3b331d9f4 100644 --- a/tests/ui/coroutine/moved-twice.stderr +++ b/tests/ui/coroutine/moved-twice.stderr @@ -10,7 +10,7 @@ LL | yield; LL | let second = first; | ^^^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/moved-twice.rs:9:1 | LL | struct Foo([u8; FOO_SIZE]); diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 9cfc4abdc0cb5..7c716fb9dd4ca 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -7,7 +7,7 @@ LL | #[repr(packed)] LL | struct X(Y); | ^ move occurs because value has type `Y`, which does not implement the `Copy` trait | -note: if `Y` implemented `Clone`, you could clone the value +help: if `Y` implemented `Clone`, you could clone the value --> $DIR/deriving-with-repr-packed.rs:16:1 | LL | struct Y(usize); diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr index c4cbc834ad98c..528f311765df6 100644 --- a/tests/ui/error-codes/E0504.stderr +++ b/tests/ui/error-codes/E0504.stderr @@ -14,7 +14,7 @@ LL | println!("child function: {}", fancy_num.num); LL | println!("main function: {}", fancy_ref.num); | ------------- borrow later used here | -note: if `FancyNum` implemented `Clone`, you could clone the value +help: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0504.rs:2:1 | LL | struct FancyNum { diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr index 3f2913e9fe3c6..ac0f390bc54b1 100644 --- a/tests/ui/error-codes/E0505.stderr +++ b/tests/ui/error-codes/E0505.stderr @@ -11,7 +11,7 @@ LL | eat(x); LL | _ref_to_val.use_ref(); | ----------- borrow later used here | -note: if `Value` implemented `Clone`, you could clone the value +help: if `Value` implemented `Clone`, you could clone the value --> $DIR/E0505.rs:1:1 | LL | struct Value {} diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr index 70d99ea2cce5c..ac03e5ea9cd5a 100644 --- a/tests/ui/error-codes/E0507.stderr +++ b/tests/ui/error-codes/E0507.stderr @@ -11,7 +11,7 @@ note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, w | LL | fn nothing_is_true(self) {} | ^^^^ -note: if `TheDarkKnight` implemented `Clone`, you could clone the value +help: if `TheDarkKnight` implemented `Clone`, you could clone the value --> $DIR/E0507.rs:3:1 | LL | struct TheDarkKnight; diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr index fcfac399e0df5..48ede17dc26a8 100644 --- a/tests/ui/error-codes/E0508-fail.stderr +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508-fail.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr index b9fa0f4d17a5f..c001b9461ebf3 100644 --- a/tests/ui/error-codes/E0508.stderr +++ b/tests/ui/error-codes/E0508.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr index 628a253e08593..89c3a5848423e 100644 --- a/tests/ui/error-codes/E0509.stderr +++ b/tests/ui/error-codes/E0509.stderr @@ -7,7 +7,7 @@ LL | let fancy_field = drop_struct.fancy; | cannot move out of here | move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait | -note: if `FancyNum` implemented `Clone`, you could clone the value +help: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0509.rs:1:1 | LL | struct FancyNum { diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr index 162d7ac031a67..7aafe081deaf2 100644 --- a/tests/ui/mir/issue-102389.stderr +++ b/tests/ui/mir/issue-102389.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*inbounds` which is behind a shared reference LL | array[*inbounds as usize] | ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait | -note: if `Enum` implemented `Clone`, you could clone the value +help: if `Enum` implemented `Clone`, you could clone the value --> $DIR/issue-102389.rs:1:1 | LL | enum Enum { A, B, C } diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs index 8f2e01bdf1aba..965a4206253e2 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.rs +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -3,10 +3,10 @@ // 'value moved in previous iteration of loop' message struct NonCopy; -//~^ NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` +//~^ HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type @@ -70,6 +70,7 @@ fn moved_loop_2() { fn uninit_1() { loop { let value: NonCopy; //~ NOTE declared here + //~^ HELP consider assigning a value let _used = value; //~ ERROR binding `value` isn't initialized //~^ NOTE `value` used here but it isn't initialized } @@ -77,6 +78,7 @@ fn uninit_1() { fn uninit_2() { let mut value: NonCopy; //~ NOTE declared here + //~^ HELP consider assigning a value loop { let _used = value; //~ ERROR binding `value` isn't initialized //~^ NOTE `value` used here but it isn't initialized diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index 3a93769ac4549..1c54d3997ed6d 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -10,7 +10,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -33,7 +33,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -53,7 +53,7 @@ LL | loop { LL | let _used = value; | ^^^^^ value moved here, in previous iteration of loop | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -73,7 +73,7 @@ LL | loop { LL | let _used2 = value; | ^^^^^ value moved here, in previous iteration of loop | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -83,10 +83,11 @@ LL | let _used2 = value; | ----- you could clone this value error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:73:21 + --> $DIR/issue-72649-uninit-in-loop.rs:74:21 | LL | let value: NonCopy; | ----- binding declared here but left uninitialized +LL | LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized | @@ -96,11 +97,11 @@ LL | let value: NonCopy = /* value */; | +++++++++++++ error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:81:21 + --> $DIR/issue-72649-uninit-in-loop.rs:83:21 | LL | let mut value: NonCopy; | --------- binding declared here but left uninitialized -LL | loop { +... LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized | diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr index 815e91b0f4df2..3fc50c48315d5 100644 --- a/tests/ui/moves/issue-75904-move-closure-loop.stderr +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -11,7 +11,7 @@ LL | &mut a; LL | a; | - use occurs due to use in closure | -note: if `NotCopy` implemented `Clone`, you could clone the value +help: if `NotCopy` implemented `Clone`, you could clone the value --> $DIR/issue-75904-move-closure-loop.rs:5:1 | LL | struct NotCopy; diff --git a/tests/ui/moves/matching-partially-moved-value-17385.stderr b/tests/ui/moves/matching-partially-moved-value-17385.stderr index 906f7868bccbf..83f4f4320485b 100644 --- a/tests/ui/moves/matching-partially-moved-value-17385.stderr +++ b/tests/ui/moves/matching-partially-moved-value-17385.stderr @@ -8,7 +8,7 @@ LL | drop(foo); LL | match foo { | ^^^^^^^^^ value used here after move | -note: if `X` implemented `Clone`, you could clone the value +help: if `X` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:2:1 | LL | struct X(isize); @@ -27,7 +27,7 @@ LL | drop(e); LL | match e { | ^ value used here after move | -note: if `Enum` implemented `Clone`, you could clone the value +help: if `Enum` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:4:1 | LL | enum Enum { diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index de19a99d388ca..b3a1215fa2f73 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -132,7 +132,7 @@ LL | foo_add + Foo; LL | foo_add; | ^^^^^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-fn-self-receiver.rs:5:1 | LL | struct Foo; diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr index 8a030f0219207..7ef859200b213 100644 --- a/tests/ui/moves/move-out-of-array-1.stderr +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -7,7 +7,7 @@ LL | a[i] | cannot move out of here | move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait | -note: if `D` implemented `Clone`, you could clone the value +help: if `D` implemented `Clone`, you could clone the value --> $DIR/move-out-of-array-1.rs:5:1 | LL | struct D { _x: u8 } diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.stderr b/tests/ui/moves/moved-value-on-as-ref-arg.stderr index a99bdb4fe9d41..b553938c6fede 100644 --- a/tests/ui/moves/moved-value-on-as-ref-arg.stderr +++ b/tests/ui/moves/moved-value-on-as-ref-arg.stderr @@ -23,7 +23,7 @@ LL | qux(bar); LL | let _baa = bar; | ^^^ value used here after move | -note: if `Bar` implemented `Clone`, you could clone the value +help: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; @@ -61,7 +61,7 @@ LL | baz(bar); LL | let _baa = bar; | ^^^ value used here after move | -note: if `Bar` implemented `Clone`, you could clone the value +help: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr index 496a298a36ce9..84c543921687b 100644 --- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr @@ -28,7 +28,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; s.y = Box::new(20); | ^^^^^^^^ value partially assigned here after move | -note: if `S>` implemented `Clone`, you could clone the value +help: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { @@ -82,7 +82,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; | ^^^^^^^^ value partially assigned here after move | -note: if `S>` implemented `Clone`, you could clone the value +help: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index bcb2ab84a239b..e84f754552175 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | let b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -27,7 +27,7 @@ LL | let b = a[0]; | cannot move out of here | move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -46,7 +46,7 @@ error[E0507]: cannot move out of `**r` which is behind a shared reference LL | let s = **r; | ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -66,7 +66,7 @@ error[E0507]: cannot move out of an `Rc` LL | let s = *r; | ^^ move occurs because value has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -89,7 +89,7 @@ LL | let a = [A("".to_string())][0]; | cannot move out of here | move occurs because value has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -137,7 +137,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr index cc438461a5d15..f9bef8d83f96f 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -8,7 +8,7 @@ LL | foo_pin_mut(&pin mut foo); LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -27,7 +27,7 @@ LL | let x = &pin mut foo; LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -46,7 +46,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -65,7 +65,7 @@ LL | let x = &pin mut foo; // ok LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -87,7 +87,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -106,7 +106,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -125,7 +125,7 @@ LL | let x = &pin mut foo; // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -144,7 +144,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -163,7 +163,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -185,7 +185,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -204,7 +204,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -223,7 +223,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr index bf9921343ee7d..523191655813b 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -33,7 +33,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -55,7 +55,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -77,7 +77,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr index 3f46602098850..cf7d50091ba45 100644 --- a/tests/ui/pin-macro/pin_move.stderr +++ b/tests/ui/pin-macro/pin_move.stderr @@ -8,7 +8,7 @@ LL | pin!(pointee); LL | let _moved = pointee; | ^^^^^^^ value used here after move | -note: if `a::NotCopy` implemented `Clone`, you could clone the value +help: if `a::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:7:5 | LL | struct NotCopy(T); @@ -23,7 +23,7 @@ error[E0507]: cannot move out of a mutable reference LL | pin!(*&mut pointee); | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy`, which does not implement the `Copy` trait | -note: if `b::NotCopy` implemented `Clone`, you could clone the value +help: if `b::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:16:5 | LL | struct NotCopy(T); diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr index 62f24324fcc17..5e447a57bfee0 100644 --- a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr @@ -7,7 +7,7 @@ LL | (b,) = *tuple; | data moved here | move occurs because the place has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/non_copy_move_out_of_tuple.rs:3:1 | LL | struct NonCopy; diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr index f78d3cf678629..cd13592d652e8 100644 --- a/tests/ui/suggestions/option-content-move3.stderr +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -10,7 +10,7 @@ LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait | = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once -note: if `NotCopyable` implemented `Clone`, you could clone the value +help: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; @@ -43,7 +43,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | fn func H, H: FnMut()>(_: F) {} | ^^^^^^^^^^^^ -note: if `NotCopyable` implemented `Clone`, you could clone the value +help: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr index 461ee407e2ddb..5974441dd807d 100644 --- a/tests/ui/union/union-borrow-move-parent-sibling.stderr +++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr @@ -59,7 +59,7 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, Moc LL | let a = (u.x.0).0; | ^^^^^^^^^ move occurs because value has type `MockVec`, which does not implement the `Copy` trait | -note: if `MockVec` implemented `Clone`, you could clone the value +help: if `MockVec` implemented `Clone`, you could clone the value --> $DIR/union-borrow-move-parent-sibling.rs:25:1 | LL | struct MockVec { diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr index d520fb00ea9d5..6266bb4770e0e 100644 --- a/tests/ui/union/union-move.stderr +++ b/tests/ui/union/union-move.stderr @@ -16,7 +16,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -note: if `U1` implemented `Clone`, you could clone the value +help: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { @@ -43,7 +43,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -note: if `U1` implemented `Clone`, you could clone the value +help: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr index 21d8de6ae8815..2a33a88bdd56a 100644 --- a/tests/ui/variance/variance-issue-20533.stderr +++ b/tests/ui/variance/variance-issue-20533.stderr @@ -10,7 +10,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -31,7 +31,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -52,7 +52,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -73,7 +73,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); From 8543404e8d8668d9834dc48a687d5096d4949f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 21:33:39 +0000 Subject: [PATCH 33/47] Tweak span in E0599 --- .../rustc_hir_typeck/src/method/suggest.rs | 50 ++++++++++++------- .../derives/derive-assoc-type-not-impl.stderr | 6 ++- .../deriving-with-repr-packed-2.stderr | 7 ++- tests/ui/union/union-derive-clone.stderr | 6 ++- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f5ef5adff6bd1..517d73f517833 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1752,16 +1752,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. - let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) { - Some(ObligationCauseCode::ImplDerived(data)) => { - (data.impl_or_alias_def_id, data.span) - } - Some( - ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) - | ObligationCauseCode::WhereClause(def_id, span), - ) if !span.is_dummy() => (*def_id, *span), - _ => continue, - }; + let (item_def_id, cause_span, cause_msg) = + match cause.as_ref().map(|cause| cause.code()) { + Some(ObligationCauseCode::ImplDerived(data)) => { + let msg = if let DefKind::Impl { of_trait: true } = + self.tcx.def_kind(data.impl_or_alias_def_id) + { + format!( + "type parameter would need to implement `{}`", + self.tcx + .item_name(self.tcx.impl_trait_id(data.impl_or_alias_def_id)) + ) + } else { + format!("unsatisfied bound `{p}` introduced here") + }; + (data.impl_or_alias_def_id, data.span, msg) + } + Some( + ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) + | ObligationCauseCode::WhereClause(def_id, span), + ) if !span.is_dummy() => { + (*def_id, *span, format!("unsatisfied bound `{p}` introduced here")) + } + _ => continue, + }; // Don't point out the span of `WellFormed` predicates. if !matches!( @@ -1792,10 +1806,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let entry = entry.or_insert_with(|| { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); - entry.0.insert(span); + entry.0.insert(cause_span); entry.1.insert(( - span, - "unsatisfied trait bound introduced in this `derive` macro", + cause_span, + cause_msg, )); entry.2.push(p); skip_list.insert(p); @@ -1844,7 +1858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.2.push(p); if cause_span != *item_span { entry.0.insert(cause_span); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); } else { if let Some(of_trait) = of_trait { entry.0.insert(of_trait.trait_ref.path.span); @@ -1852,9 +1866,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.0.insert(self_ty.span); }; if let Some(of_trait) = of_trait { - entry.1.insert((of_trait.trait_ref.path.span, "")); + entry.1.insert((of_trait.trait_ref.path.span, String::new())); } - entry.1.insert((self_ty.span, "")); + entry.1.insert((self_ty.span, String::new())); } Some(Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, rustc_ast::ast::IsAuto::Yes, ..), @@ -1883,8 +1897,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.0.insert(cause_span); - entry.1.insert((ident.span, "")); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((ident.span, String::new())); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); entry.2.push(p); } _ => { diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index e239ad4ef2091..ca968910fde43 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -11,10 +11,12 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar` due to unsatisfied trait bounds | note: trait bound `NotClone: Clone` was not satisfied - --> $DIR/derive-assoc-type-not-impl.rs:6:10 + --> $DIR/derive-assoc-type-not-impl.rs:7:12 | LL | #[derive(Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | struct Bar { + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NotClone` with `#[derive(Clone)]` | diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index fff6269472bd3..6bd3fff39790a 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -21,10 +21,13 @@ LL | let x: Foo = Foo(NonCopy, NonCopy, NonCopy); note: the following trait bounds were not satisfied: `NonCopy: Clone` `NonCopy: Copy` - --> $DIR/deriving-with-repr-packed-2.rs:5:16 + --> $DIR/deriving-with-repr-packed-2.rs:7:16 | LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | #[repr(packed)] +LL | pub struct Foo(T, T, T); + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NonCopy` with `#[derive(Clone, Copy)]` | diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index 65488629b629b..62ef35b761922 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -25,10 +25,12 @@ LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds | note: trait bound `CloneNoCopy: Copy` was not satisfied - --> $DIR/union-derive-clone.rs:25:10 + --> $DIR/union-derive-clone.rs:26:10 | LL | #[derive(Clone, Copy)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | union U5 { + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | From dffec20dee76131f74736f05f01abf44161d3264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 21:54:43 +0000 Subject: [PATCH 34/47] Tweak help to unify formatting and wording --- .../src/diagnostics/conflict_errors.rs | 27 +++++++++++-------- tests/ui/associated-types/issue-25700.stderr | 2 +- .../closure-shim-borrowck-error.stderr | 2 +- .../async-closures/move-out-of-ref.stderr | 2 +- .../borrowck-move-out-of-static-item.stderr | 2 +- .../borrowck-move-subcomponent.stderr | 2 +- .../borrowck/borrowck-overloaded-call.stderr | 2 +- tests/ui/borrowck/clone-on-ref.stderr | 2 +- .../borrowck/derive-clone-implicit-bound.rs | 26 +++++++++--------- .../derive-clone-implicit-bound.stderr | 12 ++++----- tests/ui/borrowck/issue-103624.stderr | 2 +- .../issue-119915-bad-clone-suggestion.stderr | 2 +- .../borrowck/issue-17718-static-move.stderr | 2 +- tests/ui/borrowck/issue-20801.stderr | 8 +++--- .../borrowck/move-error-in-promoted-2.stderr | 2 +- tests/ui/borrowck/move-error-snippets.stderr | 2 +- ...e-in-static-initializer-issue-38520.stderr | 4 +-- tests/ui/box/leak-alloc.stderr | 2 +- .../closure-move-use-after-move-diagnostic.rs | 16 +++++------ ...sure-move-use-after-move-diagnostic.stderr | 2 +- tests/ui/coroutine/moved-twice.stderr | 2 +- .../derives/deriving-with-repr-packed.stderr | 2 +- tests/ui/error-codes/E0504.stderr | 2 +- tests/ui/error-codes/E0505.stderr | 2 +- tests/ui/error-codes/E0507.stderr | 2 +- tests/ui/error-codes/E0508-fail.stderr | 2 +- tests/ui/error-codes/E0508.stderr | 2 +- tests/ui/error-codes/E0509.stderr | 2 +- tests/ui/mir/issue-102389.stderr | 2 +- tests/ui/moves/issue-72649-uninit-in-loop.rs | 8 +++--- .../moves/issue-72649-uninit-in-loop.stderr | 8 +++--- .../issue-75904-move-closure-loop.stderr | 2 +- ...atching-partially-moved-value-17385.stderr | 4 +-- tests/ui/moves/move-fn-self-receiver.stderr | 2 +- tests/ui/moves/move-out-of-array-1.stderr | 2 +- .../ui/moves/moved-value-on-as-ref-arg.stderr | 4 +-- .../issue-21232-partial-init-and-use.stderr | 4 +-- tests/ui/nll/move-errors.stderr | 12 ++++----- .../pin-ergonomics/borrow-unpin.pinned.stderr | 24 ++++++++--------- .../pin-ergonomics/borrow-unpin.unpin.stderr | 6 ++--- tests/ui/pin-macro/pin_move.stderr | 4 +-- .../non_copy_move_out_of_tuple.stderr | 2 +- .../suggestions/option-content-move3.stderr | 4 +-- .../union-borrow-move-parent-sibling.stderr | 2 +- tests/ui/union/union-move.stderr | 4 +-- tests/ui/variance/variance-issue-20533.stderr | 8 +++--- 46 files changed, 122 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 72a35de73f322..a39300f7030f2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1293,18 +1293,23 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } }, ); - span.push_span_label( - ty_span, - format!( - "consider {}implementing `Clone` for this type", - if derive_clone { "manually " } else { "" } - ), - ); + let msg = if !derive_clone { + span.push_span_label( + ty_span, + format!( + "consider {}implementing `Clone` for this type", + if derive_clone { "manually " } else { "" } + ), + ); + format!("if `{ty}` implemented `Clone`, you could clone the value") + } else { + format!("if all bounds were met, you could clone the value") + }; span.push_span_label(expr.span, "you could clone this value"); - err.span_help( - span, - format!("if `{ty}` implemented `Clone`, you could clone the value"), - ); + err.span_note(span, msg); + if derive_clone { + err.help("consider manually implementing `Clone` to avoid undesired bounds"); + } } else if let ty::Param(param) = ty.kind() && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() && let generics = self.infcx.tcx.generics_of(self.mir_def_id()) diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr index 595aefc9a2150..8d40e6905e07f 100644 --- a/tests/ui/associated-types/issue-25700.stderr +++ b/tests/ui/associated-types/issue-25700.stderr @@ -8,7 +8,7 @@ LL | drop(t); LL | drop(t); | ^ value used here after move | -help: if `S<()>` implemented `Clone`, you could clone the value +note: if `S<()>` implemented `Clone`, you could clone the value --> $DIR/issue-25700.rs:1:1 | LL | struct S(#[allow(dead_code)] Option<&'static T>); diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr index a4d239090830c..3fe1431fda714 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr @@ -9,7 +9,7 @@ LL | LL | x.hello(); | - variable moved due to use in coroutine | -help: if `Ty` implemented `Clone`, you could clone the value +note: if `Ty` implemented `Clone`, you could clone the value --> $DIR/closure-shim-borrowck-error.rs:17:1 | LL | x.hello(); diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.stderr b/tests/ui/async-await/async-closures/move-out-of-ref.stderr index c516597c81f95..d443dc9d4831b 100644 --- a/tests/ui/async-await/async-closures/move-out-of-ref.stderr +++ b/tests/ui/async-await/async-closures/move-out-of-ref.stderr @@ -7,7 +7,7 @@ LL | let c = async || { LL | *x; | ^^ `*x` is moved here | -help: if `Ty` implemented `Clone`, you could clone the value +note: if `Ty` implemented `Clone`, you could clone the value --> $DIR/move-out-of-ref.rs:5:1 | LL | struct Ty; diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr index 9eb90e169fd39..b4b60d40d9143 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `BAR` LL | test(BAR); | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-out-of-static-item.rs:3:1 | LL | struct Foo { diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr index 8dcb81273f897..b5dc01f180b2f 100644 --- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -10,7 +10,7 @@ LL | let S { x: ax } = a; LL | f(pb); | -- borrow later used here | -help: if `S` implemented `Clone`, you could clone the value +note: if `S` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-subcomponent.rs:6:1 | LL | struct S { diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr index c838c6512bc42..c3b7b0b6080c6 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -30,7 +30,7 @@ LL | s(" world".to_string()); LL | s(" world".to_string()); | ^ value used here after move | -help: if `SFnOnce` implemented `Clone`, you could clone the value +note: if `SFnOnce` implemented `Clone`, you could clone the value --> $DIR/borrowck-overloaded-call.rs:41:1 | LL | struct SFnOnce { diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index 535550409dd87..72580e7464b72 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -59,7 +59,7 @@ LL | LL | println!("{b:?}"); | - borrow later used here | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:19:1 | LL | struct A; diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs index 12fd2129331b9..cd92ac1e9e598 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.rs +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -2,11 +2,10 @@ use std::marker::PhantomData; -#[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters +#[derive(Clone, Copy)] //~ NOTE: derived `Clone` adds implicit bounds on type parameters pub struct TypedAddress{ -//~^ HELP if `TypedAddress` implemented `Clone`, you could clone the value -//~| NOTE consider manually implementing `Clone` for this type -//~| NOTE introduces an implicit `T: Clone` bound +//~^ NOTE: if all bounds were met, you could clone the value +//~| NOTE: introduces an implicit `T: Clone` bound inner: u64, phantom: PhantomData, } @@ -14,18 +13,19 @@ pub struct TypedAddress{ pub trait Memory { fn write_value(&self, offset: TypedAddress, value: &T); fn return_value(&self, offset: TypedAddress) -> T; - //~^ NOTE consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary - //~| NOTE in this method - //~| NOTE this parameter takes ownership of the value + //~^ NOTE: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + //~| NOTE: in this method + //~| NOTE: this parameter takes ownership of the value fn update_value(&self, offset: TypedAddress, update: F) - //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait - where F: FnOnce(T) -> T //~ HELP consider further restricting type parameter `T` + //~^ NOTE: move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait + where F: FnOnce(T) -> T //~ HELP: consider further restricting type parameter `T` { - let old = self.return_value(offset); //~ NOTE value moved here - //~^ NOTE you could clone this value + let old = self.return_value(offset); //~ NOTE: value moved here + //~^ NOTE: you could clone this value let new = update(old); - self.write_value(offset, &new); //~ ERROR use of moved value: `offset` - //~^ NOTE value used here after move + self.write_value(offset, &new); //~ ERROR: use of moved value: `offset` + //~^ NOTE: value used here after move + //~| HELP: consider manually implementing `Clone` to avoid undesired bounds } } diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr index 31a55b448eb6d..246fd1eaf0752 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.stderr +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `offset` - --> $DIR/derive-clone-implicit-bound.rs:27:26 + --> $DIR/derive-clone-implicit-bound.rs:26:26 | LL | fn update_value(&self, offset: TypedAddress, update: F) | ------ move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait @@ -11,23 +11,23 @@ LL | self.write_value(offset, &new); | ^^^^^^ value used here after move | note: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary - --> $DIR/derive-clone-implicit-bound.rs:16:39 + --> $DIR/derive-clone-implicit-bound.rs:15:39 | LL | fn return_value(&self, offset: TypedAddress) -> T; | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value -help: if `TypedAddress` implemented `Clone`, you could clone the value +note: if all bounds were met, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] | ----- derived `Clone` adds implicit bounds on type parameters LL | pub struct TypedAddress{ | ^^^^^^^^^^^^^^^^^^^^^^^^-^ - | | | - | | introduces an implicit `T: Clone` bound - | consider manually implementing `Clone` for this type + | | + | introduces an implicit `T: Clone` bound ... LL | let old = self.return_value(offset); | ------ you could clone this value + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `T` with trait `Copy` | LL | where F: FnOnce(T) -> T, T: Copy diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index 85769e187691e..bd6c1c44bfb36 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -18,7 +18,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { | ^^^^^^^^^^^ -help: if `StructB` implemented `Clone`, you could clone the value +note: if `StructB` implemented `Clone`, you could clone the value --> $DIR/issue-103624.rs:23:1 | LL | self.b; diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr index a5a218a0641d0..dde17d1f6523c 100644 --- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -11,7 +11,7 @@ note: `Example::::change` takes ownership of the receiver `self`, | LL | unsafe fn change(self) -> Example { | ^^^^ -help: if `Example` implemented `Clone`, you could clone the value +note: if `Example` implemented `Clone`, you could clone the value --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1 | LL | struct Example(PhantomData<(fn(E), fn(FakeParam))>); diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr index 959b1d1a3b840..057ac6d7e3df9 100644 --- a/tests/ui/borrowck/issue-17718-static-move.stderr +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `FOO` LL | let _a = FOO; | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 5336352e0dbde..5fda92634d8f3 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a mutable reference LL | let a = unsafe { *mut_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -24,7 +24,7 @@ error[E0507]: cannot move out of a shared reference LL | let b = unsafe { *imm_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -44,7 +44,7 @@ error[E0507]: cannot move out of a raw pointer LL | let c = unsafe { *mut_ptr() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -59,7 +59,7 @@ error[E0507]: cannot move out of a raw pointer LL | let d = unsafe { *const_ptr() }; | ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr index f2bc6bd4760a1..1e9b1d5209cb6 100644 --- a/tests/ui/borrowck/move-error-in-promoted-2.stderr +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -7,7 +7,7 @@ LL | &([S][0],); | cannot move out of here | move occurs because value has type `S`, which does not implement the `Copy` trait | -help: if `S` implemented `Clone`, you could clone the value +note: if `S` implemented `Clone`, you could clone the value --> $DIR/move-error-in-promoted-2.rs:3:1 | LL | struct S; diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 3796b7e05fb4d..97d140515184a 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -9,7 +9,7 @@ LL | let a = $c; LL | sss!(); | ------ in this macro invocation | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-error-snippets.rs:9:1 | LL | struct A; diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr index af5cbdcf150f3..009e85a8031ee 100644 --- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | static Y: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); @@ -19,7 +19,7 @@ error[E0507]: cannot move out of a shared reference LL | const Z: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr index f0d6dd3d46927..bdaa9449f913e 100644 --- a/tests/ui/box/leak-alloc.stderr +++ b/tests/ui/box/leak-alloc.stderr @@ -12,7 +12,7 @@ LL | LL | use_value(*theref) | ------- borrow later used here | -help: if `Alloc` implemented `Clone`, you could clone the value +note: if `Alloc` implemented `Clone`, you could clone the value --> $DIR/leak-alloc.rs:8:1 | LL | struct Alloc {} diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs index b55c8c16f611c..863bcedd01e6d 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs @@ -1,16 +1,16 @@ //! regression test for -struct NoCopy; //~ HELP if `NoCopy` implemented `Clone`, you could clone the value -//~^ NOTE consider implementing `Clone` for this type +struct NoCopy; //~ NOTE: if `NoCopy` implemented `Clone`, you could clone the value +//~^ NOTE: consider implementing `Clone` for this type fn main() { let x = NoCopy; - //~^ NOTE move occurs because `x` has type `NoCopy` + //~^ NOTE: move occurs because `x` has type `NoCopy` let f = move || { - //~^ NOTE value moved into closure here + //~^ NOTE: value moved into closure here let y = x; - //~^ NOTE variable moved due to use in closure - //~| NOTE you could clone this value + //~^ NOTE: variable moved due to use in closure + //~| NOTE: you could clone this value }; let z = x; - //~^ ERROR use of moved value: `x` - //~| NOTE value used here after move + //~^ ERROR: use of moved value: `x` + //~| NOTE: value used here after move } diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr index bde39ca6ca71e..94f80da1b10a4 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr @@ -13,7 +13,7 @@ LL | let y = x; LL | let z = x; | ^ value used here after move | -help: if `NoCopy` implemented `Clone`, you could clone the value +note: if `NoCopy` implemented `Clone`, you could clone the value --> $DIR/closure-move-use-after-move-diagnostic.rs:2:1 | LL | struct NoCopy; diff --git a/tests/ui/coroutine/moved-twice.stderr b/tests/ui/coroutine/moved-twice.stderr index 561b3b331d9f4..2b21f6c59f0bc 100644 --- a/tests/ui/coroutine/moved-twice.stderr +++ b/tests/ui/coroutine/moved-twice.stderr @@ -10,7 +10,7 @@ LL | yield; LL | let second = first; | ^^^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/moved-twice.rs:9:1 | LL | struct Foo([u8; FOO_SIZE]); diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 7c716fb9dd4ca..9cfc4abdc0cb5 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -7,7 +7,7 @@ LL | #[repr(packed)] LL | struct X(Y); | ^ move occurs because value has type `Y`, which does not implement the `Copy` trait | -help: if `Y` implemented `Clone`, you could clone the value +note: if `Y` implemented `Clone`, you could clone the value --> $DIR/deriving-with-repr-packed.rs:16:1 | LL | struct Y(usize); diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr index 528f311765df6..c4cbc834ad98c 100644 --- a/tests/ui/error-codes/E0504.stderr +++ b/tests/ui/error-codes/E0504.stderr @@ -14,7 +14,7 @@ LL | println!("child function: {}", fancy_num.num); LL | println!("main function: {}", fancy_ref.num); | ------------- borrow later used here | -help: if `FancyNum` implemented `Clone`, you could clone the value +note: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0504.rs:2:1 | LL | struct FancyNum { diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr index ac0f390bc54b1..3f2913e9fe3c6 100644 --- a/tests/ui/error-codes/E0505.stderr +++ b/tests/ui/error-codes/E0505.stderr @@ -11,7 +11,7 @@ LL | eat(x); LL | _ref_to_val.use_ref(); | ----------- borrow later used here | -help: if `Value` implemented `Clone`, you could clone the value +note: if `Value` implemented `Clone`, you could clone the value --> $DIR/E0505.rs:1:1 | LL | struct Value {} diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr index ac03e5ea9cd5a..70d99ea2cce5c 100644 --- a/tests/ui/error-codes/E0507.stderr +++ b/tests/ui/error-codes/E0507.stderr @@ -11,7 +11,7 @@ note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, w | LL | fn nothing_is_true(self) {} | ^^^^ -help: if `TheDarkKnight` implemented `Clone`, you could clone the value +note: if `TheDarkKnight` implemented `Clone`, you could clone the value --> $DIR/E0507.rs:3:1 | LL | struct TheDarkKnight; diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr index 48ede17dc26a8..fcfac399e0df5 100644 --- a/tests/ui/error-codes/E0508-fail.stderr +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508-fail.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr index c001b9461ebf3..b9fa0f4d17a5f 100644 --- a/tests/ui/error-codes/E0508.stderr +++ b/tests/ui/error-codes/E0508.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr index 89c3a5848423e..628a253e08593 100644 --- a/tests/ui/error-codes/E0509.stderr +++ b/tests/ui/error-codes/E0509.stderr @@ -7,7 +7,7 @@ LL | let fancy_field = drop_struct.fancy; | cannot move out of here | move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait | -help: if `FancyNum` implemented `Clone`, you could clone the value +note: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0509.rs:1:1 | LL | struct FancyNum { diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr index 7aafe081deaf2..162d7ac031a67 100644 --- a/tests/ui/mir/issue-102389.stderr +++ b/tests/ui/mir/issue-102389.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*inbounds` which is behind a shared reference LL | array[*inbounds as usize] | ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait | -help: if `Enum` implemented `Clone`, you could clone the value +note: if `Enum` implemented `Clone`, you could clone the value --> $DIR/issue-102389.rs:1:1 | LL | enum Enum { A, B, C } diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs index 965a4206253e2..f115656d7c0dd 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.rs +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -3,10 +3,10 @@ // 'value moved in previous iteration of loop' message struct NonCopy; -//~^ HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` +//~^ NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index 1c54d3997ed6d..8bde3b5c042db 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -10,7 +10,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -33,7 +33,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -53,7 +53,7 @@ LL | loop { LL | let _used = value; | ^^^^^ value moved here, in previous iteration of loop | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -73,7 +73,7 @@ LL | loop { LL | let _used2 = value; | ^^^^^ value moved here, in previous iteration of loop | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr index 3fc50c48315d5..815e91b0f4df2 100644 --- a/tests/ui/moves/issue-75904-move-closure-loop.stderr +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -11,7 +11,7 @@ LL | &mut a; LL | a; | - use occurs due to use in closure | -help: if `NotCopy` implemented `Clone`, you could clone the value +note: if `NotCopy` implemented `Clone`, you could clone the value --> $DIR/issue-75904-move-closure-loop.rs:5:1 | LL | struct NotCopy; diff --git a/tests/ui/moves/matching-partially-moved-value-17385.stderr b/tests/ui/moves/matching-partially-moved-value-17385.stderr index 83f4f4320485b..906f7868bccbf 100644 --- a/tests/ui/moves/matching-partially-moved-value-17385.stderr +++ b/tests/ui/moves/matching-partially-moved-value-17385.stderr @@ -8,7 +8,7 @@ LL | drop(foo); LL | match foo { | ^^^^^^^^^ value used here after move | -help: if `X` implemented `Clone`, you could clone the value +note: if `X` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:2:1 | LL | struct X(isize); @@ -27,7 +27,7 @@ LL | drop(e); LL | match e { | ^ value used here after move | -help: if `Enum` implemented `Clone`, you could clone the value +note: if `Enum` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:4:1 | LL | enum Enum { diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index b3a1215fa2f73..de19a99d388ca 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -132,7 +132,7 @@ LL | foo_add + Foo; LL | foo_add; | ^^^^^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-fn-self-receiver.rs:5:1 | LL | struct Foo; diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr index 7ef859200b213..8a030f0219207 100644 --- a/tests/ui/moves/move-out-of-array-1.stderr +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -7,7 +7,7 @@ LL | a[i] | cannot move out of here | move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait | -help: if `D` implemented `Clone`, you could clone the value +note: if `D` implemented `Clone`, you could clone the value --> $DIR/move-out-of-array-1.rs:5:1 | LL | struct D { _x: u8 } diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.stderr b/tests/ui/moves/moved-value-on-as-ref-arg.stderr index b553938c6fede..a99bdb4fe9d41 100644 --- a/tests/ui/moves/moved-value-on-as-ref-arg.stderr +++ b/tests/ui/moves/moved-value-on-as-ref-arg.stderr @@ -23,7 +23,7 @@ LL | qux(bar); LL | let _baa = bar; | ^^^ value used here after move | -help: if `Bar` implemented `Clone`, you could clone the value +note: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; @@ -61,7 +61,7 @@ LL | baz(bar); LL | let _baa = bar; | ^^^ value used here after move | -help: if `Bar` implemented `Clone`, you could clone the value +note: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr index 84c543921687b..496a298a36ce9 100644 --- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr @@ -28,7 +28,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; s.y = Box::new(20); | ^^^^^^^^ value partially assigned here after move | -help: if `S>` implemented `Clone`, you could clone the value +note: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { @@ -82,7 +82,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; | ^^^^^^^^ value partially assigned here after move | -help: if `S>` implemented `Clone`, you could clone the value +note: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index e84f754552175..bcb2ab84a239b 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | let b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -27,7 +27,7 @@ LL | let b = a[0]; | cannot move out of here | move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -46,7 +46,7 @@ error[E0507]: cannot move out of `**r` which is behind a shared reference LL | let s = **r; | ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -66,7 +66,7 @@ error[E0507]: cannot move out of an `Rc` LL | let s = *r; | ^^ move occurs because value has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -89,7 +89,7 @@ LL | let a = [A("".to_string())][0]; | cannot move out of here | move occurs because value has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -137,7 +137,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr index f9bef8d83f96f..cc438461a5d15 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -8,7 +8,7 @@ LL | foo_pin_mut(&pin mut foo); LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -27,7 +27,7 @@ LL | let x = &pin mut foo; LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -46,7 +46,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -65,7 +65,7 @@ LL | let x = &pin mut foo; // ok LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -87,7 +87,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -106,7 +106,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -125,7 +125,7 @@ LL | let x = &pin mut foo; // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -144,7 +144,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -163,7 +163,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -185,7 +185,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -204,7 +204,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -223,7 +223,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr index 523191655813b..bf9921343ee7d 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -33,7 +33,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -55,7 +55,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -77,7 +77,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr index cf7d50091ba45..3f46602098850 100644 --- a/tests/ui/pin-macro/pin_move.stderr +++ b/tests/ui/pin-macro/pin_move.stderr @@ -8,7 +8,7 @@ LL | pin!(pointee); LL | let _moved = pointee; | ^^^^^^^ value used here after move | -help: if `a::NotCopy` implemented `Clone`, you could clone the value +note: if `a::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:7:5 | LL | struct NotCopy(T); @@ -23,7 +23,7 @@ error[E0507]: cannot move out of a mutable reference LL | pin!(*&mut pointee); | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy`, which does not implement the `Copy` trait | -help: if `b::NotCopy` implemented `Clone`, you could clone the value +note: if `b::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:16:5 | LL | struct NotCopy(T); diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr index 5e447a57bfee0..62f24324fcc17 100644 --- a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr @@ -7,7 +7,7 @@ LL | (b,) = *tuple; | data moved here | move occurs because the place has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/non_copy_move_out_of_tuple.rs:3:1 | LL | struct NonCopy; diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr index cd13592d652e8..f78d3cf678629 100644 --- a/tests/ui/suggestions/option-content-move3.stderr +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -10,7 +10,7 @@ LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait | = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once -help: if `NotCopyable` implemented `Clone`, you could clone the value +note: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; @@ -43,7 +43,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | fn func H, H: FnMut()>(_: F) {} | ^^^^^^^^^^^^ -help: if `NotCopyable` implemented `Clone`, you could clone the value +note: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr index 5974441dd807d..461ee407e2ddb 100644 --- a/tests/ui/union/union-borrow-move-parent-sibling.stderr +++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr @@ -59,7 +59,7 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, Moc LL | let a = (u.x.0).0; | ^^^^^^^^^ move occurs because value has type `MockVec`, which does not implement the `Copy` trait | -help: if `MockVec` implemented `Clone`, you could clone the value +note: if `MockVec` implemented `Clone`, you could clone the value --> $DIR/union-borrow-move-parent-sibling.rs:25:1 | LL | struct MockVec { diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr index 6266bb4770e0e..d520fb00ea9d5 100644 --- a/tests/ui/union/union-move.stderr +++ b/tests/ui/union/union-move.stderr @@ -16,7 +16,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -help: if `U1` implemented `Clone`, you could clone the value +note: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { @@ -43,7 +43,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -help: if `U1` implemented `Clone`, you could clone the value +note: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr index 2a33a88bdd56a..21d8de6ae8815 100644 --- a/tests/ui/variance/variance-issue-20533.stderr +++ b/tests/ui/variance/variance-issue-20533.stderr @@ -10,7 +10,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -31,7 +31,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -52,7 +52,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -73,7 +73,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); From c95210f013cd0e607b4932cc841f90096037f191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Feb 2026 18:30:08 +0000 Subject: [PATCH 35/47] Do not suggest manual `impl Copy` --- .../src/error_reporting/traits/suggestions.rs | 2 +- tests/ui/associated-types/issue-38821.stderr | 1 - tests/ui/consts/const-blocks/trait-error.stderr | 1 - tests/ui/derives/deriving-copyclone.stderr | 2 -- tests/ui/generic-associated-types/impl_bounds.stderr | 2 -- 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 1880465eff54c..764790a75bb44 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3629,7 +3629,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.span_note(spans, msg); - if derived { + if derived && trait_name != "Copy" { err.help(format!( "consider manually implementing `{trait_name}` to avoid undesired \ bounds", diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index fae388c98d36f..07b146f8bfca4 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -159,7 +159,6 @@ LL | pub enum ColumnInsertValue where ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound - = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 853e10e0b35a3..308d71f0f4bd6 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -11,7 +11,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo(T); | ^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block | diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 40f96919121f4..20a73ffdcfbfe 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -13,7 +13,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { | ^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | @@ -65,7 +64,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { | ^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 63c4ba9008291..65e1dff479e54 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -35,7 +35,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 | @@ -62,7 +61,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 | From 675656188786ebb1444b5ea7baece40d8afa51ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Feb 2026 18:31:21 +0000 Subject: [PATCH 36/47] fix test after rebase --- .../derive-clone-already-present-issue-146515.rs | 5 ++--- .../derive-clone-already-present-issue-146515.stderr | 11 ++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs b/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs index 083d73711a517..78b4c017251ef 100644 --- a/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs +++ b/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs @@ -2,8 +2,8 @@ use std::rc::Rc; -#[derive(Clone)] -struct ContainsRc { +#[derive(Clone)] //~ NOTE in this expansion +struct ContainsRc { //~ NOTE derive introduces an implicit `T: Clone` bound value: Rc, } @@ -14,7 +14,6 @@ fn clone_me(x: &ContainsRc) -> ContainsRc { //~| NOTE expected `ContainsRc`, found `&ContainsRc` //~| NOTE expected struct `ContainsRc<_>` //~| NOTE `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead - //~| NOTE the trait `Clone` must be implemented } fn main() {} diff --git a/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr b/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr index 516ef38f668dc..6ecf4e7ca9439 100644 --- a/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr +++ b/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr @@ -14,9 +14,14 @@ note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned | LL | x.clone() | ^ - = help: `Clone` is not implemented because the trait bound `T: Clone` is not satisfied -note: the trait `Clone` must be implemented - --> $SRC_DIR/core/src/clone.rs:LL:COL +help: `Clone` is not implemented because a trait bound is not satisfied + --> $DIR/derive-clone-already-present-issue-146515.rs:6:19 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRc { + | ^ derive introduces an implicit `T: Clone` bound + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error: aborting due to 1 previous error From b5d9b7f6837e50d8984275f11704d8c7f8493923 Mon Sep 17 00:00:00 2001 From: usamoi Date: Sun, 1 Feb 2026 22:34:46 +0800 Subject: [PATCH 37/47] escape symbol names in global asm --- compiler/rustc_codegen_llvm/src/asm.rs | 45 ++++++++++++++++++++++-- tests/ui/asm/x86_64/global_asm_escape.rs | 17 +++++++++ tests/ui/asm/x86_64/naked_asm_escape.rs | 32 +++++++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 tests/ui/asm/x86_64/global_asm_escape.rs create mode 100644 tests/ui/asm/x86_64/naked_asm_escape.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 7f02518d6c0de..fd25fba2daac7 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -399,7 +399,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { for piece in template { match *piece { InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s), - InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { match operands[operand_idx] { GlobalAsmOperandRef::Const { ref string } => { // Const operands get injected directly into the @@ -414,7 +414,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); + template_str.push_str(&escape_symbol_name(self, symbol, span)); } GlobalAsmOperandRef::SymStatic { def_id } => { let llval = self @@ -428,7 +428,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); + template_str.push_str(&escape_symbol_name(self, symbol, span)); } } } @@ -1390,3 +1390,42 @@ fn llvm_fixup_output_type<'ll, 'tcx>( _ => layout.llvm_type(cx), } } + +fn escape_symbol_name<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, symbol: String, span: Span) -> String { + use rustc_target::spec::{Arch, BinaryFormat}; + if !symbol.is_empty() + && symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.')) + { + return symbol; + } + if cx.tcx.sess.target.binary_format == BinaryFormat::Xcoff { + cx.tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the binary format {}", + cx.tcx.sess.target.binary_format + ), + ); + } + if cx.tcx.sess.target.arch == Arch::Nvptx64 { + cx.tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the architecture {}", + cx.tcx.sess.target.arch + ), + ); + } + let mut escaped_symbol = String::new(); + escaped_symbol.push('\"'); + for c in symbol.chars() { + match c { + '\n' => escaped_symbol.push_str("\\\n"), + '"' => escaped_symbol.push_str("\\\""), + '\\' => escaped_symbol.push_str("\\\\"), + c => escaped_symbol.push(c), + } + } + escaped_symbol.push('\"'); + escaped_symbol +} diff --git a/tests/ui/asm/x86_64/global_asm_escape.rs b/tests/ui/asm/x86_64/global_asm_escape.rs new file mode 100644 index 0000000000000..59214e958a85b --- /dev/null +++ b/tests/ui/asm/x86_64/global_asm_escape.rs @@ -0,0 +1,17 @@ +//@ run-pass +//@ only-x86_64-unknown-linux-gnu +//@ ignore-backends: gcc + +// https://github.com/rust-lang/rust/issues/151950 + +unsafe extern "C" { + #[link_name = "exit@GLIBC_2.2.5"] + safe fn exit(status: i32) -> !; + safe fn my_exit(status: i32) -> !; +} + +core::arch::global_asm!(".global my_exit", "my_exit:", "jmp {}", sym exit); + +fn main() { + my_exit(0); +} diff --git a/tests/ui/asm/x86_64/naked_asm_escape.rs b/tests/ui/asm/x86_64/naked_asm_escape.rs new file mode 100644 index 0000000000000..57962993ef91f --- /dev/null +++ b/tests/ui/asm/x86_64/naked_asm_escape.rs @@ -0,0 +1,32 @@ +//@ build-fail +//@ only-x86_64-unknown-linux-gnu +//@ dont-check-compiler-stderr +//@ dont-check-compiler-stdout +//@ ignore-backends: gcc + +// https://github.com/rust-lang/rust/issues/151950 + +unsafe extern "C" { + #[link_name = "memset]; mov eax, 1; #"] + unsafe fn inject(); +} + +#[unsafe(export_name = "memset]; mov eax, 1; #")] +extern "C" fn inject_() {} + +#[unsafe(naked)] +extern "C" fn print_0() -> usize { + core::arch::naked_asm!("lea rax, [{}]", "ret", sym inject) +} + +#[unsafe(naked)] +extern "C" fn print_1() -> usize { + core::arch::naked_asm!("lea rax, [{}]", "ret", sym inject_) +} + +fn main() { + dbg!(print_0()); + dbg!(print_1()); +} + +//~? ERROR linking From 821f139a2903af53734b8359145edb426bc3f4a9 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 2 Feb 2026 10:51:20 +0100 Subject: [PATCH 38/47] Revert "Revert "Use LLVM intrinsics for `madd` intrinsics"" --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 36 +++++------ .../crates/core_arch/src/x86/avx512bw.rs | 64 +++++++++---------- .../stdarch/crates/core_arch/src/x86/sse2.rs | 26 +++++--- 3 files changed, 63 insertions(+), 63 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index e9463d4331807..83aef753c9d93 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -1841,14 +1841,20 @@ pub const fn _mm256_inserti128_si256(a: __m256i, b: __m128i) -> #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpmaddwd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_madd_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { - let r: i32x16 = simd_mul(simd_cast(a.as_i16x16()), simd_cast(b.as_i16x16())); - let even: i32x8 = simd_shuffle!(r, r, [0, 2, 4, 6, 8, 10, 12, 14]); - let odd: i32x8 = simd_shuffle!(r, r, [1, 3, 5, 7, 9, 11, 13, 15]); - simd_add(even, odd).as_m256i() - } +pub fn _mm256_madd_epi16(a: __m256i, b: __m256i) -> __m256i { + // It's a trick used in the Adler-32 algorithm to perform a widening addition. + // + // ```rust + // #[target_feature(enable = "avx2")] + // unsafe fn widening_add(mad: __m256i) -> __m256i { + // _mm256_madd_epi16(mad, _mm256_set1_epi16(1)) + // } + // ``` + // + // If we implement this using generic vector intrinsics, the optimizer + // will eliminate this pattern, and `vpmaddwd` will no longer be emitted. + // For this reason, we use x86 intrinsics. + unsafe { transmute(pmaddwd(a.as_i16x16(), b.as_i16x16())) } } /// Vertically multiplies each unsigned 8-bit integer from `a` with the @@ -3813,6 +3819,8 @@ pub const fn _mm256_extract_epi16(a: __m256i) -> i32 { #[allow(improper_ctypes)] unsafe extern "C" { + #[link_name = "llvm.x86.avx2.pmadd.wd"] + fn pmaddwd(a: i16x16, b: i16x16) -> i32x8; #[link_name = "llvm.x86.avx2.pmadd.ub.sw"] fn pmaddubsw(a: u8x32, b: i8x32) -> i16x16; #[link_name = "llvm.x86.avx2.mpsadbw"] @@ -4661,7 +4669,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_madd_epi16() { + fn test_mm256_madd_epi16() { let a = _mm256_set1_epi16(2); let b = _mm256_set1_epi16(4); let r = _mm256_madd_epi16(a, b); @@ -4669,16 +4677,6 @@ mod tests { assert_eq_m256i(r, e); } - #[target_feature(enable = "avx2")] - #[cfg_attr(test, assert_instr(vpmaddwd))] - unsafe fn test_mm256_madd_epi16_mul_one(mad: __m256i) -> __m256i { - // This is a trick used in the adler32 algorithm to get a widening addition. The - // multiplication by 1 is trivial, but must not be optimized out because then the vpmaddwd - // instruction is no longer selected. The assert_instr verifies that this is the case. - let one_v = _mm256_set1_epi16(1); - _mm256_madd_epi16(mad, one_v) - } - #[simd_test(enable = "avx2")] const fn test_mm256_inserti128_si256() { let a = _mm256_setr_epi64x(1, 2, 3, 4); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index e2d12cd97264b..8e074fdcfa486 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -6321,22 +6321,20 @@ pub const unsafe fn _mm_mask_storeu_epi8(mem_addr: *mut i8, mask: __mmask16, a: #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { - unsafe { - let r: i32x32 = simd_mul(simd_cast(a.as_i16x32()), simd_cast(b.as_i16x32())); - let even: i32x16 = simd_shuffle!( - r, - r, - [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30] - ); - let odd: i32x16 = simd_shuffle!( - r, - r, - [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31] - ); - simd_add(even, odd).as_m512i() - } +pub fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { + // It's a trick used in the Adler-32 algorithm to perform a widening addition. + // + // ```rust + // #[target_feature(enable = "avx512bw")] + // unsafe fn widening_add(mad: __m512i) -> __m512i { + // _mm512_madd_epi16(mad, _mm512_set1_epi16(1)) + // } + // ``` + // + // If we implement this using generic vector intrinsics, the optimizer + // will eliminate this pattern, and `vpmaddwd` will no longer be emitted. + // For this reason, we use x86 intrinsics. + unsafe { transmute(vpmaddwd(a.as_i16x32(), b.as_i16x32())) } } /// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -6346,8 +6344,7 @@ pub const fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { unsafe { let madd = _mm512_madd_epi16(a, b).as_i32x16(); transmute(simd_select_bitmask(k, madd, src.as_i32x16())) @@ -6361,8 +6358,7 @@ pub const fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: _ #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { unsafe { let madd = _mm512_madd_epi16(a, b).as_i32x16(); transmute(simd_select_bitmask(k, madd, i32x16::ZERO)) @@ -6376,8 +6372,7 @@ pub const fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { unsafe { let madd = _mm256_madd_epi16(a, b).as_i32x8(); transmute(simd_select_bitmask(k, madd, src.as_i32x8())) @@ -6391,8 +6386,7 @@ pub const fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { unsafe { let madd = _mm256_madd_epi16(a, b).as_i32x8(); transmute(simd_select_bitmask(k, madd, i32x8::ZERO)) @@ -6406,8 +6400,7 @@ pub const fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let madd = _mm_madd_epi16(a, b).as_i32x4(); transmute(simd_select_bitmask(k, madd, src.as_i32x4())) @@ -6421,8 +6414,7 @@ pub const fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m12 #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let madd = _mm_madd_epi16(a, b).as_i32x4(); transmute(simd_select_bitmask(k, madd, i32x4::ZERO)) @@ -12582,6 +12574,8 @@ unsafe extern "C" { #[link_name = "llvm.x86.avx512.pmul.hr.sw.512"] fn vpmulhrsw(a: i16x32, b: i16x32) -> i16x32; + #[link_name = "llvm.x86.avx512.pmaddw.d.512"] + fn vpmaddwd(a: i16x32, b: i16x32) -> i32x16; #[link_name = "llvm.x86.avx512.pmaddubs.w.512"] fn vpmaddubsw(a: u8x64, b: i8x64) -> i16x32; @@ -17506,7 +17500,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_madd_epi16() { + fn test_mm512_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_madd_epi16(a, b); @@ -17515,7 +17509,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_madd_epi16() { + fn test_mm512_mask_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_mask_madd_epi16(a, 0, a, b); @@ -17543,7 +17537,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_madd_epi16() { + fn test_mm512_maskz_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_maskz_madd_epi16(0, a, b); @@ -17554,7 +17548,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_madd_epi16() { + fn test_mm256_mask_madd_epi16() { let a = _mm256_set1_epi16(1); let b = _mm256_set1_epi16(1); let r = _mm256_mask_madd_epi16(a, 0, a, b); @@ -17574,7 +17568,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_maskz_madd_epi16() { + fn test_mm256_maskz_madd_epi16() { let a = _mm256_set1_epi16(1); let b = _mm256_set1_epi16(1); let r = _mm256_maskz_madd_epi16(0, a, b); @@ -17585,7 +17579,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_madd_epi16() { + fn test_mm_mask_madd_epi16() { let a = _mm_set1_epi16(1); let b = _mm_set1_epi16(1); let r = _mm_mask_madd_epi16(a, 0, a, b); @@ -17596,7 +17590,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_madd_epi16() { + fn test_mm_maskz_madd_epi16() { let a = _mm_set1_epi16(1); let b = _mm_set1_epi16(1); let r = _mm_maskz_madd_epi16(0, a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs index ecd478511b064..f339a003df4d1 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs @@ -210,14 +210,20 @@ pub const fn _mm_avg_epu16(a: __m128i, b: __m128i) -> __m128i { #[target_feature(enable = "sse2")] #[cfg_attr(test, assert_instr(pmaddwd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { - let r: i32x8 = simd_mul(simd_cast(a.as_i16x8()), simd_cast(b.as_i16x8())); - let even: i32x4 = simd_shuffle!(r, r, [0, 2, 4, 6]); - let odd: i32x4 = simd_shuffle!(r, r, [1, 3, 5, 7]); - simd_add(even, odd).as_m128i() - } +pub fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i { + // It's a trick used in the Adler-32 algorithm to perform a widening addition. + // + // ```rust + // #[target_feature(enable = "sse2")] + // unsafe fn widening_add(mad: __m128i) -> __m128i { + // _mm_madd_epi16(mad, _mm_set1_epi16(1)) + // } + // ``` + // + // If we implement this using generic vector intrinsics, the optimizer + // will eliminate this pattern, and `pmaddwd` will no longer be emitted. + // For this reason, we use x86 intrinsics. + unsafe { transmute(pmaddwd(a.as_i16x8(), b.as_i16x8())) } } /// Compares packed 16-bit integers in `a` and `b`, and returns the packed @@ -3187,6 +3193,8 @@ unsafe extern "C" { fn lfence(); #[link_name = "llvm.x86.sse2.mfence"] fn mfence(); + #[link_name = "llvm.x86.sse2.pmadd.wd"] + fn pmaddwd(a: i16x8, b: i16x8) -> i32x4; #[link_name = "llvm.x86.sse2.psad.bw"] fn psadbw(a: u8x16, b: u8x16) -> u64x2; #[link_name = "llvm.x86.sse2.psll.w"] @@ -3465,7 +3473,7 @@ mod tests { } #[simd_test(enable = "sse2")] - const fn test_mm_madd_epi16() { + fn test_mm_madd_epi16() { let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); let b = _mm_setr_epi16(9, 10, 11, 12, 13, 14, 15, 16); let r = _mm_madd_epi16(a, b); From 54641efc6839b75405d19dbe20150985df0fbb8d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 2 Feb 2026 17:01:10 +0100 Subject: [PATCH 39/47] add `vpmaddwd` tests back in --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 83aef753c9d93..04a88e461f752 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -4677,6 +4677,26 @@ mod tests { assert_eq_m256i(r, e); } + #[target_feature(enable = "avx2")] + #[cfg_attr(test, assert_instr(vpmaddwd))] + unsafe fn test_mm256_madd_epi16_mul_one(v: __m256i) -> __m256i { + // This is a trick used in the adler32 algorithm to get a widening addition. The + // multiplication by 1 is trivial, but must not be optimized out because then the vpmaddwd + // instruction is no longer selected. The assert_instr verifies that this is the case. + let one_v = _mm256_set1_epi16(1); + _mm256_madd_epi16(v, one_v) + } + + #[target_feature(enable = "avx2")] + #[cfg_attr(test, assert_instr(vpmaddwd))] + unsafe fn test_mm256_madd_epi16_shl(v: __m256i) -> __m256i { + // This is a trick used in the base64 algorithm to get a widening addition. Instead of a + // multiplication, a vector shl is used. In LLVM 22 that breaks the pattern recognition + // for the automatic optimization to vpmaddwd. + let shift_value = _mm256_set1_epi32(12i32); + _mm256_madd_epi16(v, shift_value) + } + #[simd_test(enable = "avx2")] const fn test_mm256_inserti128_si256() { let a = _mm256_setr_epi64x(1, 2, 3, 4); From 13141af9492b3cc91b7afeb32ee9c0fb4b24ca64 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 4 Feb 2026 19:26:13 +0000 Subject: [PATCH 40/47] Consolidate type const checks on `tcx.is_type_const` --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/check/compare_impl_item.rs | 11 +++-------- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../rustc_hir_analysis/src/hir_ty_lowering/bounds.rs | 8 ++------ .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 7 +++---- compiler/rustc_hir_analysis/src/lib.rs | 7 ++----- compiler/rustc_middle/src/ty/context.rs | 9 +++++++-- .../src/traits/dyn_compatibility.rs | 5 ++--- 8 files changed, 21 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c00122bce559a..e0bfae9617ff1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -923,7 +923,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ); check_where_clauses(wfcx, def_id); - if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if tcx.is_type_const(def_id.into()) { wfcheck::check_type_const(wfcx, def_id, ty, true)?; } Ok(()) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 9e07d5260d20e..f418dec940bbc 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -6,10 +6,9 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; -use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit}; +use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -2051,12 +2050,8 @@ fn compare_type_const<'tcx>( impl_const_item: ty::AssocItem, trait_const_item: ty::AssocItem, ) -> Result<(), ErrorGuaranteed> { - let impl_is_type_const = - find_attr!(tcx.get_all_attrs(impl_const_item.def_id), AttributeKind::TypeConst(_)); - let trait_type_const_span = find_attr!( - tcx.get_all_attrs(trait_const_item.def_id), - AttributeKind::TypeConst(sp) => *sp - ); + let impl_is_type_const = tcx.is_type_const(impl_const_item.def_id); + let trait_type_const_span = tcx.type_const_span(trait_const_item.def_id); if let Some(trait_type_const_span) = trait_type_const_span && !impl_is_type_const diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8b50eceb26e49..acead42c9a0e8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -953,7 +953,7 @@ pub(crate) fn check_associated_item( wfcx.register_wf_obligation(span, loc, ty.into()); let has_value = item.defaultness(tcx).has_value(); - if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if tcx.is_type_const(def_id.into()) { check_type_const(wfcx, def_id, ty, has_value)?; } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 3515ce4ea9399..a1c3af5f999d4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -4,10 +4,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::PolyTraitRef; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; -use rustc_hir::{PolyTraitRef, find_attr}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -603,10 +602,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); if let ty::AssocTag::Const = assoc_tag - && !find_attr!( - self.tcx().get_all_attrs(assoc_item.def_id), - AttributeKind::TypeConst(_) - ) + && !self.tcx().is_type_const(assoc_item.def_id) { if tcx.features().min_generic_const_args() { let mut err = self.dcx().struct_span_err( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 9f84f652698b4..d4b9d2e359d59 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -28,10 +28,9 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err, }; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId, find_attr}; +use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::DynCompatibilityViolation; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -1423,7 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { LowerTypeRelativePathMode::Const, )? { TypeRelativePath::AssocItem(def_id, args) => { - if !find_attr!(self.tcx().get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if !self.tcx().is_type_const(def_id) { let mut err = self.dcx().struct_span_err( span, "use of trait associated const without `#[type_const]`", @@ -1896,7 +1895,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::AssocTag::Const, ) { Ok((item_def_id, item_args)) => { - if !find_attr!(self.tcx().get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) { + if !self.tcx().is_type_const(item_def_id) { let mut err = self.dcx().struct_span_err( span, "use of `const` in the type system without `#[type_const]`", diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f7a1434359593..01f57f3a56df6 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -85,12 +85,9 @@ mod variance; pub use errors::NoVariantNamed; use rustc_abi::{CVariadicStatus, ExternAbi}; -use rustc_hir::attrs::AttributeKind; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::lints::DelayedLint; -use rustc_hir::{ - find_attr, {self as hir}, -}; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{Const, Ty, TyCtxt}; @@ -238,7 +235,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() - && !find_attr!(tcx.get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) => + && !tcx.is_type_const(item_def_id.into()) => { // FIXME(generic_const_items): Passing empty instead of identity args is fishy but // seems to be fine for now. Revisit this! diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 41e1388e31464..348e5ccf6217f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1886,10 +1886,15 @@ impl<'tcx> TyCtxt<'tcx> { self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace) } + pub fn type_const_span(self, def_id: DefId) -> Option { + matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst) + .then(|| find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(sp) => *sp)) + .flatten() + } + /// Check if the given `def_id` is a const with the `#[type_const]` attribute. pub fn is_type_const(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst) - && find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(_)) + self.type_const_span(def_id).is_some() } /// Returns the movability of the coroutine of `def_id`, or panics diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 9371b55b63633..512973e452870 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -7,10 +7,9 @@ use std::ops::ControlFlow; use rustc_errors::FatalError; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem, find_attr}; +use rustc_hir::{self as hir, LangItem}; use rustc_middle::query::Providers; use rustc_middle::ty::{ self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -333,7 +332,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( if tcx.features().min_generic_const_args() { if !tcx.generics_of(item.def_id).is_own_empty() { errors.push(AssocConstViolation::Generic); - } else if !find_attr!(tcx.get_all_attrs(item.def_id), AttributeKind::TypeConst(_)) { + } else if !tcx.is_type_const(item.def_id) { errors.push(AssocConstViolation::NonType); } From 8c404a764919b9155c0ac68978185d7db80cc351 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Thu, 5 Feb 2026 04:37:12 +0000 Subject: [PATCH 41/47] Prepare for merging from rust-lang/rust This updates the rust-version file to db3e99bbab28c6ca778b13222becdea54533d908. --- library/stdarch/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index ccc0b55d4dc55..aa3876b14a221 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -873d4682c7d285540b8f28bfe637006cef8918a6 +db3e99bbab28c6ca778b13222becdea54533d908 From edeb02f3828aedb3dac3c32553842e6a4d01d422 Mon Sep 17 00:00:00 2001 From: "Eddy (Eduard) Stefes" Date: Thu, 5 Feb 2026 13:36:18 +0100 Subject: [PATCH 42/47] disable s390x vector intrinsics if softfloat is enabled we will add an explicit incompatibility of softfloat and vector feature in rutsc s390x-unknown-none-softfloat target specification. Therefore we need to disable vector intrinsics here to be able to compile core for this target. --- library/stdarch/crates/core_arch/src/s390x/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/s390x/mod.rs b/library/stdarch/crates/core_arch/src/s390x/mod.rs index 7d3b3f2d99aae..5b85020072d87 100644 --- a/library/stdarch/crates/core_arch/src/s390x/mod.rs +++ b/library/stdarch/crates/core_arch/src/s390x/mod.rs @@ -2,6 +2,11 @@ pub(crate) mod macros; +/// the float and vector registers overlap therefore we cannot use any vector +/// extensions if softfloat is enabled. + +#[cfg(not(target_abi = "softfloat"))] mod vector; +#[cfg(not(target_abi = "softfloat"))] #[unstable(feature = "stdarch_s390x", issue = "130869")] pub use self::vector::*; From 911203936b799451029b91526eba6b7dbf842559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 14:34:01 +0100 Subject: [PATCH 43/47] Port rustc_effective_visibility to the new attribute parser --- .../src/attributes/rustc_internal.rs | 39 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- 6 files changed, 46 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 348882dc59fcd..bde4904e9655d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -721,3 +721,42 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { Some(ident) } } + +pub(crate) struct RustcEffectiveVisibilityParser; + +impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { + const PATH: &'static [Symbol] = &[sym::rustc_effective_visibility]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Use), + Allow(Target::Static), + Allow(Target::Const), + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Mod), + Allow(Target::ForeignMod), + Allow(Target::TyAlias), + Allow(Target::Enum), + Allow(Target::Variant), + Allow(Target::Struct), + Allow(Target::Field), + Allow(Target::Union), + Allow(Target::Trait), + Allow(Target::TraitAlias), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::AssocConst), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::AssocTy), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::ForeignTy), + Allow(Target::MacroDef), + Allow(Target::PatField), + Allow(Target::Crate), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5abf299ec618c..eb9ae158abb79 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -258,6 +258,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index a444b5e4badf5..e4d93b2e0c29f 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1094,6 +1094,9 @@ pub enum AttributeKind { /// Represents `#[rustc_dyn_incompatible_trait]`. RustcDynIncompatibleTrait(Span), + /// Represents `#[rustc_effective_visibility]`. + RustcEffectiveVisibility, + /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index b6249e1e2ec2c..2a214fe58220b 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -112,6 +112,7 @@ impl AttributeKind { RustcDumpUserArgs => No, RustcDumpVtable(..) => No, RustcDynIncompatibleTrait(..) => No, + RustcEffectiveVisibility => Yes, RustcHasIncoherentInherentImpls => Yes, RustcHiddenTypeOfOpaques => No, RustcIfThisChanged(..) => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0d64e30d9c79e..acc7abe191675 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -307,6 +307,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDumpUserArgs | AttributeKind::RustcDumpVtable(..) | AttributeKind::RustcDynIncompatibleTrait(..) + | AttributeKind::RustcEffectiveVisibility | AttributeKind::RustcHasIncoherentInherentImpls | AttributeKind::RustcHiddenTypeOfOpaques | AttributeKind::RustcIfThisChanged(..) @@ -401,7 +402,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_regions | sym::rustc_strict_coherence | sym::rustc_mir - | sym::rustc_effective_visibility | sym::rustc_outlives | sym::rustc_symbol_name | sym::rustc_evaluate_where_clauses diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4a88ea0cc4450..f69f8777ef425 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -876,7 +876,7 @@ pub struct TestReachabilityVisitor<'a, 'tcx> { impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> { fn effective_visibility_diagnostic(&self, def_id: LocalDefId) { - if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) { + if find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::RustcEffectiveVisibility) { let mut error_msg = String::new(); let span = self.tcx.def_span(def_id.to_def_id()); if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) { From dd61998e74e1cc4bcec9b6f92026d218b34d262e Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 16:00:30 +0100 Subject: [PATCH 44/47] Convert to inline diagnostics in `rustc_borrowck` --- Cargo.lock | 2 - compiler/rustc_borrowck/Cargo.toml | 1 - compiler/rustc_borrowck/messages.ftl | 296 ------------------ .../rustc_borrowck/src/diagnostics/mod.rs | 22 +- .../src/diagnostics/region_errors.rs | 28 +- compiler/rustc_borrowck/src/lib.rs | 2 - .../rustc_borrowck/src/session_diagnostics.rs | 275 +++++++++++----- compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - 9 files changed, 233 insertions(+), 395 deletions(-) delete mode 100644 compiler/rustc_borrowck/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 23abc6626aaba..4d67ea5b8180a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3571,7 +3571,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_index", @@ -3771,7 +3770,6 @@ dependencies = [ "rustc_abi", "rustc_ast", "rustc_ast_pretty", - "rustc_borrowck", "rustc_codegen_ssa", "rustc_const_eval", "rustc_data_structures", diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 9e7d55180a233..55a09dbf1d724 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -11,7 +11,6 @@ polonius-engine = "0.13.0" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl deleted file mode 100644 index f59e106c7ac3c..0000000000000 --- a/compiler/rustc_borrowck/messages.ftl +++ /dev/null @@ -1,296 +0,0 @@ -borrowck_assign_due_to_use_closure = - assignment occurs due to use in closure - -borrowck_assign_due_to_use_coroutine = - assign occurs due to use in coroutine - -borrowck_assign_part_due_to_use_closure = - assignment to part occurs due to use in closure - -borrowck_assign_part_due_to_use_coroutine = - assign to part occurs due to use in coroutine - -borrowck_borrow_due_to_use_closure = - borrow occurs due to use in closure - -borrowck_borrow_due_to_use_coroutine = - borrow occurs due to use in coroutine - -borrowck_calling_operator_moves = - calling this operator moves the value - -borrowck_calling_operator_moves_lhs = - calling this operator moves the left-hand side - -borrowck_cannot_move_when_borrowed = - cannot move out of {$place -> - [value] value - *[other] {$place} - } because it is borrowed - .label = borrow of {$borrow_place -> - [value] value - *[other] {$borrow_place} - } occurs here - .move_label = move out of {$value_place -> - [value] value - *[other] {$value_place} - } occurs here - -borrowck_capture_immute = - capture is immutable because of use here - -borrowck_capture_move = - capture is moved because of use here - -borrowck_capture_mut = - capture is mutable because of use here - -borrowck_closure_inferred_mut = inferred to be a `FnMut` closure - -borrowck_closure_invoked_twice = - closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment - -borrowck_closure_moved_twice = - closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment - -borrowck_consider_borrow_type_contents = - help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents - -borrowck_could_not_normalize = - could not normalize `{$value}` - -borrowck_could_not_prove = - could not prove `{$predicate}` - -borrowck_dereference_suggestion = - dereference the return value - -borrowck_func_take_self_moved_place = - `{$func}` takes ownership of the receiver `self`, which moves {$place_name} - -borrowck_generic_does_not_live_long_enough = - `{$kind}` does not live long enough - -borrowck_higher_ranked_lifetime_error = - higher-ranked lifetime error - -borrowck_higher_ranked_subtype_error = - higher-ranked subtype error - -borrowck_implicit_static = - this has an implicit `'static` lifetime requirement - -borrowck_implicit_static_introduced = - calling this method introduces the `impl`'s `'static` requirement - -borrowck_implicit_static_relax = - consider relaxing the implicit `'static` requirement - -borrowck_lifetime_constraints_error = - lifetime may not live long enough - -borrowck_limitations_implies_static = - due to a current limitation of the type system, this implies a `'static` lifetime - -borrowck_move_closure_suggestion = - consider adding 'move' keyword before the nested closure - -borrowck_move_out_place_here = - {$place} is moved here - -borrowck_move_unsized = - cannot move a value of type `{$ty}` - .label = the size of `{$ty}` cannot be statically determined - -borrowck_moved_a_fn_once_in_call = - this value implements `FnOnce`, which causes it to be moved when called - -borrowck_moved_a_fn_once_in_call_call = - `FnOnce` closures can only be called once - -borrowck_moved_a_fn_once_in_call_def = - `{$ty}` is made to be an `FnOnce` closure here - -borrowck_moved_due_to_await = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this {$is_loop_message -> - [true] await, in previous iteration of loop - *[false] await - } - -borrowck_moved_due_to_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this {$is_loop_message -> - [true] call, in previous iteration of loop - *[false] call - } - -borrowck_moved_due_to_implicit_into_iter_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this implicit call to {$is_loop_message -> - [true] `.into_iter()`, in previous iteration of loop - *[false] `.into_iter()` - } - -borrowck_moved_due_to_method_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this method {$is_loop_message -> - [true] call, in previous iteration of loop - *[false] call - } - -borrowck_moved_due_to_usage_in_operator = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to usage in {$is_loop_message -> - [true] operator, in previous iteration of loop - *[false] operator - } - -borrowck_opaque_type_lifetime_mismatch = - opaque type used twice with different lifetimes - .label = lifetime `{$arg}` used here - .prev_lifetime_label = lifetime `{$prev}` previously used here - .note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - -borrowck_partial_var_move_by_use_in_closure = - variable {$is_partial -> - [true] partially moved - *[false] moved - } due to use in closure - -borrowck_partial_var_move_by_use_in_coroutine = - variable {$is_partial -> - [true] partially moved - *[false] moved - } due to use in coroutine - -borrowck_restrict_to_static = - consider restricting the type parameter to the `'static` lifetime - -borrowck_returned_async_block_escaped = - returns an `async` block that contains a reference to a captured variable, which then escapes the closure body - -borrowck_returned_closure_escaped = - returns a closure that contains a reference to a captured variable, which then escapes the closure body - -borrowck_returned_lifetime_short = - {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}` - -borrowck_returned_lifetime_wrong = - {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}` - -borrowck_returned_ref_escaped = - returns a reference to a captured variable which escapes the closure body - -borrowck_simd_intrinsic_arg_const = - {$arg -> - [1] 1st - [2] 2nd - [3] 3rd - *[other] {$arg}th - } argument of `{$intrinsic}` is required to be a `const` item - -borrowck_suggest_create_fresh_reborrow = - consider reborrowing the `Pin` instead of moving it - -borrowck_suggest_iterate_over_slice = - consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop - -borrowck_tail_expr_drop_order = relative drop order changing in Rust 2024 - .label = this temporary value will be dropped at the end of the block - .note = consider using a `let` binding to ensure the value will live long enough - -borrowck_ty_no_impl_copy = - {$is_partial_move -> - [true] partial move - *[false] move - } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait - -borrowck_use_due_to_use_closure = - use occurs due to use in closure - -borrowck_use_due_to_use_coroutine = - use occurs due to use in coroutine - -borrowck_used_impl_require_static = - the used `impl` has a `'static` requirement - -borrowck_value_capture_here = - value captured {$is_within -> - [true] here by coroutine - *[false] here - } - -borrowck_value_moved_here = - value {$is_partial -> - [true] partially moved - *[false] moved - } {$is_move_msg -> - [true] into closure here - *[false] here - }{$is_loop_message -> - [true] , in previous iteration of loop - *[false] {""} - } - -borrowck_var_borrow_by_use_in_closure = - borrow occurs due to use in closure - -borrowck_var_borrow_by_use_in_coroutine = - borrow occurs due to use in coroutine - -borrowck_var_borrow_by_use_place_in_closure = - {$is_single_var -> - *[true] borrow occurs - [false] borrows occur - } due to use of {$place} in closure - -borrowck_var_borrow_by_use_place_in_coroutine = - {$is_single_var -> - *[true] borrow occurs - [false] borrows occur - } due to use of {$place} in coroutine - -borrowck_var_cannot_escape_closure = - captured variable cannot escape `FnMut` closure body - .note = `FnMut` closures only have access to their captured variables while they are executing... - .cannot_escape = ...therefore, they cannot allow references to captured variables to escape - -borrowck_var_does_not_need_mut = - variable does not need to be mutable - .suggestion = remove this `mut` - -borrowck_var_first_borrow_by_use_place_in_closure = - first borrow occurs due to use of {$place} in closure - -borrowck_var_first_borrow_by_use_place_in_coroutine = - first borrow occurs due to use of {$place} in coroutine - -borrowck_var_here_captured = variable captured here - -borrowck_var_here_defined = variable defined here - -borrowck_var_move_by_use_in_closure = - move occurs due to use in closure - -borrowck_var_move_by_use_in_coroutine = - move occurs due to use in coroutine - -borrowck_var_mutable_borrow_by_use_place_in_closure = - mutable borrow occurs due to use of {$place} in closure - -borrowck_var_second_borrow_by_use_place_in_closure = - second borrow occurs due to use of {$place} in closure - -borrowck_var_second_borrow_by_use_place_in_coroutine = - second borrow occurs due to use of {$place} in coroutine diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c15e7041c94d3..04bacd049bc97 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -4,7 +4,9 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify}; +use rustc_errors::{ + Applicability, Diag, DiagMessage, EmissionGuarantee, MultiSpan, inline_fluent, listify, +}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{ self as hir, CoroutineKind, GenericBound, LangItem, WhereBoundPredicate, WherePredicateKind, @@ -35,7 +37,6 @@ use tracing::debug; use super::MirBorrowckCtxt; use super::borrow_set::BorrowData; use crate::constraints::OutlivesConstraint; -use crate::fluent_generated as fluent; use crate::nll::ConstraintDescription; use crate::session_diagnostics::{ CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, @@ -700,7 +701,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id) .is_some() { - diag.span_note(pred.span, fluent::borrowck_limitations_implies_static); + diag.span_note(pred.span, LIMITATION_NOTE); return; } for bound in bounds.iter() { @@ -711,7 +712,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id) .is_some() { - diag.span_note(bound.span, fluent::borrowck_limitations_implies_static); + diag.span_note(bound.span, LIMITATION_NOTE); return; } } @@ -1312,7 +1313,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut span: MultiSpan = spans.clone().into(); err.arg("ty", param_ty.to_string()); let msg = err.dcx.eagerly_translate_to_string( - fluent::borrowck_moved_a_fn_once_in_call_def, + inline_fluent!("`{$ty}` is made to be an `FnOnce` closure here"), err.args.iter(), ); err.remove_arg("ty"); @@ -1321,9 +1322,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } span.push_span_label( fn_call_span, - fluent::borrowck_moved_a_fn_once_in_call, + inline_fluent!("this value implements `FnOnce`, which causes it to be moved when called"), + ); + err.span_note( + span, + inline_fluent!("`FnOnce` closures can only be called once"), ); - err.span_note(span, fluent::borrowck_moved_a_fn_once_in_call_call); } else { err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); } @@ -1568,3 +1572,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.local_name(index).is_none_or(|name| name.as_str().starts_with('_')) } } + +const LIMITATION_NOTE: DiagMessage = inline_fluent!( + "due to a current limitation of the type system, this implies a `'static` lifetime" +); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 17f1988a17c40..ae389d1a6e10c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,7 +1,7 @@ //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, inline_fluent}; use rustc_hir as hir; use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; @@ -27,7 +27,7 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{Obligation, ObligationCtxt}; use tracing::{debug, instrument, trace}; -use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; +use super::{LIMITATION_NOTE, OutlivesSuggestionBuilder, RegionName, RegionNameSource}; use crate::nll::ConstraintDescription; use crate::region_infer::values::RegionElement; use crate::region_infer::{BlameConstraint, TypeTest}; @@ -36,7 +36,7 @@ use crate::session_diagnostics::{ LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, }; use crate::universal_regions::DefiningTy; -use crate::{MirBorrowckCtxt, borrowck_errors, fluent_generated as fluent}; +use crate::{MirBorrowckCtxt, borrowck_errors}; impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { @@ -265,7 +265,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }) = bound else { return; }; - diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static); + diag.span_note(*trait_span, LIMITATION_NOTE); let Some(generics_fn) = tcx.hir_get_generics(self.body.source.def_id().expect_local()) else { return; @@ -298,7 +298,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - fluent::borrowck_restrict_to_static, + inline_fluent!("consider restricting the type parameter to the `'static` lifetime"), suggestions, Applicability::MaybeIncorrect, ); @@ -966,12 +966,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { debug!("trait spans found: {:?}", traits); for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); - multi_span.push_span_label(*span, fluent::borrowck_implicit_static); - multi_span.push_span_label(ident.span, fluent::borrowck_implicit_static_introduced); + multi_span.push_span_label( + *span, + inline_fluent!("this has an implicit `'static` lifetime requirement"), + ); + multi_span.push_span_label( + ident.span, + inline_fluent!( + "calling this method introduces the `impl`'s `'static` requirement" + ), + ); err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), - fluent::borrowck_implicit_static_relax, + inline_fluent!("consider relaxing the implicit `'static` requirement"), " + '_", Applicability::MaybeIncorrect, ); @@ -1134,7 +1142,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if ocx.evaluate_obligations_error_on_ambiguity().is_empty() && count > 0 { diag.span_suggestion_verbose( tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(), - fluent::borrowck_dereference_suggestion, + inline_fluent!("dereference the return value"), "*".repeat(count), Applicability::MachineApplicable, ); @@ -1178,7 +1186,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(closure_span) = closure_span { diag.span_suggestion_verbose( closure_span, - fluent::borrowck_move_closure_suggestion, + inline_fluent!("consider adding 'move' keyword before the nested closure"), "move ", Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7c5cbc58e25c5..9186d82974d77 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -99,8 +99,6 @@ mod used_muts; /// A public API provided for the Rust compiler consumers. pub mod consumers; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - /// Associate some local constants with the `'tcx` lifetime struct TyCtxtConsts<'tcx>(PhantomData<&'tcx ()>); diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 5143b2fa20598..7bde534dafd20 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -7,16 +7,16 @@ use rustc_span::Span; use crate::diagnostics::RegionName; #[derive(Diagnostic)] -#[diag(borrowck_move_unsized, code = E0161)] +#[diag("cannot move a value of type `{$ty}`", code = E0161)] pub(crate) struct MoveUnsized<'tcx> { pub ty: Ty<'tcx>, #[primary_span] - #[label] + #[label("the size of `{$ty}` cannot be statically determined")] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_higher_ranked_lifetime_error)] +#[diag("higher-ranked lifetime error")] pub(crate) struct HigherRankedLifetimeError { #[subdiagnostic] pub cause: Option, @@ -26,21 +26,21 @@ pub(crate) struct HigherRankedLifetimeError { #[derive(Subdiagnostic)] pub(crate) enum HigherRankedErrorCause { - #[note(borrowck_could_not_prove)] + #[note("could not prove `{$predicate}`")] CouldNotProve { predicate: String }, - #[note(borrowck_could_not_normalize)] + #[note("could not normalize `{$value}`")] CouldNotNormalize { value: String }, } #[derive(Diagnostic)] -#[diag(borrowck_higher_ranked_subtype_error)] +#[diag("higher-ranked subtype error")] pub(crate) struct HigherRankedSubtypeError { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_generic_does_not_live_long_enough)] +#[diag("`{$kind}` does not live long enough")] pub(crate) struct GenericDoesNotLiveLongEnough { pub kind: String, #[primary_span] @@ -48,15 +48,20 @@ pub(crate) struct GenericDoesNotLiveLongEnough { } #[derive(LintDiagnostic)] -#[diag(borrowck_var_does_not_need_mut)] +#[diag("variable does not need to be mutable")] pub(crate) struct VarNeedNotMut { - #[suggestion(style = "short", applicability = "machine-applicable", code = "")] + #[suggestion( + "remove this `mut`", + style = "short", + applicability = "machine-applicable", + code = "" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_var_cannot_escape_closure)] -#[note] -#[note(borrowck_cannot_escape)] +#[diag("captured variable cannot escape `FnMut` closure body")] +#[note("`FnMut` closures only have access to their captured variables while they are executing...")] +#[note("...therefore, they cannot allow references to captured variables to escape")] pub(crate) struct FnMutError { #[primary_span] pub span: Span, @@ -66,17 +71,17 @@ pub(crate) struct FnMutError { #[derive(Subdiagnostic)] pub(crate) enum VarHereDenote { - #[label(borrowck_var_here_captured)] + #[label("variable captured here")] Captured { #[primary_span] span: Span, }, - #[label(borrowck_var_here_defined)] + #[label("variable defined here")] Defined { #[primary_span] span: Span, }, - #[label(borrowck_closure_inferred_mut)] + #[label("inferred to be a `FnMut` closure")] FnMutInferred { #[primary_span] span: Span, @@ -85,17 +90,21 @@ pub(crate) enum VarHereDenote { #[derive(Subdiagnostic)] pub(crate) enum FnMutReturnTypeErr { - #[label(borrowck_returned_closure_escaped)] + #[label( + "returns a closure that contains a reference to a captured variable, which then escapes the closure body" + )] ReturnClosure { #[primary_span] span: Span, }, - #[label(borrowck_returned_async_block_escaped)] + #[label( + "returns an `async` block that contains a reference to a captured variable, which then escapes the closure body" + )] ReturnAsyncBlock { #[primary_span] span: Span, }, - #[label(borrowck_returned_ref_escaped)] + #[label("returns a reference to a captured variable which escapes the closure body")] ReturnRef { #[primary_span] span: Span, @@ -103,7 +112,7 @@ pub(crate) enum FnMutReturnTypeErr { } #[derive(Diagnostic)] -#[diag(borrowck_lifetime_constraints_error)] +#[diag("lifetime may not live long enough")] pub(crate) struct LifetimeOutliveErr { #[primary_span] pub span: Span, @@ -111,7 +120,9 @@ pub(crate) struct LifetimeOutliveErr { #[derive(Subdiagnostic)] pub(crate) enum LifetimeReturnCategoryErr<'a> { - #[label(borrowck_returned_lifetime_wrong)] + #[label( + "{$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`" + )] WrongReturn { #[primary_span] span: Span, @@ -119,7 +130,9 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { outlived_fr_name: RegionName, fr_name: &'a RegionName, }, - #[label(borrowck_returned_lifetime_short)] + #[label( + "{$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`" + )] ShortReturn { #[primary_span] span: Span, @@ -131,7 +144,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { #[derive(Subdiagnostic)] pub(crate) enum RequireStaticErr { - #[note(borrowck_used_impl_require_static)] + #[note("the used `impl` has a `'static` requirement")] UsedImpl { #[primary_span] multi_span: MultiSpan, @@ -140,42 +153,42 @@ pub(crate) enum RequireStaticErr { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarPathUseCause { - #[label(borrowck_borrow_due_to_use_coroutine)] + #[label("borrow occurs due to use in coroutine")] BorrowInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_use_due_to_use_coroutine)] + #[label("use occurs due to use in coroutine")] UseInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_due_to_use_coroutine)] + #[label("assign occurs due to use in coroutine")] AssignInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_part_due_to_use_coroutine)] + #[label("assign to part occurs due to use in coroutine")] AssignPartInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_borrow_due_to_use_closure)] + #[label("borrow occurs due to use in closure")] BorrowInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_use_due_to_use_closure)] + #[label("use occurs due to use in closure")] UseInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_due_to_use_closure)] + #[label("assignment occurs due to use in closure")] AssignInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_part_due_to_use_closure)] + #[label("assignment to part occurs due to use in closure")] AssignPartInClosure { #[primary_span] path_span: Span, @@ -184,17 +197,17 @@ pub(crate) enum CaptureVarPathUseCause { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarKind { - #[label(borrowck_capture_immute)] + #[label("capture is immutable because of use here")] Immut { #[primary_span] kind_span: Span, }, - #[label(borrowck_capture_mut)] + #[label("capture is mutable because of use here")] Mut { #[primary_span] kind_span: Span, }, - #[label(borrowck_capture_move)] + #[label("capture is moved because of use here")] Move { #[primary_span] kind_span: Span, @@ -203,77 +216,97 @@ pub(crate) enum CaptureVarKind { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarCause { - #[label(borrowck_var_borrow_by_use_place_in_coroutine)] + #[label( + "{$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in coroutine" + )] BorrowUsePlaceCoroutine { is_single_var: bool, place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_place_in_closure)] + #[label( + "{$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in closure" + )] BorrowUsePlaceClosure { is_single_var: bool, place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_in_coroutine)] + #[label("borrow occurs due to use in coroutine")] BorrowUseInCoroutine { #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_in_closure)] + #[label("borrow occurs due to use in closure")] BorrowUseInClosure { #[primary_span] var_span: Span, }, - #[label(borrowck_var_move_by_use_in_coroutine)] + #[label("move occurs due to use in coroutine")] MoveUseInCoroutine { #[primary_span] var_span: Span, }, - #[label(borrowck_var_move_by_use_in_closure)] + #[label("move occurs due to use in closure")] MoveUseInClosure { #[primary_span] var_span: Span, }, - #[label(borrowck_var_first_borrow_by_use_place_in_coroutine)] + #[label("first borrow occurs due to use of {$place} in coroutine")] FirstBorrowUsePlaceCoroutine { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_first_borrow_by_use_place_in_closure)] + #[label("first borrow occurs due to use of {$place} in closure")] FirstBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_second_borrow_by_use_place_in_coroutine)] + #[label("second borrow occurs due to use of {$place} in coroutine")] SecondBorrowUsePlaceCoroutine { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_second_borrow_by_use_place_in_closure)] + #[label("second borrow occurs due to use of {$place} in closure")] SecondBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)] + #[label("mutable borrow occurs due to use of {$place} in closure")] MutableBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_partial_var_move_by_use_in_coroutine)] + #[label( + "variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in coroutine" + )] PartialMoveUseInCoroutine { #[primary_span] var_span: Span, is_partial: bool, }, - #[label(borrowck_partial_var_move_by_use_in_closure)] + #[label( + "variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in closure" + )] PartialMoveUseInClosure { #[primary_span] var_span: Span, @@ -282,34 +315,57 @@ pub(crate) enum CaptureVarCause { } #[derive(Diagnostic)] -#[diag(borrowck_cannot_move_when_borrowed, code = E0505)] +#[diag("cannot move out of {$place -> + [value] value + *[other] {$place} +} because it is borrowed", code = E0505)] pub(crate) struct MoveBorrow<'a> { pub place: &'a str, pub borrow_place: &'a str, pub value_place: &'a str, #[primary_span] - #[label(borrowck_move_label)] + #[label( + "move out of {$value_place -> + [value] value + *[other] {$value_place} + } occurs here" + )] pub span: Span, - #[label] + #[label( + "borrow of {$borrow_place -> + [value] value + *[other] {$borrow_place} + } occurs here" + )] pub borrow_span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_opaque_type_lifetime_mismatch)] +#[diag("opaque type used twice with different lifetimes")] pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> { pub arg: GenericArg<'tcx>, pub prev: GenericArg<'tcx>, #[primary_span] - #[label] - #[note] + #[label("lifetime `{$arg}` used here")] + #[note( + "if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types" + )] pub span: Span, - #[label(borrowck_prev_lifetime_label)] + #[label("lifetime `{$prev}` previously used here")] pub prev_span: Span, } #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonLabel<'a> { - #[label(borrowck_moved_due_to_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + }" + )] Call { #[primary_span] fn_call_span: Span, @@ -317,7 +373,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_usage_in_operator)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to usage in {$is_loop_message -> + [true] operator, in previous iteration of loop + *[false] operator + }" + )] OperatorUse { #[primary_span] fn_call_span: Span, @@ -325,7 +389,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_implicit_into_iter_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this implicit call to {$is_loop_message -> + [true] `.into_iter()`, in previous iteration of loop + *[false] `.into_iter()` + }" + )] ImplicitCall { #[primary_span] fn_call_span: Span, @@ -333,7 +405,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_method_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this method {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + }" + )] MethodCall { #[primary_span] fn_call_span: Span, @@ -341,7 +421,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_await)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] await, in previous iteration of loop + *[false] await + }" + )] Await { #[primary_span] fn_call_span: Span, @@ -349,7 +437,18 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_value_moved_here)] + #[label( + "value {$is_partial -> + [true] partially moved + *[false] moved + } {$is_move_msg -> + [true] into closure here + *[false] here + }{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {\"\"} + }" + )] MovedHere { #[primary_span] move_span: Span, @@ -357,7 +456,7 @@ pub(crate) enum CaptureReasonLabel<'a> { is_move_msg: bool, is_loop_message: bool, }, - #[label(borrowck_consider_borrow_type_contents)] + #[label("help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents")] BorrowContent { #[primary_span] var_span: Span, @@ -366,22 +465,22 @@ pub(crate) enum CaptureReasonLabel<'a> { #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonNote { - #[note(borrowck_moved_a_fn_once_in_call)] + #[note("this value implements `FnOnce`, which causes it to be moved when called")] FnOnceMoveInCall { #[primary_span] var_span: Span, }, - #[note(borrowck_calling_operator_moves)] + #[note("calling this operator moves the value")] UnOpMoveByOperator { #[primary_span] span: Span, }, - #[note(borrowck_calling_operator_moves_lhs)] + #[note("calling this operator moves the left-hand side")] LhsMoveByOperator { #[primary_span] span: Span, }, - #[note(borrowck_func_take_self_moved_place)] + #[note("`{$func}` takes ownership of the receiver `self`, which moves {$place_name}")] FuncTakeSelf { func: String, place_name: String, @@ -393,7 +492,7 @@ pub(crate) enum CaptureReasonNote { #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonSuggest<'tcx> { #[suggestion( - borrowck_suggest_iterate_over_slice, + "consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop", applicability = "maybe-incorrect", code = "&", style = "verbose" @@ -404,7 +503,7 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { span: Span, }, #[suggestion( - borrowck_suggest_create_fresh_reborrow, + "consider reborrowing the `Pin` instead of moving it", applicability = "maybe-incorrect", code = ".as_mut()", style = "verbose" @@ -417,13 +516,18 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum CaptureArgLabel { - #[label(borrowck_value_capture_here)] + #[label( + "value captured {$is_within -> + [true] here by coroutine + *[false] here + }" + )] Capture { is_within: bool, #[primary_span] args_span: Span, }, - #[label(borrowck_move_out_place_here)] + #[label("{$place} is moved here")] MoveOutPlace { place: String, #[primary_span] @@ -433,13 +537,17 @@ pub(crate) enum CaptureArgLabel { #[derive(Subdiagnostic)] pub(crate) enum OnClosureNote<'a> { - #[note(borrowck_closure_invoked_twice)] + #[note( + "closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment" + )] InvokedTwice { place_name: &'a str, #[primary_span] span: Span, }, - #[note(borrowck_closure_moved_twice)] + #[note( + "closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment" + )] MovedTwice { place_name: &'a str, #[primary_span] @@ -449,7 +557,12 @@ pub(crate) enum OnClosureNote<'a> { #[derive(Subdiagnostic)] pub(crate) enum TypeNoCopy<'a, 'tcx> { - #[label(borrowck_ty_no_impl_copy)] + #[label( + "{$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait" + )] Label { is_partial_move: bool, ty: Ty<'tcx>, @@ -457,12 +570,24 @@ pub(crate) enum TypeNoCopy<'a, 'tcx> { #[primary_span] span: Span, }, - #[note(borrowck_ty_no_impl_copy)] + #[note( + "{$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait" + )] Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, } #[derive(Diagnostic)] -#[diag(borrowck_simd_intrinsic_arg_const)] +#[diag( + "{$arg -> + [1] 1st + [2] 2nd + [3] 3rd + *[other] {$arg}th + } argument of `{$intrinsic}` is required to be a `const` item" +)] pub(crate) struct SimdIntrinsicArgConst { #[primary_span] pub span: Span, @@ -471,8 +596,8 @@ pub(crate) struct SimdIntrinsicArgConst { } #[derive(LintDiagnostic)] -#[diag(borrowck_tail_expr_drop_order)] +#[diag("relative drop order changing in Rust 2024")] pub(crate) struct TailExprDropOrder { - #[label] + #[label("this temporary value will be dropped at the end of the block")] pub borrowed: Span, } diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 39e512be6820f..be77b879757c7 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -10,7 +10,6 @@ jiff = { version = "0.2.5", default-features = false, features = ["std"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_borrowck = { path = "../rustc_borrowck" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e97b4fed245d..3b19ee3c672c5 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -114,7 +114,6 @@ pub fn default_translator() -> Translator { pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start - rustc_borrowck::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, From 6782a190f22df03d1106f4d4c1aa907c016ddebb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 17:17:45 +0100 Subject: [PATCH 45/47] Register functions in translation --- compiler/rustc_error_messages/src/lib.rs | 2 +- compiler/rustc_errors/src/translation.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index c9e887061305f..641defd1eabfe 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -192,7 +192,7 @@ pub fn fluent_bundle( Ok(Some(bundle)) } -fn register_functions(bundle: &mut FluentBundle) { +pub fn register_functions(bundle: &mut fluent_bundle::bundle::FluentBundle) { bundle .add_function("STREQ", |positional, _named| match positional { [FluentValue::String(a), FluentValue::String(b)] => format!("{}", (a == b)).into(), diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index aba79c30f3a30..ed3f9a405342e 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -3,8 +3,8 @@ use std::env; use std::error::Report; use std::sync::Arc; -use rustc_error_messages::langid; pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle}; +use rustc_error_messages::{langid, register_functions}; use tracing::{debug, trace}; use crate::error::{TranslateError, TranslateErrorKind}; @@ -91,6 +91,7 @@ impl Translator { let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); bundle.set_use_isolating(false); bundle.add_resource(resource).unwrap(); + register_functions(&mut bundle); let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); let value = message.value().unwrap(); From 55d1ba12d9df062e4ee6543f06657716028b5bbd Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 17:17:54 +0100 Subject: [PATCH 46/47] Convert to inline diagnostics in `rustc_trait_selection` --- Cargo.lock | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_trait_selection/Cargo.toml | 1 - compiler/rustc_trait_selection/messages.ftl | 470 ------------ .../src/error_reporting/infer/region.rs | 37 +- .../traits/fulfillment_errors.rs | 4 +- .../traits/on_unimplemented.rs | 18 +- .../traits/on_unimplemented_format.rs | 18 +- compiler/rustc_trait_selection/src/errors.rs | 704 +++++++++++++----- .../src/errors/note_and_explain.rs | 38 +- compiler/rustc_trait_selection/src/lib.rs | 2 - .../src/traits/normalize.rs | 3 +- 13 files changed, 586 insertions(+), 713 deletions(-) delete mode 100644 compiler/rustc_trait_selection/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 23abc6626aaba..a2a475b8011ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3797,7 +3797,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_trait_selection", "serde_json", "shlex", "tracing", @@ -4724,7 +4723,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_infer", "rustc_macros", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 39e512be6820f..4fdac2b3da4e2 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -36,7 +36,6 @@ rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -rustc_trait_selection = { path = "../rustc_trait_selection" } serde_json = "1.0.59" shlex = "1.0" tracing = { version = "0.1.35" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e97b4fed245d..83f502cf72d59 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -121,7 +121,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, - rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 1071105522d11..cd61a8f654733 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -10,7 +10,6 @@ rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl deleted file mode 100644 index fcb250250871e..0000000000000 --- a/compiler/rustc_trait_selection/messages.ftl +++ /dev/null @@ -1,470 +0,0 @@ -trait_selection_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} -trait_selection_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} -trait_selection_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} - -trait_selection_actual_impl_expl_expected_other_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_other_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}` - -trait_selection_actual_impl_expl_expected_other_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_other_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_actual_impl_expl_expected_passive_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` -trait_selection_actual_impl_expl_expected_passive_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_passive_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_actual_impl_expl_expected_signature_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}` -trait_selection_actual_impl_expl_expected_signature_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_signature_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_adjust_signature_borrow = consider adjusting the signature so it borrows its {$len -> - [one] argument - *[other] arguments - } - -trait_selection_adjust_signature_remove_borrow = consider adjusting the signature so it does not borrow its {$len -> - [one] argument - *[other] arguments - } - -trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds - -trait_selection_await_both_futures = consider `await`ing on both `Future`s -trait_selection_await_future = consider `await`ing on the `Future` -trait_selection_await_note = calling an async function returns a future - -trait_selection_but_calling_introduces = {$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$lifetime_kind -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement - .label1 = {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - } - .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> - [true] `impl` of `{$impl_path}` - *[false] inherent `impl` - } - -trait_selection_but_needs_to_satisfy = {$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but it needs to satisfy a `'static` lifetime requirement - .influencer = this data with {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - }... - .require = {$spans_empty -> - *[true] ...is used and required to live as long as `'static` here - [false] ...and is required to live as long as `'static` here - } - .used_here = ...is used here... - .introduced_by_bound = `'static` lifetime requirement introduced by this bound - -trait_selection_closure_fn_mut_label = closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here - -trait_selection_closure_fn_once_label = closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment - -trait_selection_closure_kind_mismatch = expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}` - .label = this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}` - -trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here - -trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait -trait_selection_consider_specifying_length = consider specifying the actual array length -trait_selection_coro_closure_not_fn = {$coro_kind}closure does not implement `{$kind}` because it captures state from its environment - -trait_selection_data_flows = ...but data{$label_var1_exists -> - [true] {" "}from `{$label_var1}` - *[false] {""} -} flows{$label_var2_exists -> - [true] {" "}into `{$label_var2}` - *[false] {""} -} here - -trait_selection_data_lifetime_flow = ...but data with one lifetime flows into the other here -trait_selection_data_returned = ...but data{$label_var1_exists -> - [true] {" "}from `{$label_var1}` - *[false] {""} -} is returned here - -trait_selection_declared_different = this parameter and the return type are declared with different lifetimes... -trait_selection_declared_multiple = this type is declared with multiple lifetimes... -trait_selection_disallowed_positional_argument = positional format arguments are not allowed here - .help = only named format arguments with the name of one of the generic types are allowed in this context - -trait_selection_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl` -trait_selection_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement -trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement -trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement -trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement - -trait_selection_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}` - -trait_selection_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type - -trait_selection_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}` - .label = lifetime `{$named}` required - -trait_selection_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type - .label = lifetime `{$named}` required - -trait_selection_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}` - -trait_selection_fn_consider_casting_both = consider casting both fn items to fn pointers using `as {$sig}` - -trait_selection_fn_uniq_types = different fn items have unique types, even if their signatures are the same -trait_selection_fps_cast = consider casting to a fn pointer -trait_selection_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}` - -trait_selection_fps_items_are_distinct = fn items are distinct from fn pointers -trait_selection_fps_remove_ref = consider removing the reference -trait_selection_fps_use_ref = consider using a reference -trait_selection_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime - -trait_selection_ignored_diagnostic_option = `{$option_name}` is ignored due to previous definition of `{$option_name}` - .other_label = `{$option_name}` is first declared here - .label = `{$option_name}` is already declared here - -trait_selection_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement -trait_selection_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement -trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}` - -trait_selection_invalid_format_specifier = invalid format specifier - .help = no format specifier are supported in this position - -trait_selection_label_bad = {$bad_kind -> - *[other] cannot infer type - [more_info] cannot infer {$prefix_kind -> - *[type] type for {$prefix} - [const_with_param] the value of const parameter - [const] the value of the constant - } `{$name}`{$has_parent -> - [true] {" "}declared on the {$parent_prefix} `{$parent_name}` - *[false] {""} - } -} - -trait_selection_lf_bound_not_satisfied = lifetime bound not satisfied -trait_selection_lifetime_mismatch = lifetime mismatch - -trait_selection_lifetime_param_suggestion = consider {$is_reuse -> - [true] reusing - *[false] introducing -} a named lifetime parameter{$is_impl -> - [true] {" "}and update trait if needed - *[false] {""} -} -trait_selection_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime - -trait_selection_malformed_on_unimplemented_attr = malformed `on_unimplemented` attribute - .help = only `message`, `note` and `label` are allowed as options - .label = invalid option found here - -trait_selection_meant_byte_literal = if you meant to write a byte literal, prefix with `b` -trait_selection_meant_char_literal = if you meant to write a `char` literal, use single quotes -trait_selection_meant_str_literal = if you meant to write a string literal, use double quotes -trait_selection_mismatched_static_lifetime = incompatible lifetime on type -trait_selection_missing_options_for_on_unimplemented_attr = missing options for `on_unimplemented` attribute - .help = at least one of the `message`, `note` and `label` options are expected - -trait_selection_msl_introduces_static = introduces a `'static` lifetime requirement -trait_selection_msl_unmet_req = because this has an unmet lifetime requirement - -trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> - [none] {""} - *[default] {" "}for type `{$self_desc}` - }: - .negative_implementation_here = negative implementation here - .negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}` - .positive_implementation_here = positive implementation here - .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}` - -trait_selection_nothing = {""} - -trait_selection_oc_cant_coerce_force_inline = - cannot coerce functions which must be inlined to function pointers -trait_selection_oc_cant_coerce_intrinsic = cannot coerce intrinsics to function pointers -trait_selection_oc_closure_selfref = closure/coroutine type that references itself -trait_selection_oc_const_compat = const not compatible with trait -trait_selection_oc_fn_lang_correct_type = {$lang_item_name -> - [panic_impl] `#[panic_handler]` - *[lang_item_name] lang item `{$lang_item_name}` - } function has wrong type -trait_selection_oc_fn_main_correct_type = `main` function has wrong type -trait_selection_oc_generic = mismatched types - -trait_selection_oc_if_else_different = `if` and `else` have incompatible types -trait_selection_oc_intrinsic_correct_type = intrinsic has wrong type -trait_selection_oc_match_compat = `match` arms have incompatible types -trait_selection_oc_method_compat = method not compatible with trait -trait_selection_oc_method_correct_type = mismatched `self` parameter type -trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge -trait_selection_oc_no_else = `if` may be missing an `else` clause -trait_selection_oc_try_compat = `?` operator has incompatible types -trait_selection_oc_type_compat = type not compatible with trait - -trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds - .label = opaque type defined here -trait_selection_opaque_type_non_generic_param = - expected generic {$kind} parameter, found `{$arg}` - .label = {STREQ($arg, "'static") -> - [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type - *[other] this generic parameter must be used with a generic {$kind} parameter - } - -trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type -trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content... - -trait_selection_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it -trait_selection_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}` - -trait_selection_precise_capturing_new_but_apit = add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate - -trait_selection_precise_capturing_overcaptures = use the precise capturing `use<...>` syntax to make the captures explicit - -trait_selection_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here... -trait_selection_prlf_defined_without_sub = the lifetime defined here... -trait_selection_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 for more information) - -trait_selection_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here -trait_selection_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here -trait_selection_reborrow = ...so that reference does not outlive borrowed content -trait_selection_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references - -trait_selection_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at -trait_selection_region_explanation = {$pref_kind -> - *[should_not_happen] [{$pref_kind}] - [ref_valid_for] ...the reference is valid for - [content_valid_for] ...but the borrowed content is only valid for - [type_obj_valid_for] object type is valid for - [source_pointer_valid_for] source pointer is only valid for - [type_satisfy] type must satisfy - [type_outlive] type must outlive - [lf_param_instantiated_with] lifetime parameter instantiated with - [lf_param_must_outlive] but lifetime parameter must outlive - [lf_instantiated_with] lifetime instantiated with - [lf_must_outlive] but lifetime must outlive - [pointer_valid_for] the pointer is valid for - [data_valid_for] but the referenced data is only valid for - [empty] {""} -}{$pref_kind -> - [empty] {""} - *[other] {" "} -}{$desc_kind -> - *[should_not_happen] [{$desc_kind}] - [restatic] the static lifetime - [revar] lifetime {$desc_arg} - [as_defined] the lifetime `{$desc_arg}` as defined here - [as_defined_anon] the anonymous lifetime as defined here - [defined_here] the anonymous lifetime defined here - [defined_here_reg] the lifetime `{$desc_arg}` as defined here -}{$suff_kind -> - *[should_not_happen] [{$suff_kind}] - [empty]{""} - [continues] ... - [req_by_binding] {" "}as required by this binding -} - -trait_selection_relate_object_bound = ...so that it can be closed over into an object -trait_selection_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues -> - [true] ... - *[false] {""} -} -trait_selection_relate_param_bound_2 = ...that is required by this bound -trait_selection_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied -trait_selection_ril_because_of = because of this returned expression -trait_selection_ril_introduced_by = requirement introduced by this return type -trait_selection_ril_introduced_here = `'static` requirement introduced here -trait_selection_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type - -trait_selection_rustc_on_unimplemented_empty_on_clause = empty `on`-clause in `#[rustc_on_unimplemented]` - .label = empty `on`-clause here -trait_selection_rustc_on_unimplemented_expected_identifier = expected an identifier inside this `on`-clause - .label = expected an identifier here, not `{$path}` -trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not = expected a single predicate in `not(..)` - .label = unexpected quantity of predicates here -trait_selection_rustc_on_unimplemented_invalid_flag = invalid flag in `on`-clause - .label = expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}` -trait_selection_rustc_on_unimplemented_invalid_name = invalid name in `on`-clause - .label = expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}` -trait_selection_rustc_on_unimplemented_invalid_predicate = this predicate is invalid - .label = expected one of `any`, `all` or `not` here, not `{$invalid_pred}` -trait_selection_rustc_on_unimplemented_missing_value = this attribute must have a value - .label = expected value here - .note = e.g. `#[rustc_on_unimplemented(message="foo")]` -trait_selection_rustc_on_unimplemented_unsupported_literal_in_on = literals inside `on`-clauses are not supported - .label = unexpected literal here - -trait_selection_source_kind_closure_return = - try giving this closure an explicit return type - -# coroutine_kind may need to be translated -trait_selection_source_kind_fully_qualified = - try using a fully qualified path to specify the expected types - -trait_selection_source_kind_subdiag_generic_label = - cannot infer {$is_type -> - [true] type - *[false] the value - } of the {$is_type -> - [true] type - *[false] const - } {$parent_exists -> - [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` - *[false] parameter {$param_name} - } - -trait_selection_source_kind_subdiag_generic_suggestion = - consider specifying the generic {$arg_count -> - [one] argument - *[other] arguments - } - -trait_selection_source_kind_subdiag_let = {$kind -> - [with_pattern] consider giving `{$name}` an explicit type - [closure] consider giving this closure parameter an explicit type - *[other] consider giving this pattern a type -}{$x_kind -> - [has_name] , where the {$prefix_kind -> - *[type] type for {$prefix} - [const_with_param] value of const parameter - [const] value of the constant - } `{$arg_name}` is specified - [underscore] , where the placeholders `_` are specified - *[empty] {""} -} - -trait_selection_srs_add = consider returning the local binding `{$ident}` -trait_selection_srs_add_one = consider returning one of these bindings - -trait_selection_srs_remove = consider removing this semicolon -trait_selection_srs_remove_and_box = consider removing this semicolon and boxing the expressions -trait_selection_stp_wrap_many = try wrapping the pattern in a variant of `{$path}` - -trait_selection_stp_wrap_one = try wrapping the pattern in `{$variant}` -trait_selection_subtype = ...so that the {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` function has the correct type - [fn_lang_correct_type] lang item function has the correct type - [intrinsic_correct_type] intrinsic has the correct type - [method_correct_type] method receiver has the correct type - *[other] types are compatible -} -trait_selection_subtype_2 = ...so that {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` function has the correct type - [fn_lang_correct_type] lang item function has the correct type - [intrinsic_correct_type] intrinsic has the correct type - [method_correct_type] method receiver has the correct type - *[other] types are compatible -} - -trait_selection_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}` - -trait_selection_suggest_add_let_for_letchains = consider adding `let` - -trait_selection_tid_consider_borrowing = consider borrowing this type parameter in the trait -trait_selection_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - -trait_selection_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output -trait_selection_trait_has_no_impls = this trait has no implementations, consider adding one - -trait_selection_trait_impl_diff = `impl` item signature doesn't match `trait` item signature - .found = found `{$found}` - .expected = expected `{$expected}` - .expected_found = expected signature `{$expected}` - {" "}found signature `{$found}` - -trait_selection_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough - .label_satisfy = doesn't satisfy where-clause - .label_where = due to a where-clause on `{$def_id}`... - .label_dup = implementation of `{$trait_def_id}` is not general enough - -trait_selection_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}` - -trait_selection_tuple_trailing_comma = use a trailing comma to create a tuple with one element - -trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead -trait_selection_type_annotations_needed = {$source_kind -> - [closure] type annotations needed for the closure `{$source_name}` - [normal] type annotations needed for `{$source_name}` - *[other] type annotations needed -} - .label = type must be known at this point - -trait_selection_types_declared_different = these two types are declared with different lifetimes... - -trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} - -trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}` - .help = expect either a generic argument name or {"`{Self}`"} as format argument - -trait_selection_warn_removing_apit_params_for_overcapture = you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable - -trait_selection_warn_removing_apit_params_for_undercapture = you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable - -trait_selection_where_copy_predicates = copy the `where` clause predicates from the trait - -trait_selection_where_remove = remove the `where` clause -trait_selection_wrapped_parser_error = {$description} - .label = {$label} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index b11461cd0e32d..d15fb40dd1cb0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -2,7 +2,8 @@ use std::iter; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ - Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, struct_span_code_err, + Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, inline_fluent, + struct_span_code_err, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -25,7 +26,6 @@ use crate::errors::{ self, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, RefLongerThanData, RegionOriginNote, WhereClauseSuggestions, note_and_explain, }; -use crate::fluent_generated as fluent; use crate::infer::region_constraints::GenericKind; use crate::infer::{ BoundRegionConversionTime, InferCtxt, RegionResolutionError, RegionVariableOrigin, @@ -228,18 +228,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()), } .add_to_diag(err), - SubregionOrigin::Reborrow(span) => { - RegionOriginNote::Plain { span, msg: fluent::trait_selection_reborrow } - .add_to_diag(err) + SubregionOrigin::Reborrow(span) => RegionOriginNote::Plain { + span, + msg: inline_fluent!("...so that reference does not outlive borrowed content"), } + .add_to_diag(err), SubregionOrigin::RelateObjectBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_object_bound } - .add_to_diag(err); + RegionOriginNote::Plain { + span, + msg: inline_fluent!("...so that it can be closed over into an object"), + } + .add_to_diag(err); } SubregionOrigin::ReferenceOutlivesReferent(ty, span) => { RegionOriginNote::WithName { span, - msg: fluent::trait_selection_reference_outlives_referent, + msg: inline_fluent!("...so that the reference type `{$name}` does not outlive the data it points at"), name: &self.ty_to_string(ty), continues: false, } @@ -248,7 +252,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, - msg: fluent::trait_selection_relate_param_bound, + msg: inline_fluent!("...so that the type `{$name}` will meet its required lifetime bounds{$continues -> +[true] ... +*[false] {\"\"} +}"), name: &self.ty_to_string(ty), continues: opt_span.is_some(), } @@ -256,7 +263,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(span) = opt_span { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_relate_param_bound_2, + msg: inline_fluent!("...that is required by this bound"), } .add_to_diag(err); } @@ -264,14 +271,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_relate_region_param_bound, + msg: inline_fluent!( + "...so that the declared lifetime parameter bounds are satisfied" + ), } .add_to_diag(err); } SubregionOrigin::CompareImplItemObligation { span, .. } => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_compare_impl_item_obligation, + msg: inline_fluent!( + "...so that the definition in impl matches the definition from the trait" + ), } .add_to_diag(err); } @@ -281,7 +292,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::AscribeUserTypeProvePredicate(span) => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_ascribe_user_type_prove_predicate, + msg: inline_fluent!("...so that the where clause holds"), } .add_to_diag(err); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 45e4f5fe23a6f..3cb3224302b6c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -12,7 +12,7 @@ use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, - pluralize, struct_span_code_err, + inline_fluent, pluralize, struct_span_code_err, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; @@ -3003,7 +3003,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { err.span_help( self.tcx.def_span(trait_def_id), - crate::fluent_generated::trait_selection_trait_has_no_impls, + inline_fluent!("this trait has no implementations, consider adding one"), ); } else if !suggested && trait_predicate.polarity() == ty::PredicatePolarity::Positive { // Can't show anything else useful, try to find similar impls. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 0a6af42e122b6..5eff7bba7c633 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -360,10 +360,10 @@ pub enum AppendConstMessage { } #[derive(LintDiagnostic)] -#[diag(trait_selection_malformed_on_unimplemented_attr)] -#[help] +#[diag("malformed `on_unimplemented` attribute")] +#[help("only `message`, `note` and `label` are allowed as options")] pub struct MalformedOnUnimplementedAttrLint { - #[label] + #[label("invalid option found here")] pub span: Span, } @@ -374,17 +374,17 @@ impl MalformedOnUnimplementedAttrLint { } #[derive(LintDiagnostic)] -#[diag(trait_selection_missing_options_for_on_unimplemented_attr)] -#[help] +#[diag("missing options for `on_unimplemented` attribute")] +#[help("at least one of the `message`, `note` and `label` options are expected")] pub struct MissingOptionsForOnUnimplementedAttr; #[derive(LintDiagnostic)] -#[diag(trait_selection_ignored_diagnostic_option)] +#[diag("`{$option_name}` is ignored due to previous definition of `{$option_name}`")] pub struct IgnoredDiagnosticOption { pub option_name: &'static str, - #[label] + #[label("`{$option_name}` is already declared here")] pub span: Span, - #[label(trait_selection_other_label)] + #[label("`{$option_name}` is first declared here")] pub prev_span: Span, } @@ -410,7 +410,7 @@ impl IgnoredDiagnosticOption { } #[derive(LintDiagnostic)] -#[diag(trait_selection_wrapped_parser_error)] +#[diag("{$description}")] pub struct WrappedParserError { pub description: String, pub label: String, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs index 1954f8a1f639f..8488d76e2c773 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs @@ -310,25 +310,27 @@ pub mod errors { use super::*; #[derive(LintDiagnostic)] - #[diag(trait_selection_unknown_format_parameter_for_on_unimplemented_attr)] - #[help] + #[diag("there is no parameter `{$argument_name}` on trait `{$trait_name}`")] + #[help("expect either a generic argument name or {\"`{Self}`\"} as format argument")] pub struct UnknownFormatParameterForOnUnimplementedAttr { pub argument_name: Symbol, pub trait_name: Ident, } #[derive(LintDiagnostic)] - #[diag(trait_selection_disallowed_positional_argument)] - #[help] + #[diag("positional format arguments are not allowed here")] + #[help( + "only named format arguments with the name of one of the generic types are allowed in this context" + )] pub struct DisallowedPositionalArgument; #[derive(LintDiagnostic)] - #[diag(trait_selection_invalid_format_specifier)] - #[help] + #[diag("invalid format specifier")] + #[help("no format specifier are supported in this position")] pub struct InvalidFormatSpecifier; #[derive(LintDiagnostic)] - #[diag(trait_selection_missing_options_for_on_unimplemented_attr)] - #[help] + #[diag("missing options for `on_unimplemented` attribute")] + #[help("at least one of the `message`, `note` and `label` options are expected")] pub struct MissingOptionsForOnUnimplementedAttr; } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index af241099c0149..e0690b8a6245d 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -3,7 +3,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, inline_fluent, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -17,12 +17,11 @@ use rustc_span::{BytePos, Ident, Span, Symbol, kw}; use crate::error_reporting::infer::ObligationCauseAsDiagArg; use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind; use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted; -use crate::fluent_generated as fluent; pub mod note_and_explain; #[derive(Diagnostic)] -#[diag(trait_selection_unable_to_construct_constant_value)] +#[diag("unable to construct a constant value for the unevaluated constant {$unevaluated}")] pub struct UnableToConstructConstantValue<'a> { #[primary_span] pub span: Span, @@ -31,60 +30,64 @@ pub struct UnableToConstructConstantValue<'a> { #[derive(Diagnostic)] pub enum InvalidOnClause { - #[diag(trait_selection_rustc_on_unimplemented_empty_on_clause, code = E0232)] + #[diag("empty `on`-clause in `#[rustc_on_unimplemented]`", code = E0232)] Empty { #[primary_span] - #[label] + #[label("empty `on`-clause here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not, code = E0232)] + #[diag("expected a single predicate in `not(..)`", code = E0232)] ExpectedOnePredInNot { #[primary_span] - #[label] + #[label("unexpected quantity of predicates here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_unsupported_literal_in_on, code = E0232)] + #[diag("literals inside `on`-clauses are not supported", code = E0232)] UnsupportedLiteral { #[primary_span] - #[label] + #[label("unexpected literal here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_expected_identifier, code = E0232)] + #[diag("expected an identifier inside this `on`-clause", code = E0232)] ExpectedIdentifier { #[primary_span] - #[label] + #[label("expected an identifier here, not `{$path}`")] span: Span, path: Path, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_predicate, code = E0232)] + #[diag("this predicate is invalid", code = E0232)] InvalidPredicate { #[primary_span] - #[label] + #[label("expected one of `any`, `all` or `not` here, not `{$invalid_pred}`")] span: Span, invalid_pred: Symbol, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_flag, code = E0232)] + #[diag("invalid flag in `on`-clause", code = E0232)] InvalidFlag { #[primary_span] - #[label] + #[label( + "expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`" + )] span: Span, invalid_flag: Symbol, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_name, code = E0232)] + #[diag("invalid name in `on`-clause", code = E0232)] InvalidName { #[primary_span] - #[label] + #[label( + "expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}`" + )] span: Span, invalid_name: Symbol, }, } #[derive(Diagnostic)] -#[diag(trait_selection_rustc_on_unimplemented_missing_value, code = E0232)] -#[note] +#[diag("this attribute must have a value", code = E0232)] +#[note("e.g. `#[rustc_on_unimplemented(message=\"foo\")]`")] pub struct NoValueInOnUnimplemented { #[primary_span] - #[label] + #[label("expected value here")] pub span: Span, } @@ -99,26 +102,33 @@ pub struct NegativePositiveConflict<'tcx> { impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::trait_selection_negative_positive_conflict); + let mut diag = Diag::new(dcx, level, inline_fluent!("found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> +[none] {\"\"} +*[default] {\" \"}for type `{$self_desc}` +}:")); diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); diag.span(self.impl_span); diag.code(E0751); match self.negative_impl_span { Ok(span) => { - diag.span_label(span, fluent::trait_selection_negative_implementation_here); + diag.span_label(span, inline_fluent!("negative implementation here")); } Err(cname) => { - diag.note(fluent::trait_selection_negative_implementation_in_crate); + diag.note(inline_fluent!( + "negative implementation in crate `{$negative_impl_cname}`" + )); diag.arg("negative_impl_cname", cname.to_string()); } } match self.positive_impl_span { Ok(span) => { - diag.span_label(span, fluent::trait_selection_positive_implementation_here); + diag.span_label(span, inline_fluent!("positive implementation here")); } Err(cname) => { - diag.note(fluent::trait_selection_positive_implementation_in_crate); + diag.note(inline_fluent!( + "positive implementation in crate `{$positive_impl_cname}`" + )); diag.arg("positive_impl_cname", cname.to_string()); } } @@ -127,7 +137,7 @@ impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { } #[derive(Diagnostic)] -#[diag(trait_selection_inherent_projection_normalization_overflow)] +#[diag("overflow evaluating associated type `{$ty}`")] pub struct InherentProjectionNormalizationOverflow { #[primary_span] pub span: Span, @@ -145,7 +155,12 @@ impl Subdiagnostic for AdjustSignatureBorrow { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("len", to_borrow.len()); diag.multipart_suggestion_verbose( - fluent::trait_selection_adjust_signature_borrow, + inline_fluent!( + "consider adjusting the signature so it borrows its {$len -> +[one] argument +*[other] arguments +}" + ), to_borrow, Applicability::MaybeIncorrect, ); @@ -153,7 +168,12 @@ impl Subdiagnostic for AdjustSignatureBorrow { AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { diag.arg("len", remove_borrow.len()); diag.multipart_suggestion_verbose( - fluent::trait_selection_adjust_signature_remove_borrow, + inline_fluent!( + "consider adjusting the signature so it does not borrow its {$len -> +[one] argument +*[other] arguments +}" + ), remove_borrow, Applicability::MaybeIncorrect, ); @@ -163,14 +183,14 @@ impl Subdiagnostic for AdjustSignatureBorrow { } #[derive(Diagnostic)] -#[diag(trait_selection_closure_kind_mismatch, code = E0525)] +#[diag("expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}`", code = E0525)] pub struct ClosureKindMismatch { #[primary_span] - #[label] + #[label("this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}`")] pub closure_span: Span, pub expected: ClosureKind, pub found: ClosureKind, - #[label(trait_selection_closure_kind_requirement)] + #[label("the requirement to implement `{$trait_prefix}{$expected}` derives from here")] pub cause_span: Span, pub trait_prefix: &'static str, @@ -183,7 +203,9 @@ pub struct ClosureKindMismatch { } #[derive(Subdiagnostic)] -#[label(trait_selection_closure_fn_once_label)] +#[label( + "closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment" +)] pub struct ClosureFnOnceLabel { #[primary_span] pub span: Span, @@ -191,7 +213,7 @@ pub struct ClosureFnOnceLabel { } #[derive(Subdiagnostic)] -#[label(trait_selection_closure_fn_mut_label)] +#[label("closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here")] pub struct ClosureFnMutLabel { #[primary_span] pub span: Span, @@ -199,7 +221,9 @@ pub struct ClosureFnMutLabel { } #[derive(Diagnostic)] -#[diag(trait_selection_coro_closure_not_fn)] +#[diag( + "{$coro_kind}closure does not implement `{$kind}` because it captures state from its environment" +)] pub(crate) struct CoroClosureNotFn { #[primary_span] pub span: Span, @@ -208,13 +232,17 @@ pub(crate) struct CoroClosureNotFn { } #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0282)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0282)] pub struct AnnotationRequired<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -226,13 +254,17 @@ pub struct AnnotationRequired<'a> { // Copy of `AnnotationRequired` for E0283 #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0283)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0283)] pub struct AmbiguousImpl<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -244,13 +276,17 @@ pub struct AmbiguousImpl<'a> { // Copy of `AnnotationRequired` for E0284 #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0284)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0284)] pub struct AmbiguousReturn<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -262,7 +298,19 @@ pub struct AmbiguousReturn<'a> { // Used when a better one isn't available #[derive(Subdiagnostic)] -#[label(trait_selection_label_bad)] +#[label( + "{$bad_kind -> +*[other] cannot infer type +[more_info] cannot infer {$prefix_kind -> +*[type] type for {$prefix} +[const_with_param] the value of const parameter +[const] the value of the constant +} `{$name}`{$has_parent -> +[true] {\" \"}declared on the {$parent_prefix} `{$parent_name}` +*[false] {\"\"} +} +}" +)] pub struct InferenceBadError<'a> { #[primary_span] pub span: Span, @@ -278,7 +326,19 @@ pub struct InferenceBadError<'a> { #[derive(Subdiagnostic)] pub enum SourceKindSubdiag<'a> { #[suggestion( - trait_selection_source_kind_subdiag_let, + "{$kind -> +[with_pattern] consider giving `{$name}` an explicit type +[closure] consider giving this closure parameter an explicit type +*[other] consider giving this pattern a type +}{$x_kind -> +[has_name] , where the {$prefix_kind -> +*[type] type for {$prefix} +[const_with_param] value of const parameter +[const] value of the constant +} `{$arg_name}` is specified +[underscore] , where the placeholders `_` are specified +*[empty] {\"\"} +}", style = "verbose", code = ": {type_name}", applicability = "has-placeholders" @@ -294,7 +354,18 @@ pub enum SourceKindSubdiag<'a> { prefix: &'a str, arg_name: String, }, - #[label(trait_selection_source_kind_subdiag_generic_label)] + #[label( + "cannot infer {$is_type -> +[true] type +*[false] the value +} of the {$is_type -> +[true] type +*[false] const +} {$parent_exists -> +[true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` +*[false] parameter {$param_name} +}" + )] GenericLabel { #[primary_span] span: Span, @@ -305,7 +376,10 @@ pub enum SourceKindSubdiag<'a> { parent_name: String, }, #[suggestion( - trait_selection_source_kind_subdiag_generic_suggestion, + "consider specifying the generic {$arg_count -> +[one] argument +*[other] arguments +}", style = "verbose", code = "::<{args}>", applicability = "has-placeholders" @@ -321,7 +395,7 @@ pub enum SourceKindSubdiag<'a> { #[derive(Subdiagnostic)] pub enum SourceKindMultiSuggestion<'a> { #[multipart_suggestion( - trait_selection_source_kind_fully_qualified, + "try using a fully qualified path to specify the expected types", style = "verbose", applicability = "has-placeholders" )] @@ -335,7 +409,7 @@ pub enum SourceKindMultiSuggestion<'a> { successor_pos: &'a str, }, #[multipart_suggestion( - trait_selection_source_kind_closure_return, + "try giving this closure an explicit return type", style = "verbose", applicability = "has-placeholders" )] @@ -427,7 +501,24 @@ impl Subdiagnostic for RegionOriginNote<'_> { requirement, expected_found: Some((expected, found)), } => { - label_or_note(span, fluent::trait_selection_subtype); + label_or_note( + span, + inline_fluent!( + "...so that the {$requirement -> +[method_compat] method type is compatible with trait +[type_compat] associated type is compatible with trait +[const_compat] const is compatible with trait +[expr_assignable] expression is assignable +[if_else_different] `if` and `else` have incompatible types +[no_else] `if` missing an `else` returns `()` +[fn_main_correct_type] `main` function has the correct type +[fn_lang_correct_type] lang item function has the correct type +[intrinsic_correct_type] intrinsic has the correct type +[method_correct_type] method receiver has the correct type +*[other] types are compatible +}" + ), + ); diag.arg("requirement", requirement); diag.note_expected_found("", expected, "", found); @@ -436,7 +527,24 @@ impl Subdiagnostic for RegionOriginNote<'_> { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is // *terrible*. - label_or_note(span, fluent::trait_selection_subtype_2); + label_or_note( + span, + inline_fluent!( + "...so that {$requirement -> +[method_compat] method type is compatible with trait +[type_compat] associated type is compatible with trait +[const_compat] const is compatible with trait +[expr_assignable] expression is assignable +[if_else_different] `if` and `else` have incompatible types +[no_else] `if` missing an `else` returns `()` +[fn_main_correct_type] `main` function has the correct type +[fn_lang_correct_type] lang item function has the correct type +[intrinsic_correct_type] intrinsic has the correct type +[method_correct_type] method receiver has the correct type +*[other] types are compatible +}" + ), + ); diag.arg("requirement", requirement); } }; @@ -464,9 +572,17 @@ impl Subdiagnostic for LifetimeMismatchLabels { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { - diag.span_label(param_span, fluent::trait_selection_declared_different); - diag.span_label(ret_span, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_returned); + diag.span_label(param_span, inline_fluent!("this parameter and the return type are declared with different lifetimes...")); + diag.span_label(ret_span, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!( + "...but data{$label_var1_exists -> +[true] {\" \"}from `{$label_var1}` +*[false] {\"\"} +} is returned here" + ), + ); diag.arg("label_var1_exists", label_var1.is_some()); diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); } @@ -479,13 +595,33 @@ impl Subdiagnostic for LifetimeMismatchLabels { sub: label_var2, } => { if hir_equal { - diag.span_label(ty_sup, fluent::trait_selection_declared_multiple); - diag.span_label(ty_sub, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_lifetime_flow); + diag.span_label( + ty_sup, + inline_fluent!("this type is declared with multiple lifetimes..."), + ); + diag.span_label(ty_sub, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!("...but data with one lifetime flows into the other here"), + ); } else { - diag.span_label(ty_sup, fluent::trait_selection_types_declared_different); - diag.span_label(ty_sub, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_flows); + diag.span_label( + ty_sup, + inline_fluent!("these two types are declared with different lifetimes..."), + ); + diag.span_label(ty_sub, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!( + "...but data{$label_var1_exists -> +[true] {\" \"}from `{$label_var1}` +*[false] {\"\"} +} flows{$label_var2_exists -> +[true] {\" \"}into `{$label_var2}` +*[false] {\"\"} +} here" + ), + ); diag.arg("label_var1_exists", label_var1.is_some()); diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); diag.arg("label_var2_exists", label_var2.is_some()); @@ -651,7 +787,15 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { visitor.suggestions.push(new_param_suggestion); } diag.multipart_suggestion_verbose( - fluent::trait_selection_lifetime_param_suggestion, + inline_fluent!( + "consider {$is_reuse -> +[true] reusing +*[false] introducing +} a named lifetime parameter{$is_impl -> +[true] {\" \"}and update trait if needed +*[false] {\"\"} +}" + ), visitor.suggestions, Applicability::MaybeIncorrect, ); @@ -661,13 +805,15 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { true }; if mk_suggestion() && self.add_note { - diag.note(fluent::trait_selection_lifetime_param_suggestion_elided); + diag.note(inline_fluent!( + "each elided lifetime in input position becomes a distinct lifetime" + )); } } } #[derive(Diagnostic)] -#[diag(trait_selection_lifetime_mismatch, code = E0623)] +#[diag("lifetime mismatch", code = E0623)] pub struct LifetimeMismatch<'a> { #[primary_span] pub span: Span, @@ -684,33 +830,42 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { - self.unmet_requirements - .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static); - diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req); + self.unmet_requirements.push_span_label( + self.binding_span, + inline_fluent!("introduces a `'static` lifetime requirement"), + ); + diag.span_note( + self.unmet_requirements, + inline_fluent!("because this has an unmet lifetime requirement"), + ); } } // FIXME(#100717): replace with a `Option` when subdiagnostic supports that #[derive(Subdiagnostic)] pub enum DoesNotOutliveStaticFromImpl { - #[note(trait_selection_does_not_outlive_static_from_impl)] + #[note( + "...does not necessarily outlive the static lifetime introduced by the compatible `impl`" + )] Spanned { #[primary_span] span: Span, }, - #[note(trait_selection_does_not_outlive_static_from_impl)] + #[note( + "...does not necessarily outlive the static lifetime introduced by the compatible `impl`" + )] Unspanned, } #[derive(Subdiagnostic)] pub enum ImplicitStaticLifetimeSubdiag { - #[note(trait_selection_implicit_static_lifetime_note)] + #[note("this has an implicit `'static` lifetime requirement")] Note { #[primary_span] span: Span, }, #[suggestion( - trait_selection_implicit_static_lifetime_suggestion, + "consider relaxing the implicit `'static` requirement", style = "verbose", code = " + '_", applicability = "maybe-incorrect" @@ -722,7 +877,7 @@ pub enum ImplicitStaticLifetimeSubdiag { } #[derive(Diagnostic)] -#[diag(trait_selection_mismatched_static_lifetime)] +#[diag("incompatible lifetime on type")] pub struct MismatchedStaticLifetime<'a> { #[primary_span] pub cause_span: Span, @@ -738,15 +893,15 @@ pub struct MismatchedStaticLifetime<'a> { #[derive(Diagnostic)] pub enum ExplicitLifetimeRequired<'a> { - #[diag(trait_selection_explicit_lifetime_required_with_ident, code = E0621)] + #[diag("explicit lifetime required in the type of `{$simple_ident}`", code = E0621)] WithIdent { #[primary_span] - #[label] + #[label("lifetime `{$named}` required")] span: Span, simple_ident: Ident, named: String, #[suggestion( - trait_selection_explicit_lifetime_required_sugg_with_ident, + "add explicit lifetime `{$named}` to the type of `{$simple_ident}`", code = "{new_ty}", applicability = "unspecified", style = "verbose" @@ -755,14 +910,14 @@ pub enum ExplicitLifetimeRequired<'a> { #[skip_arg] new_ty: Ty<'a>, }, - #[diag(trait_selection_explicit_lifetime_required_with_param_type, code = E0621)] + #[diag("explicit lifetime required in parameter type", code = E0621)] WithParamType { #[primary_span] - #[label] + #[label("lifetime `{$named}` required")] span: Span, named: String, #[suggestion( - trait_selection_explicit_lifetime_required_sugg_with_param_type, + "add explicit lifetime `{$named}` to type", code = "{new_ty}", applicability = "unspecified", style = "verbose" @@ -789,7 +944,10 @@ impl IntoDiagArg for TyOrSig<'_> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes<'tcx> { - #[note(trait_selection_actual_impl_expl_expected_signature_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedSignatureTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -797,27 +955,41 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_any)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] ExpectedSignatureAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_some)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedSignatureSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" + )] ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_expected_passive_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedPassiveTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -825,27 +997,41 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_any)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] ExpectedPassiveAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_some)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedPassiveSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" + )] ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_expected_other_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedOtherTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -853,40 +1039,70 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_any)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." + )] ExpectedOtherAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_some)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." + )] ExpectedOtherSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`" + )] ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_but_actually_implements_trait)] + #[note( + "...but it actually implements `{$trait_path}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyImplementsTrait { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, }, - #[note(trait_selection_actual_impl_expl_but_actually_implemented_for_ty)] + #[note( + "...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyImplementedForTy { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, ty: String, }, - #[note(trait_selection_actual_impl_expl_but_actually_ty_implements)] + #[note( + "...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyTyImplements { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, @@ -978,15 +1194,15 @@ impl<'tcx> ActualImplExplNotes<'tcx> { } #[derive(Diagnostic)] -#[diag(trait_selection_trait_placeholder_mismatch)] +#[diag("implementation of `{$trait_def_id}` is not general enough")] pub struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, - #[label(trait_selection_label_satisfy)] + #[label("doesn't satisfy where-clause")] pub satisfy_span: Option, - #[label(trait_selection_label_where)] + #[label("due to a where-clause on `{$def_id}`...")] pub where_span: Option, - #[label(trait_selection_label_dup)] + #[label("implementation of `{$trait_def_id}` is not general enough")] pub dup_span: Option, pub def_id: String, pub trait_def_id: String, @@ -1004,26 +1220,34 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required - type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing); + type_param_span.push_span_label( + span, + inline_fluent!("consider borrowing this type parameter in the trait"), + ); } - let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help); + let msg = diag.eagerly_translate(inline_fluent!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`")); diag.span_help(type_param_span, msg); } } #[derive(Subdiagnostic)] -#[help(trait_selection_tid_rel_help)] +#[help( + "verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output" +)] pub struct RelationshipHelp; #[derive(Diagnostic)] -#[diag(trait_selection_trait_impl_diff)] +#[diag("`impl` item signature doesn't match `trait` item signature")] pub struct TraitImplDiff { #[primary_span] - #[label(trait_selection_found)] + #[label("found `{$found}`")] pub sp: Span, - #[label(trait_selection_expected)] + #[label("expected `{$expected}`")] pub trait_sp: Span, - #[note(trait_selection_expected_found)] + #[note( + "expected signature `{$expected}` + {\" \"}found signature `{$found}`" + )] pub note: (), #[subdiagnostic] pub param_help: ConsiderBorrowingParamHelp, @@ -1043,12 +1267,20 @@ pub struct DynTraitConstraintSuggestion { impl Subdiagnostic for DynTraitConstraintSuggestion { fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multi_span: MultiSpan = vec![self.span].into(); - multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label); - multi_span - .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement); - let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note); + multi_span.push_span_label( + self.span, + inline_fluent!("this has an implicit `'static` lifetime requirement"), + ); + multi_span.push_span_label( + self.ident.span, + inline_fluent!("calling this method introduces the `impl`'s `'static` requirement"), + ); + let msg = + diag.eagerly_translate(inline_fluent!("the used `impl` has a `'static` requirement")); diag.span_note(multi_span, msg); - let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion); + let msg = diag.eagerly_translate(inline_fluent!( + "consider relaxing the implicit `'static` requirement" + )); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -1059,12 +1291,26 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { } #[derive(Diagnostic)] -#[diag(trait_selection_but_calling_introduces, code = E0772)] +#[diag("{$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$lifetime_kind -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement", code = E0772)] pub struct ButCallingIntroduces { - #[label(trait_selection_label1)] + #[label( + "{$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` + }" + )] pub param_ty_span: Span, #[primary_span] - #[label(trait_selection_label2)] + #[label("...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> + [true] `impl` of `{$impl_path}` + *[false] inherent `impl` + }")] pub cause_span: Span, pub has_param_name: bool, @@ -1087,32 +1333,61 @@ pub struct ReqIntroducedLocations { impl Subdiagnostic for ReqIntroducedLocations { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { for sp in self.spans { - self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here); + self.span.push_span_label(sp, inline_fluent!("`'static` requirement introduced here")); } if self.add_label { - self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by); + self.span.push_span_label( + self.fn_decl_span, + inline_fluent!("requirement introduced by this return type"), + ); } - self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of); - let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by); + self.span.push_span_label( + self.cause_span, + inline_fluent!("because of this returned expression"), + ); + let msg = diag.eagerly_translate(inline_fluent!( + "\"`'static` lifetime requirement introduced by the return type" + )); diag.span_note(self.span, msg); } } #[derive(Diagnostic)] -#[diag(trait_selection_but_needs_to_satisfy, code = E0759)] +#[diag("{$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but it needs to satisfy a `'static` lifetime requirement", code = E0759)] pub struct ButNeedsToSatisfy { #[primary_span] pub sp: Span, - #[label(trait_selection_influencer)] + #[label( + "this data with {$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` + }..." + )] pub influencer_point: Span, - #[label(trait_selection_used_here)] + #[label("...is used here...")] pub spans: Vec, - #[label(trait_selection_require)] + #[label( + "{$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + }" + )] pub require_span_as_label: Option, - #[note(trait_selection_require)] + #[note( + "{$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + }" + )] pub require_span_as_note: Option, - #[note(trait_selection_introduced_by_bound)] + #[note("`'static` lifetime requirement introduced by this bound")] pub bound: Option, pub has_param_name: bool, @@ -1123,7 +1398,7 @@ pub struct ButNeedsToSatisfy { } #[derive(Diagnostic)] -#[diag(trait_selection_outlives_content, code = E0312)] +#[diag("lifetime of reference outlives lifetime of borrowed content...", code = E0312)] pub struct OutlivesContent<'a> { #[primary_span] pub span: Span, @@ -1132,7 +1407,7 @@ pub struct OutlivesContent<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_outlives_bound, code = E0476)] +#[diag("lifetime of the source pointer does not outlive lifetime bound of the object type", code = E0476)] pub struct OutlivesBound<'a> { #[primary_span] pub span: Span, @@ -1141,7 +1416,7 @@ pub struct OutlivesBound<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_fulfill_req_lifetime, code = E0477)] +#[diag("the type `{$ty}` does not fulfill the required lifetime", code = E0477)] pub struct FulfillReqLifetime<'a> { #[primary_span] pub span: Span, @@ -1151,7 +1426,7 @@ pub struct FulfillReqLifetime<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)] +#[diag("lifetime bound not satisfied", code = E0478)] pub struct LfBoundNotSatisfied<'a> { #[primary_span] pub span: Span, @@ -1160,7 +1435,7 @@ pub struct LfBoundNotSatisfied<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_ref_longer_than_data, code = E0491)] +#[diag("in type `{$ty}`, reference has a longer lifetime than the data it references", code = E0491)] pub struct RefLongerThanData<'a> { #[primary_span] pub span: Span, @@ -1172,7 +1447,7 @@ pub struct RefLongerThanData<'a> { #[derive(Subdiagnostic)] pub enum WhereClauseSuggestions { #[suggestion( - trait_selection_where_remove, + "remove the `where` clause", code = "", applicability = "machine-applicable", style = "verbose" @@ -1182,7 +1457,7 @@ pub enum WhereClauseSuggestions { span: Span, }, #[suggestion( - trait_selection_where_copy_predicates, + "copy the `where` clause predicates from the trait", code = "{space}where {trait_predicates}", applicability = "machine-applicable", style = "verbose" @@ -1198,7 +1473,7 @@ pub enum WhereClauseSuggestions { #[derive(Subdiagnostic)] pub enum SuggestRemoveSemiOrReturnBinding { #[multipart_suggestion( - trait_selection_srs_remove_and_box, + "consider removing this semicolon and boxing the expressions", applicability = "machine-applicable" )] RemoveAndBox { @@ -1214,7 +1489,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { sp: Span, }, #[suggestion( - trait_selection_srs_remove, + "consider removing this semicolon", style = "short", code = "", applicability = "machine-applicable" @@ -1224,7 +1499,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { sp: Span, }, #[suggestion( - trait_selection_srs_add, + "consider returning the local binding `{$ident}`", style = "verbose", code = "{code}", applicability = "maybe-incorrect" @@ -1235,7 +1510,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { code: String, ident: Ident, }, - #[note(trait_selection_srs_add_one)] + #[note("consider returning one of these bindings")] AddOne { #[primary_span] spans: MultiSpan, @@ -1244,9 +1519,12 @@ pub enum SuggestRemoveSemiOrReturnBinding { #[derive(Subdiagnostic)] pub enum ConsiderAddingAwait { - #[help(trait_selection_await_both_futures)] + #[help("consider `await`ing on both `Future`s")] BothFuturesHelp, - #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "consider `await`ing on both `Future`s", + applicability = "maybe-incorrect" + )] BothFuturesSugg { #[suggestion_part(code = ".await")] first: Span, @@ -1254,7 +1532,7 @@ pub enum ConsiderAddingAwait { second: Span, }, #[suggestion( - trait_selection_await_future, + "consider `await`ing on the `Future`", code = ".await", style = "verbose", applicability = "maybe-incorrect" @@ -1263,13 +1541,13 @@ pub enum ConsiderAddingAwait { #[primary_span] span: Span, }, - #[note(trait_selection_await_note)] + #[note("calling an async function returns a future")] FutureSuggNote { #[primary_span] span: Span, }, #[multipart_suggestion( - trait_selection_await_future, + "consider `await`ing on the `Future`", style = "verbose", applicability = "maybe-incorrect" )] @@ -1281,69 +1559,79 @@ pub enum ConsiderAddingAwait { #[derive(Diagnostic)] pub enum PlaceholderRelationLfNotSatisfied { - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasBoth { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_with_sub)] + #[note("the lifetime `{$sub_symbol}` defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_with_sup)] + #[note("...must outlive the lifetime `{$sup_symbol}` defined here")] sup_span: Span, sub_symbol: Symbol, sup_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasSub { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_with_sub)] + #[note("the lifetime `{$sub_symbol}` defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_without_sup)] + #[note("...must outlive the lifetime defined here")] sup_span: Span, sub_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasSup { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_without_sub)] + #[note("the lifetime defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_with_sup)] + #[note("...must outlive the lifetime `{$sup_symbol}` defined here")] sup_span: Span, sup_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasNone { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_without_sub)] + #[note("the lifetime defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_without_sup)] + #[note("...must outlive the lifetime defined here")] sup_span: Span, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] OnlyPrimarySpan { #[primary_span] span: Span, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, } #[derive(Diagnostic)] -#[diag(trait_selection_opaque_captures_lifetime, code = E0700)] +#[diag("hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds", code = E0700)] pub struct OpaqueCapturesLifetime<'tcx> { #[primary_span] pub span: Span, - #[label] + #[label("opaque type defined here")] pub opaque_ty_span: Span, pub opaque_ty: Ty<'tcx>, } @@ -1351,7 +1639,7 @@ pub struct OpaqueCapturesLifetime<'tcx> { #[derive(Subdiagnostic)] pub enum FunctionPointerSuggestion<'a> { #[suggestion( - trait_selection_fps_use_ref, + "consider using a reference", code = "&", style = "verbose", applicability = "maybe-incorrect" @@ -1361,7 +1649,7 @@ pub enum FunctionPointerSuggestion<'a> { span: Span, }, #[suggestion( - trait_selection_fps_remove_ref, + "consider removing the reference", code = "{fn_name}", style = "verbose", applicability = "maybe-incorrect" @@ -1373,7 +1661,7 @@ pub enum FunctionPointerSuggestion<'a> { fn_name: String, }, #[suggestion( - trait_selection_fps_cast, + "consider casting to a fn pointer", code = "&({fn_name} as {sig})", style = "verbose", applicability = "maybe-incorrect" @@ -1387,7 +1675,7 @@ pub enum FunctionPointerSuggestion<'a> { sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast, + "consider casting to a fn pointer", code = " as {sig}", style = "verbose", applicability = "maybe-incorrect" @@ -1399,7 +1687,7 @@ pub enum FunctionPointerSuggestion<'a> { sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast_both, + "consider casting both fn items to fn pointers using `as {$expected_sig}`", code = " as {found_sig}", style = "hidden", applicability = "maybe-incorrect" @@ -1412,7 +1700,7 @@ pub enum FunctionPointerSuggestion<'a> { expected_sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast_both, + "consider casting both fn items to fn pointers using `as {$expected_sig}`", code = "&({fn_name} as {found_sig})", style = "hidden", applicability = "maybe-incorrect" @@ -1429,21 +1717,21 @@ pub enum FunctionPointerSuggestion<'a> { } #[derive(Subdiagnostic)] -#[note(trait_selection_fps_items_are_distinct)] +#[note("fn items are distinct from fn pointers")] pub struct FnItemsAreDistinct; #[derive(Subdiagnostic)] -#[note(trait_selection_fn_uniq_types)] +#[note("different fn items have unique types, even if their signatures are the same")] pub struct FnUniqTypes; #[derive(Subdiagnostic)] -#[help(trait_selection_fn_consider_casting)] +#[help("consider casting the fn item to a fn pointer: `{$casting}`")] pub struct FnConsiderCasting { pub casting: String, } #[derive(Subdiagnostic)] -#[help(trait_selection_fn_consider_casting_both)] +#[help("consider casting both fn items to fn pointers using `as {$sig}`")] pub struct FnConsiderCastingBoth<'a> { pub sig: Binder<'a, FnSig<'a>>, } @@ -1451,7 +1739,7 @@ pub struct FnConsiderCastingBoth<'a> { #[derive(Subdiagnostic)] pub enum SuggestAccessingField<'a> { #[suggestion( - trait_selection_suggest_accessing_field, + "you might have meant to use field `{$name}` whose type is `{$ty}`", code = "{snippet}.{name}", applicability = "maybe-incorrect", style = "verbose" @@ -1464,7 +1752,7 @@ pub enum SuggestAccessingField<'a> { ty: Ty<'a>, }, #[suggestion( - trait_selection_suggest_accessing_field, + "you might have meant to use field `{$name}` whose type is `{$ty}`", code = "unsafe {{ {snippet}.{name} }}", applicability = "maybe-incorrect", style = "verbose" @@ -1479,7 +1767,10 @@ pub enum SuggestAccessingField<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "try wrapping the pattern in `{$variant}`", + applicability = "maybe-incorrect" +)] pub struct SuggestTuplePatternOne { pub variant: String, #[suggestion_part(code = "{variant}(")] @@ -1497,7 +1788,9 @@ pub struct SuggestTuplePatternMany { impl Subdiagnostic for SuggestTuplePatternMany { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("path", self.path); - let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many); + let message = diag.eagerly_translate(inline_fluent!( + "try wrapping the pattern in a variant of `{$path}`" + )); diag.multipart_suggestions( message, self.compatible_variants.into_iter().map(|variant| { @@ -1514,7 +1807,7 @@ impl Subdiagnostic for SuggestTuplePatternMany { #[derive(Subdiagnostic)] pub enum TypeErrorAdditionalDiags { #[suggestion( - trait_selection_meant_byte_literal, + "if you meant to write a byte literal, prefix with `b`", code = "b'{code}'", applicability = "machine-applicable" )] @@ -1524,7 +1817,7 @@ pub enum TypeErrorAdditionalDiags { code: String, }, #[suggestion( - trait_selection_meant_char_literal, + "if you meant to write a `char` literal, use single quotes", code = "'{code}'", applicability = "machine-applicable" )] @@ -1533,7 +1826,10 @@ pub enum TypeErrorAdditionalDiags { span: Span, code: String, }, - #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")] + #[multipart_suggestion( + "if you meant to write a string literal, use double quotes", + applicability = "machine-applicable" + )] MeantStrLiteral { #[suggestion_part(code = "\"")] start: Span, @@ -1541,7 +1837,7 @@ pub enum TypeErrorAdditionalDiags { end: Span, }, #[suggestion( - trait_selection_consider_specifying_length, + "consider specifying the actual array length", code = "{length}", applicability = "maybe-incorrect" )] @@ -1550,10 +1846,10 @@ pub enum TypeErrorAdditionalDiags { span: Span, length: u64, }, - #[note(trait_selection_try_cannot_convert)] + #[note("`?` operator cannot convert from `{$found}` to `{$expected}`")] TryCannotConvert { found: String, expected: String }, #[suggestion( - trait_selection_tuple_trailing_comma, + "use a trailing comma to create a tuple with one element", code = ",", applicability = "machine-applicable" )] @@ -1562,7 +1858,7 @@ pub enum TypeErrorAdditionalDiags { span: Span, }, #[multipart_suggestion( - trait_selection_tuple_trailing_comma, + "use a trailing comma to create a tuple with one element", applicability = "machine-applicable" )] TupleAlsoParentheses { @@ -1572,7 +1868,7 @@ pub enum TypeErrorAdditionalDiags { span_high: Span, }, #[suggestion( - trait_selection_suggest_add_let_for_letchains, + "consider adding `let`", style = "verbose", applicability = "machine-applicable", code = "let " @@ -1585,66 +1881,69 @@ pub enum TypeErrorAdditionalDiags { #[derive(Diagnostic)] pub enum ObligationCauseFailureCode { - #[diag(trait_selection_oc_method_compat, code = E0308)] + #[diag("method not compatible with trait", code = E0308)] MethodCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_type_compat, code = E0308)] + #[diag("type not compatible with trait", code = E0308)] TypeCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_const_compat, code = E0308)] + #[diag("const not compatible with trait", code = E0308)] ConstCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_try_compat, code = E0308)] + #[diag("`?` operator has incompatible types", code = E0308)] TryCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_match_compat, code = E0308)] + #[diag("`match` arms have incompatible types", code = E0308)] MatchCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_if_else_different, code = E0308)] + #[diag("`if` and `else` have incompatible types", code = E0308)] IfElseDifferent { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_no_else, code = E0317)] + #[diag("`if` may be missing an `else` clause", code = E0317)] NoElse { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_no_diverge, code = E0308)] + #[diag("`else` clause of `let...else` does not diverge", code = E0308)] NoDiverge { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)] + #[diag("`main` function has wrong type", code = E0580)] FnMainCorrectType { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)] + #[diag("{$lang_item_name -> +[panic_impl] `#[panic_handler]` +*[lang_item_name] lang item `{$lang_item_name}` +} function has wrong type", code = E0308)] FnLangCorrectType { #[primary_span] span: Span, @@ -1652,40 +1951,40 @@ pub enum ObligationCauseFailureCode { subdiags: Vec, lang_item_name: Symbol, }, - #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)] + #[diag("intrinsic has wrong type", code = E0308)] IntrinsicCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_method_correct_type, code = E0308)] + #[diag("mismatched `self` parameter type", code = E0308)] MethodCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_closure_selfref, code = E0644)] + #[diag("closure/coroutine type that references itself", code = E0644)] ClosureSelfref { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_cant_coerce_force_inline, code = E0308)] + #[diag("cannot coerce functions which must be inlined to function pointers", code = E0308)] CantCoerceForceInline { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_cant_coerce_intrinsic, code = E0308)] + #[diag("cannot coerce intrinsics to function pointers", code = E0308)] CantCoerceIntrinsic { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_generic, code = E0308)] + #[diag("mismatched types", code = E0308)] Generic { #[primary_span] span: Span, @@ -1697,7 +1996,7 @@ pub enum ObligationCauseFailureCode { #[derive(Subdiagnostic)] pub enum AddPreciseCapturing { #[suggestion( - trait_selection_precise_capturing_new, + "add a `use<...>` bound to explicitly capture `{$new_lifetime}`", style = "verbose", code = " + use<{concatenated_bounds}>", applicability = "machine-applicable" @@ -1709,7 +2008,7 @@ pub enum AddPreciseCapturing { concatenated_bounds: String, }, #[suggestion( - trait_selection_precise_capturing_existing, + "add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it", style = "verbose", code = "{pre}{new_lifetime}{post}", applicability = "machine-applicable" @@ -1733,13 +2032,13 @@ impl Subdiagnostic for AddPreciseCapturingAndParams { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("new_lifetime", self.new_lifetime); diag.multipart_suggestion_verbose( - fluent::trait_selection_precise_capturing_new_but_apit, + inline_fluent!("add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate"), self.suggs, Applicability::MaybeIncorrect, ); diag.span_note( self.apit_spans, - fluent::trait_selection_warn_removing_apit_params_for_undercapture, + inline_fluent!("you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable"), ); } } @@ -1880,26 +2179,31 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture { Applicability::MaybeIncorrect }; diag.multipart_suggestion_verbose( - fluent::trait_selection_precise_capturing_overcaptures, + inline_fluent!( + "use the precise capturing `use<...>` syntax to make the captures explicit" + ), self.suggs, applicability, ); if !self.apit_spans.is_empty() { diag.span_note( self.apit_spans, - fluent::trait_selection_warn_removing_apit_params_for_overcapture, + inline_fluent!("you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable"), ); } } } #[derive(Diagnostic)] -#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)] +#[diag("expected generic {$kind} parameter, found `{$arg}`", code = E0792)] pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { pub arg: GenericArg<'tcx>, pub kind: &'a str, #[primary_span] pub span: Span, - #[label] + #[label("{STREQ($arg, \"'static\") -> + [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type + *[other] this generic parameter must be used with a generic {$kind} parameter + }")] pub param_span: Span, } diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 3471036256db7..8e86b8fae1577 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -1,11 +1,10 @@ -use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic, inline_fluent}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Span, kw}; use crate::error_reporting::infer::nice_region_error::find_anon_type; -use crate::fluent_generated as fluent; struct DescriptionCtx<'a> { span: Option, @@ -170,7 +169,40 @@ impl Subdiagnostic for RegionExplanation<'_> { diag.arg("desc_kind", self.desc.kind); diag.arg("desc_arg", self.desc.arg); - let msg = diag.eagerly_translate(fluent::trait_selection_region_explanation); + let msg = diag.eagerly_translate(inline_fluent!( + "{$pref_kind -> +*[should_not_happen] [{$pref_kind}] +[ref_valid_for] ...the reference is valid for +[content_valid_for] ...but the borrowed content is only valid for +[type_obj_valid_for] object type is valid for +[source_pointer_valid_for] source pointer is only valid for +[type_satisfy] type must satisfy +[type_outlive] type must outlive +[lf_param_instantiated_with] lifetime parameter instantiated with +[lf_param_must_outlive] but lifetime parameter must outlive +[lf_instantiated_with] lifetime instantiated with +[lf_must_outlive] but lifetime must outlive +[pointer_valid_for] the pointer is valid for +[data_valid_for] but the referenced data is only valid for +[empty] {\"\"} +}{$pref_kind -> +[empty] {\"\"} +*[other] {\" \"} +}{$desc_kind -> +*[should_not_happen] [{$desc_kind}] +[restatic] the static lifetime +[revar] lifetime {$desc_arg} +[as_defined] the lifetime `{$desc_arg}` as defined here +[as_defined_anon] the anonymous lifetime as defined here +[defined_here] the anonymous lifetime defined here +[defined_here_reg] the lifetime `{$desc_arg}` as defined here +}{$suff_kind -> +*[should_not_happen] [{$suff_kind}] +[empty]{\"\"} +[continues] ... +[req_by_binding] {\" \"}as required by this binding +}" + )); diag.restore_args(); if let Some(span) = self.desc.span { diag.span_note(span, msg); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 561a95bad50c3..645fd17ac7096 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -34,5 +34,3 @@ pub mod opaque_types; pub mod regions; pub mod solve; pub mod traits; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 24854990fe716..46d95fdfabfed 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -1,6 +1,7 @@ //! Deeply normalize types using the old trait solver. use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::inline_fluent; use rustc_hir::def::DefKind; use rustc_infer::infer::at::At; use rustc_infer::infer::{InferCtxt, InferOk}; @@ -294,7 +295,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { self.cause.span, false, |diag| { - diag.note(crate::fluent_generated::trait_selection_ty_alias_overflow); + diag.note(inline_fluent!("in case this is a recursive type alias, consider using a struct, enum, or union instead")); }, ); } From a2f9dec29cfd8a0fc1b76f5ffbf7803a904c1017 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Thu, 5 Feb 2026 19:04:44 +0000 Subject: [PATCH 47/47] Parse #[rustc_abi(..)] --- .../src/attributes/test_attrs.rs | 50 +++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 11 + .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/abi_test.rs | 193 +++++++++--------- compiler/rustc_passes/src/check_attr.rs | 2 +- tests/ui/abi/debug.generic.stderr | 44 +++- tests/ui/abi/debug.loongarch64.stderr | 44 +++- tests/ui/abi/debug.riscv64.stderr | 44 +++- tests/ui/abi/debug.rs | 10 +- 10 files changed, 276 insertions(+), 124 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 236d10d77b92a..908941c2b3358 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -1,3 +1,4 @@ +use rustc_hir::attrs::RustcAbiAttrKind; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use super::prelude::*; @@ -140,3 +141,52 @@ impl SingleAttributeParser for ReexportTestHarnessMainParser { Some(AttributeKind::ReexportTestHarnessMain(name)) } } + +pub(crate) struct RustcAbiParser; + +impl SingleAttributeParser for RustcAbiParser { + const PATH: &[Symbol] = &[sym::rustc_abi]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::debug, sym::assert_eq]); + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::TyAlias), + Allow(Target::Fn), + Allow(Target::ForeignFn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(args) = args.list() else { + cx.expected_specific_argument_and_list(cx.attr_span, &[sym::assert_eq, sym::debug]); + return None; + }; + + let Some(arg) = args.single() else { + cx.expected_single_argument(cx.attr_span); + return None; + }; + + let fail_incorrect_argument = + |span| cx.expected_specific_argument(span, &[sym::assert_eq, sym::debug]); + + let Some(arg) = arg.meta_item() else { + fail_incorrect_argument(args.span); + return None; + }; + + let kind: RustcAbiAttrKind = match arg.path().word_sym() { + Some(sym::assert_eq) => RustcAbiAttrKind::AssertEq, + Some(sym::debug) => RustcAbiAttrKind::Debug, + None | Some(_) => { + fail_incorrect_argument(arg.span()); + return None; + } + }; + + Some(AttributeKind::RustcAbi { attr_span: cx.attr_span, kind }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5abf299ec618c..6259a90ea3f33 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -191,6 +191,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index a444b5e4badf5..2a3adbd77e6e7 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -167,6 +167,14 @@ pub enum CoverageAttrKind { Off, } +/// Successfully-parsed value of a `#[rustc_abi(..)]` attribute. +#[derive(Copy, Debug, Eq, PartialEq, Encodable, Decodable, Clone)] +#[derive(HashStable_Generic, PrintAttribute)] +pub enum RustcAbiAttrKind { + Debug, + AssertEq, +} + impl Deprecation { /// Whether an item marked with #[deprecated(since = "X")] is currently /// deprecated (i.e., whether X is not greater than the current rustc @@ -1015,6 +1023,9 @@ pub enum AttributeKind { /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span }, + /// Represents `#[rustc_abi(..)]` + RustcAbi { attr_span: Span, kind: RustcAbiAttrKind }, + /// Represents `#[rustc_allocator]` RustcAllocator, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index b6249e1e2ec2c..6a529cae5f199 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -89,6 +89,7 @@ impl AttributeKind { RecursionLimit { .. } => No, ReexportTestHarnessMain(..) => No, Repr { .. } => No, + RustcAbi { .. } => No, RustcAllocator => No, RustcAllocatorZeroed => No, RustcAllocatorZeroedVariant { .. } => Yes, diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 0ac42f03eb2f5..c3e80208e2d5f 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -1,11 +1,12 @@ -use rustc_hir::Attribute; +use rustc_hir::attrs::{AttributeKind, RustcAbiAttrKind}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::span_bug; use rustc_middle::ty::layout::{FnAbiError, LayoutError}; use rustc_middle::ty::{self, GenericArgs, Instance, Ty, TyCtxt}; +use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_span::sym; use rustc_target::callconv::FnAbi; use super::layout_test::ensure_wf; @@ -17,17 +18,19 @@ pub fn test_abi(tcx: TyCtxt<'_>) { return; } for id in tcx.hir_crate_items(()).definitions() { - for attr in tcx.get_attrs(id, sym::rustc_abi) { - match tcx.def_kind(id) { - DefKind::Fn | DefKind::AssocFn => { - dump_abi_of_fn_item(tcx, id, attr); - } - DefKind::TyAlias => { - dump_abi_of_fn_type(tcx, id, attr); - } - _ => { - tcx.dcx().emit_err(AbiInvalidAttribute { span: tcx.def_span(id) }); - } + let Some((attr_span, attr_kind)) = find_attr!(tcx.get_all_attrs(id), AttributeKind::RustcAbi{ attr_span, kind } => (*attr_span, *kind)) + else { + continue; + }; + match tcx.def_kind(id) { + DefKind::Fn | DefKind::AssocFn => { + dump_abi_of_fn_item(tcx, id, attr_span, attr_kind); + } + DefKind::TyAlias => { + dump_abi_of_fn_type(tcx, id, attr_span, attr_kind); + } + _ => { + tcx.dcx().emit_err(AbiInvalidAttribute { span: tcx.def_span(id) }); } } } @@ -49,7 +52,12 @@ fn unwrap_fn_abi<'tcx>( } } -fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { +fn dump_abi_of_fn_item( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + attr_span: Span, + attr_kind: RustcAbiAttrKind, +) { let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let args = GenericArgs::identity_for_item(tcx, item_def_id); let instance = match Instance::try_resolve(tcx, typing_env, item_def_id.into(), args) { @@ -75,22 +83,18 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut // Check out the `#[rustc_abi(..)]` attribute to tell what to dump. // The `..` are the names of fields to dump. - let meta_items = attr.meta_item_list().unwrap_or_default(); - for meta_item in meta_items { - match meta_item.name() { - Some(sym::debug) => { - let fn_name = tcx.item_name(item_def_id); - tcx.dcx().emit_err(AbiOf { - span: tcx.def_span(item_def_id), - fn_name, - // FIXME: using the `Debug` impl here isn't ideal. - fn_abi: format!("{:#?}", abi), - }); - } - - _ => { - tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); - } + match attr_kind { + RustcAbiAttrKind::Debug => { + let fn_name = tcx.item_name(item_def_id); + tcx.dcx().emit_err(AbiOf { + span: tcx.def_span(item_def_id), + fn_name, + // FIXME: using the `Debug` impl here isn't ideal. + fn_abi: format!("{:#?}", abi), + }); + } + _ => { + tcx.dcx().emit_err(UnrecognizedArgument { span: attr_span }); } } } @@ -109,24 +113,29 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx, && abi1.args.iter().zip(abi2.args.iter()).all(|(arg1, arg2)| arg1.eq_abi(arg2)) } -fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { +fn dump_abi_of_fn_type( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + attr_span: Span, + attr_kind: RustcAbiAttrKind, +) { let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id); if !ensure_wf(tcx, typing_env, ty, item_def_id, span) { return; } - let meta_items = attr.meta_item_list().unwrap_or_default(); - for meta_item in meta_items { - match meta_item.name() { - Some(sym::debug) => { - let ty::FnPtr(sig_tys, hdr) = ty.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(debug)]` on a type alias requires function pointer type" - ); - }; - let abi = unwrap_fn_abi( + + match attr_kind { + RustcAbiAttrKind::Debug => { + let ty::FnPtr(sig_tys, hdr) = ty.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(debug)]` on a type alias requires function pointer type" + ); + }; + let abi = + unwrap_fn_abi( tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( sig_tys.with(*hdr), /* extra_args */ ty::List::empty(), @@ -135,61 +144,57 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut item_def_id, ); - let fn_name = tcx.item_name(item_def_id); - tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) }); - } - Some(sym::assert_eq) => { - let ty::Tuple(fields) = ty.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" - ); - }; - let [field1, field2] = ***fields else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" - ); - }; - let ty::FnPtr(sig_tys1, hdr1) = field1.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" - ); - }; - let abi1 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( - sig_tys1.with(*hdr1), - /* extra_args */ ty::List::empty(), - ))), - tcx, - item_def_id, + let fn_name = tcx.item_name(item_def_id); + tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) }); + } + RustcAbiAttrKind::AssertEq => { + let ty::Tuple(fields) = ty.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" ); - let ty::FnPtr(sig_tys2, hdr2) = field2.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" - ); - }; - let abi2 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( - sig_tys2.with(*hdr2), - /* extra_args */ ty::List::empty(), - ))), - tcx, - item_def_id, + }; + let [field1, field2] = ***fields else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" + ); + }; + let ty::FnPtr(sig_tys1, hdr1) = field1.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" ); + }; + let abi1 = unwrap_fn_abi( + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys1.with(*hdr1), + /* extra_args */ ty::List::empty(), + ))), + tcx, + item_def_id, + ); + let ty::FnPtr(sig_tys2, hdr2) = field2.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" + ); + }; + let abi2 = unwrap_fn_abi( + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys2.with(*hdr2), + /* extra_args */ ty::List::empty(), + ))), + tcx, + item_def_id, + ); - if !test_abi_eq(abi1, abi2) { - tcx.dcx().emit_err(AbiNe { - span, - left: format!("{:#?}", abi1), - right: format!("{:#?}", abi2), - }); - } - } - _ => { - tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); + if !test_abi_eq(abi1, abi2) { + tcx.dcx().emit_err(AbiNe { + span, + left: format!("{:#?}", abi1), + right: format!("{:#?}", abi2), + }); } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0d64e30d9c79e..27398d4a9ac44 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -287,6 +287,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::ReexportTestHarnessMain(..) // handled below this loop and elsewhere | AttributeKind::Repr { .. } + | AttributeKind::RustcAbi { .. } | AttributeKind::RustcAllocator | AttributeKind::RustcAllocatorZeroed | AttributeKind::RustcAllocatorZeroedVariant { .. } @@ -392,7 +393,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_conversion_suggestion | sym::rustc_deprecated_safe_2024 | sym::rustc_test_marker - | sym::rustc_abi | sym::rustc_layout | sym::rustc_proc_macro_decls | sym::rustc_never_type_options diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 8a031b79780a8..b154c3fa201e5 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -1,3 +1,36 @@ +error: `#[rustc_abi]` attribute cannot be used on constants + --> $DIR/debug.rs:42:1 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error: `#[rustc_abi]` attribute cannot be used on associated consts + --> $DIR/debug.rs:46:5 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error[E0539]: malformed `rustc_abi` attribute input + --> $DIR/debug.rs:74:1 + | +LL | #[rustc_abi("assert_eq")] + | ^^^^^^^^^^^-------------^ + | | + | valid arguments are `assert_eq` or `debug` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(assert_eq)] + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(debug)] + | + error: fn_abi_of(test) = FnAbi { args: [ ArgAbi { @@ -884,12 +917,6 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type -error: unrecognized argument - --> $DIR/debug.rs:74:13 - | -LL | #[rustc_abi("assert_eq")] - | ^^^^^^^^^^^ - error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions --> $DIR/debug.rs:47:5 | @@ -986,6 +1013,7 @@ error: fn_abi_of(assoc_test) = FnAbi { LL | fn assoc_test(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0539. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index 00bd3febde4ec..68bcd736e47ce 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -1,3 +1,36 @@ +error: `#[rustc_abi]` attribute cannot be used on constants + --> $DIR/debug.rs:42:1 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error: `#[rustc_abi]` attribute cannot be used on associated consts + --> $DIR/debug.rs:46:5 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error[E0539]: malformed `rustc_abi` attribute input + --> $DIR/debug.rs:74:1 + | +LL | #[rustc_abi("assert_eq")] + | ^^^^^^^^^^^-------------^ + | | + | valid arguments are `assert_eq` or `debug` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(assert_eq)] + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(debug)] + | + error: fn_abi_of(test) = FnAbi { args: [ ArgAbi { @@ -884,12 +917,6 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type -error: unrecognized argument - --> $DIR/debug.rs:74:13 - | -LL | #[rustc_abi("assert_eq")] - | ^^^^^^^^^^^ - error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions --> $DIR/debug.rs:47:5 | @@ -986,6 +1013,7 @@ error: fn_abi_of(assoc_test) = FnAbi { LL | fn assoc_test(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0539. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index 00bd3febde4ec..68bcd736e47ce 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -1,3 +1,36 @@ +error: `#[rustc_abi]` attribute cannot be used on constants + --> $DIR/debug.rs:42:1 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error: `#[rustc_abi]` attribute cannot be used on associated consts + --> $DIR/debug.rs:46:5 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error[E0539]: malformed `rustc_abi` attribute input + --> $DIR/debug.rs:74:1 + | +LL | #[rustc_abi("assert_eq")] + | ^^^^^^^^^^^-------------^ + | | + | valid arguments are `assert_eq` or `debug` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(assert_eq)] + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(debug)] + | + error: fn_abi_of(test) = FnAbi { args: [ ArgAbi { @@ -884,12 +917,6 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type -error: unrecognized argument - --> $DIR/debug.rs:74:13 - | -LL | #[rustc_abi("assert_eq")] - | ^^^^^^^^^^^ - error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions --> $DIR/debug.rs:47:5 | @@ -986,6 +1013,7 @@ error: fn_abi_of(assoc_test) = FnAbi { LL | fn assoc_test(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0539. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/abi/debug.rs b/tests/ui/abi/debug.rs index 2e34fa5d7df42..42ea14ec51d07 100644 --- a/tests/ui/abi/debug.rs +++ b/tests/ui/abi/debug.rs @@ -39,12 +39,12 @@ type TestFnPtr = fn(bool) -> u8; //~ ERROR: fn_abi #[rustc_abi(debug)] fn test_generic(_x: *const T) {} //~ ERROR: fn_abi -#[rustc_abi(debug)] -const C: () = (); //~ ERROR: can only be applied to +#[rustc_abi(debug)] //~ ERROR: `#[rustc_abi]` attribute cannot be used on constants +const C: () = (); //~ ERROR: `#[rustc_abi]` can only be applied to impl S { - #[rustc_abi(debug)] - const C: () = (); //~ ERROR: can only be applied to + #[rustc_abi(debug)] //~ ERROR: `#[rustc_abi]` attribute cannot be used on assoc + const C: () = (); //~ ERROR: `#[rustc_abi]` can only be applied to } impl S { @@ -71,5 +71,5 @@ type TestAbiNeSign = (fn(i32), fn(u32)); //~ ERROR: ABIs are not compatible #[rustc_abi(assert_eq)] type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time -#[rustc_abi("assert_eq")] //~ ERROR unrecognized argument +#[rustc_abi("assert_eq")] //~ ERROR malformed `rustc_abi` attribute input type Bad = u32;