From 75d8687f2b6ac1e73071450cb57c4157fcba53b4 Mon Sep 17 00:00:00 2001 From: Valdemar Erk Date: Sat, 23 Aug 2025 11:37:53 +0200 Subject: [PATCH 01/13] add span to struct pattern rest (..) --- compiler/rustc_ast/src/ast.rs | 6 +++--- compiler/rustc_ast_lowering/src/expr.rs | 6 +++--- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_ast_lowering/src/pat.rs | 9 +++++---- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_hir/src/hir.rs | 8 ++++---- compiler/rustc_hir_pretty/src/lib.rs | 4 ++-- compiler/rustc_hir_typeck/src/pat.rs | 12 +++++++++-- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_passes/src/liveness.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- .../clippy_lints/src/equatable_if_let.rs | 2 +- .../clippy_lints/src/manual_let_else.rs | 4 ++-- .../matches/rest_pat_in_fully_bound_struct.rs | 2 +- .../clippy/clippy_lints/src/utils/author.rs | 3 ++- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- src/tools/rustfmt/src/patterns.rs | 2 +- tests/ui/stats/input-stats.stderr | 20 +++++++++---------- 18 files changed, 50 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index de3e0e0c87f5a..802a6fa324984 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -937,7 +937,7 @@ pub enum PatKind { #[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Walkable)] pub enum PatFieldsRest { /// `module::StructName { field, ..}` - Rest, + Rest(Span), /// `module::StructName { field, syntax error }` Recovered(ErrorGuaranteed), /// `module::StructName { field }` @@ -4051,8 +4051,8 @@ mod size_asserts { static_assert_size!(Local, 96); static_assert_size!(MetaItemLit, 40); static_assert_size!(Param, 40); - static_assert_size!(Pat, 72); - static_assert_size!(PatKind, 48); + static_assert_size!(Pat, 80); + static_assert_size!(PatKind, 56); static_assert_size!(Path, 24); static_assert_size!(PathSegment, 24); static_assert_size!(Stmt, 32); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index cbd17d66b7548..3674814b796c2 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1434,10 +1434,10 @@ impl<'hir> LoweringContext<'_, 'hir> { self.dcx().emit_err(FunctionalRecordUpdateDestructuringAssignment { span: e.span, }); - true + Some(self.lower_span(e.span)) } - StructRest::Rest(_) => true, - StructRest::None => false, + StructRest::Rest(span) => Some(self.lower_span(*span)), + StructRest::None => None, }; let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted); return self.pat_without_dbm(lhs.span, struct_pat); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 70595391b85bc..137207bde1f12 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2508,7 +2508,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fields: &'hir [hir::PatField<'hir>], ) -> &'hir hir::Pat<'hir> { let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span)); - self.pat(span, hir::PatKind::Struct(qpath, fields, false)) + self.pat(span, hir::PatKind::Struct(qpath, fields, None)) } fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index b8f8624787565..ed159f37051c1 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -106,10 +106,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { break hir::PatKind::Struct( qpath, fs, - matches!( - etc, - ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) - ), + match etc { + ast::PatFieldsRest::Rest(sp) => Some(self.lower_span(*sp)), + ast::PatFieldsRest::Recovered(_) => Some(Span::default()), + _ => None, + }, ); } PatKind::Tuple(pats) => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a056ce3e29d28..41b520b04c993 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1769,7 +1769,7 @@ impl<'a> State<'a> { }, |f| f.pat.span, ); - if let ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) = etc { + if let ast::PatFieldsRest::Rest(_) | ast::PatFieldsRest::Recovered(_) = etc { if !fields.is_empty() { self.word_space(","); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e397c286de289..e3c27c73638c1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1884,8 +1884,8 @@ pub enum PatKind<'hir> { Binding(BindingMode, HirId, Ident, Option<&'hir Pat<'hir>>), /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). - /// The `bool` is `true` in the presence of a `..`. - Struct(QPath<'hir>, &'hir [PatField<'hir>], bool), + /// The `Option` contains the span of a possible `..`. + Struct(QPath<'hir>, &'hir [PatField<'hir>], Option), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `DotDotPos` denotes its position. @@ -4979,8 +4979,8 @@ mod size_asserts { static_assert_size!(ItemKind<'_>, 64); static_assert_size!(LetStmt<'_>, 72); static_assert_size!(Param<'_>, 32); - static_assert_size!(Pat<'_>, 72); - static_assert_size!(PatKind<'_>, 48); + static_assert_size!(Pat<'_>, 80); + static_assert_size!(PatKind<'_>, 56); static_assert_size!(Path<'_>, 40); static_assert_size!(PathSegment<'_>, 48); static_assert_size!(QPath<'_>, 24); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index be5859b57c5e0..52b29e05dcb0e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1958,12 +1958,12 @@ impl<'a> State<'a> { self.print_qpath(qpath, true); self.nbsp(); self.word("{"); - let empty = fields.is_empty() && !etc; + let empty = fields.is_empty() && etc.is_none(); if !empty { self.space(); } self.commasep_cmnt(Consistent, fields, |s, f| s.print_patfield(f), |f| f.pat.span); - if etc { + if etc.is_some() { if !fields.is_empty() { self.word_space(","); } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7dc736e5e6b14..f735c0a416099 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -605,7 +605,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, PatKind::Struct(_, fields, has_rest_pat) => match opt_path_res.unwrap() { Ok(ResolvedPat { ty, kind: ResolvedPatKind::Struct { variant } }) => self - .check_pat_struct(pat, fields, has_rest_pat, ty, variant, expected, pat_info), + .check_pat_struct( + pat, + fields, + has_rest_pat.is_some(), + ty, + variant, + expected, + pat_info, + ), Err(guar) => { let ty_err = Ty::new_error(self.tcx, guar); for field in fields { @@ -2428,7 +2436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let len = unmentioned_fields.len(); let (prefix, postfix, sp) = match fields { [] => match &pat.kind { - PatKind::Struct(path, [], false) => { + PatKind::Struct(path, [], None) => { (" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi())) } _ => return err, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 9754691a0b9ca..c4d30b3d32832 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1516,7 +1516,7 @@ impl<'a> Parser<'a> { || self.check_noexpect(&token::DotDotDot) || self.check_keyword(exp!(Underscore)) { - etc = PatFieldsRest::Rest; + etc = PatFieldsRest::Rest(self.token.span); let mut etc_sp = self.token.span; if first_etc_and_maybe_comma_span.is_none() { if let Some(comma_tok) = diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 801a533c94338..ae16a51bc693c 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1583,7 +1583,7 @@ impl<'tcx> Liveness<'_, 'tcx> { }); let can_remove = match pat.kind { - hir::PatKind::Struct(_, fields, true) => { + hir::PatKind::Struct(_, fields, Some(_)) => { // if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix fields.iter().all(|f| f.is_shorthand) } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 679e663f88614..84108f0b8663d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3922,7 +3922,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn record_patterns_with_skipped_bindings(&mut self, pat: &Pat, rest: &ast::PatFieldsRest) { match rest { - ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) => { + ast::PatFieldsRest::Rest(_) | ast::PatFieldsRest::Recovered(_) => { // Record that the pattern doesn't introduce all the bindings it could. if let Some(partial_res) = self.r.partial_res_map.get(&pat.id) && let Some(res) = partial_res.full_res() diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 72f5eaf8a4bcc..c3fc09343dbfe 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -53,7 +53,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { | PatKind::Never | PatKind::Or(_) | PatKind::Err(_) => false, - PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), + PatKind::Struct(_, a, etc) => etc.is_none() && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), PatKind::Ref(x, _) | PatKind::Box(x) | PatKind::Deref(x) | PatKind::Guard(x, _) => unary_pattern(x), PatKind::Expr(_) => true, diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 5a7967bbf9468..2705ef20b795d 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -287,7 +287,7 @@ fn replace_in_pattern( } return or_pat; }, - PatKind::Struct(path, fields, has_dot_dot) => { + PatKind::Struct(path, fields, dot_dot) => { let fields = fields .iter() .map(|fld| { @@ -311,7 +311,7 @@ fn replace_in_pattern( .collect::>(); let fields_string = fields.join(", "); - let dot_dot_str = if has_dot_dot { " .." } else { "" }; + let dot_dot_str = if dot_dot.is_some() { " .." } else { "" }; let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app); return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}"); }, diff --git a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs index 2154cd5b24a54..ae09c2e87d6b7 100644 --- a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs +++ b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs @@ -7,7 +7,7 @@ use super::REST_PAT_IN_FULLY_BOUND_STRUCTS; pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) { if !pat.span.from_expansion() - && let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind + && let PatKind::Struct(QPath::Resolved(_, path), fields, Some(_)) = pat.kind && let Some(def_id) = path.res.opt_def_id() && let ty = cx.tcx.type_of(def_id).instantiate_identity() && let ty::Adt(def, _) = ty.kind() diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 2113cb92137eb..ece29362a39f9 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -754,7 +754,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.ident(name); sub.if_some(|p| self.pat(p)); }, - PatKind::Struct(ref qpath, fields, ignore) => { + PatKind::Struct(ref qpath, fields, etc) => { + let ignore = etc.is_some(); bind!(self, qpath, fields); kind!("Struct(ref {qpath}, {fields}, {ignore})"); self.qpath(qpath, pat); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 8533fa8554199..011c9b2f931ae 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2011,7 +2011,7 @@ pub fn is_expr_identity_of_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr< false } }, - (PatKind::Struct(pat_ident, field_pats, false), ExprKind::Struct(ident, fields, hir::StructTailExpr::None)) + (PatKind::Struct(pat_ident, field_pats, None), ExprKind::Struct(ident, fields, hir::StructTailExpr::None)) if field_pats.len() == fields.len() => { // check ident diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index d212ecf392a7f..848bd0766e786 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -303,7 +303,7 @@ impl Rewrite for Pat { qself, path, fields, - rest == ast::PatFieldsRest::Rest, + matches!(rest, ast::PatFieldsRest::Rest(_)), self.span, context, shape, diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 72a9820bb6431..4a73a4747ad0c 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -23,10 +23,10 @@ ast-stats - Path 72 (NN.N%) 1 ast-stats - Struct 72 (NN.N%) 1 ast-stats - Lit 144 (NN.N%) 2 ast-stats - Block 216 (NN.N%) 3 -ast-stats Pat 504 (NN.N%) 7 72 -ast-stats - Struct 72 (NN.N%) 1 -ast-stats - Wild 72 (NN.N%) 1 -ast-stats - Ident 360 (NN.N%) 5 +ast-stats Pat 560 (NN.N%) 7 80 +ast-stats - Struct 80 (NN.N%) 1 +ast-stats - Wild 80 (NN.N%) 1 +ast-stats - Ident 400 (NN.N%) 5 ast-stats GenericParam 480 (NN.N%) 5 96 ast-stats GenericBound 352 (NN.N%) 4 88 ast-stats - Trait 352 (NN.N%) 4 @@ -57,7 +57,7 @@ ast-stats GenericArgs 40 (NN.N%) 1 40 ast-stats - AngleBracketed 40 (NN.N%) 1 ast-stats Crate 40 (NN.N%) 1 40 ast-stats ---------------------------------------------------------------- -ast-stats Total 7_472 129 +ast-stats Total 7_528 129 ast-stats ================================================================ hir-stats ================================================================ hir-stats HIR STATS: input_stats @@ -85,11 +85,11 @@ hir-stats - Ptr 48 (NN.N%) 1 hir-stats - Ref 48 (NN.N%) 1 hir-stats - Path 624 (NN.N%) 13 hir-stats Generics 560 (NN.N%) 10 56 +hir-stats Pat 400 (NN.N%) 5 80 +hir-stats - Struct 80 (NN.N%) 1 +hir-stats - Wild 80 (NN.N%) 1 +hir-stats - Binding 240 (NN.N%) 3 hir-stats GenericParam 400 (NN.N%) 5 80 -hir-stats Pat 360 (NN.N%) 5 72 -hir-stats - Struct 72 (NN.N%) 1 -hir-stats - Wild 72 (NN.N%) 1 -hir-stats - Binding 216 (NN.N%) 3 hir-stats Block 288 (NN.N%) 6 48 hir-stats GenericBound 256 (NN.N%) 4 64 hir-stats - Trait 256 (NN.N%) 4 @@ -119,5 +119,5 @@ hir-stats TraitItemId 8 (NN.N%) 2 4 hir-stats ImplItemId 8 (NN.N%) 2 4 hir-stats ForeignItemId 4 (NN.N%) 1 4 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_584 173 +hir-stats Total 8_624 173 hir-stats ================================================================ From e10735dd08a24d43613356d0342f437df1d5c416 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 Aug 2025 12:03:19 +0200 Subject: [PATCH 02/13] stabilize extended_varargs_abi_support --- compiler/rustc_abi/src/extern_abi.rs | 25 +++++++- compiler/rustc_abi/src/lib.rs | 2 + compiler/rustc_ast_passes/messages.ftl | 2 +- compiler/rustc_feature/src/accepted.rs | 3 + compiler/rustc_feature/src/unstable.rs | 3 - .../rustc_hir_analysis/src/check/check.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 4 +- compiler/rustc_hir_analysis/src/lib.rs | 59 ++++++++----------- library/std/src/lib.rs | 1 - .../extended-varargs-abi-support.md | 10 ---- tests/codegen-llvm/cffi/c-variadic-ffi.rs | 2 +- tests/ui/abi/unsupported-varargs-fnptr.rs | 2 - tests/ui/abi/unsupported-varargs-fnptr.stderr | 2 +- ...ature-gate-extended_varargs_abi_support.rs | 16 ----- ...e-gate-extended_varargs_abi_support.stderr | 33 ----------- tests/ui/c-variadic/issue-86053-1.rs | 2 +- tests/ui/c-variadic/issue-86053-1.stderr | 2 +- .../same-program-multiple-abis-x86_64.rs | 1 - .../cmse-nonsecure-entry/generics.rs | 2 +- .../cmse-nonsecure-entry/generics.stderr | 2 +- .../feature-gates/feature-gate-c_variadic.rs | 6 ++ .../feature-gate-c_variadic.stderr | 18 +++++- .../issue-83499-input-output-iteration-ice.rs | 2 +- ...ue-83499-input-output-iteration-ice.stderr | 2 +- .../variadic-ffi-semantic-restrictions.rs | 42 ++++++------- .../variadic-ffi-semantic-restrictions.stderr | 42 ++++++------- 27 files changed, 128 insertions(+), 161 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md delete mode 100644 tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs delete mode 100644 tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 41d744e1946ad..e3b2b1eff72d4 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -6,6 +6,8 @@ use std::hash::{Hash, Hasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable}; +#[cfg(feature = "nightly")] +use rustc_span::Symbol; use crate::AbiFromStrErr; @@ -226,6 +228,13 @@ impl StableOrd for ExternAbi { #[cfg(feature = "nightly")] rustc_error_messages::into_diag_arg_using_display!(ExternAbi); +#[cfg(feature = "nightly")] +pub enum CVariadicStatus { + NotSupported, + Stable, + Unstable { feature: Symbol }, +} + impl ExternAbi { /// An ABI "like Rust" /// @@ -238,23 +247,33 @@ impl ExternAbi { matches!(self, Rust | RustCall | RustCold) } - pub fn supports_varargs(self) -> bool { + /// Returns whether the ABI supports C variadics. This only controls whether we allow *imports* + /// of such functions via `extern` blocks; there's a separate check during AST construction + /// guarding *definitions* of variadic functions. + #[cfg(feature = "nightly")] + pub fn supports_c_variadic(self) -> CVariadicStatus { // * C and Cdecl obviously support varargs. // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs. // * EfiApi is based on Win64 or C, so it also supports it. + // * System automatically falls back to C when used with variadics, therefore supports it. // // * Stdcall does not, because it would be impossible for the callee to clean // up the arguments. (callee doesn't know how many arguments are there) // * Same for Fastcall, Vectorcall and Thiscall. // * Other calling conventions are related to hardware or the compiler itself. + // + // All of the supported ones must have a test in `tests/codegen/cffi/c-variadic-ffi.rs`. match self { Self::C { .. } | Self::Cdecl { .. } | Self::Aapcs { .. } | Self::Win64 { .. } | Self::SysV64 { .. } - | Self::EfiApi => true, - _ => false, + | Self::EfiApi => CVariadicStatus::Stable, + Self::System { .. } => { + CVariadicStatus::Unstable { feature: rustc_span::sym::extern_system_varargs } + } + _ => CVariadicStatus::NotSupported, } } } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 14e256b8045df..22aba1fac0f8b 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -63,6 +63,8 @@ mod tests; pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind}; pub use canon_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; +#[cfg(feature = "nightly")] +pub use extern_abi::CVariadicStatus; pub use extern_abi::{ExternAbi, all_names}; #[cfg(feature = "nightly")] pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx}; diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index a95f144396844..e5f1fcdc4b40d 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -57,7 +57,7 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim .label = {ast_passes_auto_super_lifetime} .suggestion = remove the super traits or lifetime bounds -ast_passes_bad_c_variadic = only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +ast_passes_bad_c_variadic = defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block .cannot_have = cannot have a body diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 9fe55216f9395..6af4cfb0e562e 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -203,6 +203,9 @@ declare_features! ( (accepted, expr_fragment_specifier_2024, "1.83.0", Some(123742)), /// Allows arbitrary expressions in key-value attributes at parse time. (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), + /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions + /// for functions with varargs. + (accepted, extended_varargs_abi_support, "CURRENT_RUSTC_VERSION", Some(100189)), /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660)), /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 92b435b4b0178..573e9aab0554a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -492,9 +492,6 @@ declare_features! ( (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), /// Allows using `#[export_stable]` which indicates that an item is exportable. (incomplete, export_stable, "1.88.0", Some(139939)), - /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions - /// for functions with varargs. - (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), /// Allows using `system` as a calling convention with varargs. (unstable, extern_system_varargs, "1.86.0", Some(136946)), /// Allows defining `extern type`s. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index eccb88a938fba..08b344638dd59 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -978,7 +978,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), tcx.ensure_ok().fn_sig(def_id); let item = tcx.hir_foreign_item(item); let hir::ForeignItemKind::Fn(sig, ..) = item.kind else { bug!() }; - require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); + check_c_variadic_abi(tcx, sig.decl, abi, item.span); } DefKind::Static { .. } => { tcx.ensure_ok().codegen_fn_attrs(def_id); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 2e4b151d4dc8c..b5c0ca4727cda 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -98,7 +98,7 @@ use tracing::debug; use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys; use self::region::region_scope_tree; -use crate::{errors, require_c_abi_if_c_variadic}; +use crate::{check_c_variadic_abi, errors}; /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`] pub(super) fn provide(providers: &mut Providers) { 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 c7b984d9b259c..c5e079fe89ac4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -52,11 +52,11 @@ use rustc_trait_selection::traits::{self, FulfillmentError}; use tracing::{debug, instrument}; use crate::check::check_abi; +use crate::check_c_variadic_abi; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; -use crate::require_c_abi_if_c_variadic; /// A path segment that is semantically allowed to have generic arguments. #[derive(Debug)] @@ -2412,7 +2412,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.lower_ty(t))) } hir::TyKind::FnPtr(bf) => { - require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, hir_ty.span); + check_c_variadic_abi(tcx, bf.decl, bf.abi, hir_ty.span); Ty::new_fn_ptr( tcx, diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 44a5ceed46961..2562ab7542a6a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -90,7 +90,7 @@ mod outlives; mod variance; pub use errors::NoVariantNamed; -use rustc_abi::ExternAbi; +use rustc_abi::{CVariadicStatus, ExternAbi}; use rustc_hir::def::DefKind; use rustc_hir::lints::DelayedLint; use rustc_hir::{self as hir}; @@ -99,7 +99,6 @@ use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_session::parse::feature_err; -use rustc_span::symbol::sym; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; @@ -108,46 +107,34 @@ use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer}; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } -fn require_c_abi_if_c_variadic( - tcx: TyCtxt<'_>, - decl: &hir::FnDecl<'_>, - abi: ExternAbi, - span: Span, -) { - // ABIs which can stably use varargs - if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) { +fn check_c_variadic_abi(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: ExternAbi, span: Span) { + if !decl.c_variadic { + // Not even a variadic function. return; } - // ABIs with feature-gated stability - let extended_abi_support = tcx.features().extended_varargs_abi_support(); - let extern_system_varargs = tcx.features().extern_system_varargs(); - - // If the feature gate has been enabled, we can stop here - if extern_system_varargs && let ExternAbi::System { .. } = abi { - return; - }; - if extended_abi_support && abi.supports_varargs() { - return; - }; - - // Looks like we need to pick an error to emit. - // Is there any feature which we could have enabled to make this work? - let unstable_explain = - format!("C-variadic functions with the {abi} calling convention are unstable"); - match abi { - ExternAbi::System { .. } => { - feature_err(&tcx.sess, sym::extern_system_varargs, span, unstable_explain) + match abi.supports_c_variadic() { + CVariadicStatus::Stable => {} + CVariadicStatus::NotSupported => { + tcx.dcx() + .create_err(errors::VariadicFunctionCompatibleConvention { + span, + convention: &format!("{abi}"), + }) + .emit(); } - abi if abi.supports_varargs() => { - feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, unstable_explain) + CVariadicStatus::Unstable { feature } => { + if !tcx.features().enabled(feature) { + feature_err( + &tcx.sess, + feature, + span, + format!("C-variadic functions with the {abi} calling convention are unstable"), + ) + .emit(); + } } - _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention { - span, - convention: &format!("{abi}"), - }), } - .emit(); } /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f0de03c9a2806..da8fda42cd143 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -291,7 +291,6 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(extended_varargs_abi_support)] #![feature(f16)] #![feature(f128)] #![feature(ffi_const)] diff --git a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md b/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md deleted file mode 100644 index b20c30ec8f1c8..0000000000000 --- a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md +++ /dev/null @@ -1,10 +0,0 @@ -# `extended_varargs_abi_support` - -The tracking issue for this feature is: [#100189] - -[#100189]: https://github.com/rust-lang/rust/issues/100189 - ------------------------- - -This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling -conventions on functions with varargs. diff --git a/tests/codegen-llvm/cffi/c-variadic-ffi.rs b/tests/codegen-llvm/cffi/c-variadic-ffi.rs index 3e99c9fb84e42..1dee477e9ed7c 100644 --- a/tests/codegen-llvm/cffi/c-variadic-ffi.rs +++ b/tests/codegen-llvm/cffi/c-variadic-ffi.rs @@ -14,7 +14,7 @@ //@[arm32] needs-llvm-components: arm #![crate_type = "lib"] #![feature(no_core)] -#![feature(extended_varargs_abi_support, extern_system_varargs)] +#![feature(extern_system_varargs)] #![no_core] extern crate minicore; diff --git a/tests/ui/abi/unsupported-varargs-fnptr.rs b/tests/ui/abi/unsupported-varargs-fnptr.rs index 1d23916d03902..ac3913b3ef88f 100644 --- a/tests/ui/abi/unsupported-varargs-fnptr.rs +++ b/tests/ui/abi/unsupported-varargs-fnptr.rs @@ -6,8 +6,6 @@ // We have to use this flag to force ABI computation of an invalid ABI //@ compile-flags: -Clink-dead-code -#![feature(extended_varargs_abi_support)] - // sometimes fn ptrs with varargs make layout and ABI computation ICE // as found in https://github.com/rust-lang/rust/issues/142107 diff --git a/tests/ui/abi/unsupported-varargs-fnptr.stderr b/tests/ui/abi/unsupported-varargs-fnptr.stderr index 238f2b3133044..c05c55df82e75 100644 --- a/tests/ui/abi/unsupported-varargs-fnptr.stderr +++ b/tests/ui/abi/unsupported-varargs-fnptr.stderr @@ -1,5 +1,5 @@ error[E0570]: "aapcs" is not a supported ABI for the current target - --> $DIR/unsupported-varargs-fnptr.rs:14:20 + --> $DIR/unsupported-varargs-fnptr.rs:12:20 | LL | fn aapcs(f: extern "aapcs" fn(usize, ...)) { | ^^^^^^^ diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs deleted file mode 100644 index 1e0576b21866b..0000000000000 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ only-x86_64 - -fn efiapi(f: extern "efiapi" fn(usize, ...)) { - //~^ ERROR: unstable - f(22, 44); -} -fn sysv(f: extern "sysv64" fn(usize, ...)) { - //~^ ERROR: unstable - f(22, 44); -} -fn win(f: extern "win64" fn(usize, ...)) { - //~^ ERROR: unstable - f(22, 44); -} - -fn main() {} diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr deleted file mode 100644 index 7ef54b639ad2b..0000000000000 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0658]: C-variadic functions with the "efiapi" calling convention are unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 - | -LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 for more information - = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: C-variadic functions with the "sysv64" calling convention are unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:7:12 - | -LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 for more information - = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: C-variadic functions with the "win64" calling convention are unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11 - | -LL | fn win(f: extern "win64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 for more information - = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs index 8eeb99a4cc19c..537d0263adf78 100644 --- a/tests/ui/c-variadic/issue-86053-1.rs +++ b/tests/ui/c-variadic/issue-86053-1.rs @@ -13,6 +13,6 @@ fn ordering4 < 'a , 'b > ( a : , self , self , self , //~| ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function //~| ERROR `...` must be the last argument of a C-variadic function - //~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR cannot find type `F` in this scope } diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr index dc323f9a234d6..472295c92b972 100644 --- a/tests/ui/c-variadic/issue-86053-1.stderr +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -46,7 +46,7 @@ error: `...` must be the last argument of a C-variadic function LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/issue-86053-1.rs:11:12 | LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { diff --git a/tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs b/tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs index b21accb999e9b..aff8ab613c431 100644 --- a/tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs +++ b/tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs @@ -1,4 +1,3 @@ -#![feature(extended_varargs_abi_support)] //@ run-pass //@ only-x86_64 diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs index 800dd580af290..ad4fca8252d24 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs @@ -71,6 +71,6 @@ extern "cmse-nonsecure-entry" fn wrapped_trait_object( } extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR requires `va_list` lang_item } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr index f0190671b5a17..7aeb6969feb9f 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr @@ -1,4 +1,4 @@ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/generics.rs:73:53 | LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.rs b/tests/ui/feature-gates/feature-gate-c_variadic.rs index f189f02a26ddf..45c688420931d 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic.rs +++ b/tests/ui/feature-gates/feature-gate-c_variadic.rs @@ -2,3 +2,9 @@ pub unsafe extern "C" fn test(_: i32, ap: ...) { } //~^ ERROR C-variadic functions are unstable + +trait Trait { + unsafe extern "C" fn trait_test(_: i32, ap: ...) { } + //~^ ERROR C-variadic functions are unstable + //~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention +} diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.stderr b/tests/ui/feature-gates/feature-gate-c_variadic.stderr index 1b6a8c92af5ed..e30a2f1ede367 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic.stderr @@ -1,3 +1,9 @@ +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention + --> $DIR/feature-gate-c_variadic.rs:7:45 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { } + | ^^^^^^^ + error[E0658]: C-variadic functions are unstable --> $DIR/feature-gate-c_variadic.rs:3:1 | @@ -8,6 +14,16 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { } = help: add `#![feature(c_variadic)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: C-variadic functions are unstable + --> $DIR/feature-gate-c_variadic.rs:7:5 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44930 for more information + = help: add `#![feature(c_variadic)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/mir/issue-83499-input-output-iteration-ice.rs b/tests/ui/mir/issue-83499-input-output-iteration-ice.rs index 78e5c96180285..9277994d9b30f 100644 --- a/tests/ui/mir/issue-83499-input-output-iteration-ice.rs +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.rs @@ -5,6 +5,6 @@ fn main() {} fn foo(_: Bar, ...) -> impl {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR cannot find type `Bar` in this scope //~| ERROR at least one trait must be specified diff --git a/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr index 80a8a94aea400..4a1aa49eb6e6f 100644 --- a/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr @@ -1,4 +1,4 @@ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/issue-83499-input-output-iteration-ice.rs:7:16 | LL | fn foo(_: Bar, ...) -> impl {} diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs index 1cd6d13d56b6b..e7a0248cffab9 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -4,29 +4,29 @@ fn main() {} fn f1_1(x: isize, ...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn f1_2(...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f2_1(x: isize, ...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f2_2(...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f2_3(..., x: isize) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function extern "C" fn f3_1(x: isize, ...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f3_2(...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f3_3(..., x: isize) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function const unsafe extern "C" fn f4_1(x: isize, ...) {} @@ -35,12 +35,12 @@ const unsafe extern "C" fn f4_1(x: isize, ...) {} const extern "C" fn f4_2(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic -//~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time const extern "C" fn f4_3(..., x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic -//~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function extern "C" { @@ -52,34 +52,34 @@ struct X; impl X { fn i_f1(x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn i_f2(...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn i_f3(..., x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function fn i_f4(..., x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function const fn i_f5(x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR functions cannot be both `const` and C-variadic //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time } trait T { fn t_f1(x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn t_f2(x: isize, ...); - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn t_f3(...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn t_f4(...); - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn t_f5(..., x: isize) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function fn t_f6(..., x: isize); - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function } diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr index b740cef020055..5379045967aa0 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -1,22 +1,22 @@ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:6:19 | LL | fn f1_1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 | LL | fn f1_2(...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30 | LL | extern "C" fn f2_1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 | LL | extern "C" fn f2_2(...) {} @@ -28,19 +28,19 @@ error: `...` must be the last argument of a C-variadic function LL | extern "C" fn f2_3(..., x: isize) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:18:20 | LL | extern "C" fn f2_3(..., x: isize) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:22:30 | LL | extern "C" fn f3_1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:25:20 | LL | extern "C" fn f3_2(...) {} @@ -52,7 +52,7 @@ error: `...` must be the last argument of a C-variadic function LL | extern "C" fn f3_3(..., x: isize) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:28:20 | LL | extern "C" fn f3_3(..., x: isize) {} @@ -70,7 +70,7 @@ error: functions cannot be both `const` and C-variadic LL | const extern "C" fn f4_2(x: isize, ...) {} | ^^^^^ `const` because of this ^^^ C-variadic because of this -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:36:36 | LL | const extern "C" fn f4_2(x: isize, ...) {} @@ -91,7 +91,7 @@ LL | const extern "C" fn f4_3(..., x: isize, ...) {} | | C-variadic because of this | `const` because of this -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:41:26 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} @@ -103,13 +103,13 @@ error: `...` must be the last argument of a C-variadic function LL | fn e_f2(..., x: isize); | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:54:23 | LL | fn i_f1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:56:13 | LL | fn i_f2(...) {} @@ -121,7 +121,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn i_f3(..., x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:58:13 | LL | fn i_f3(..., x: isize, ...) {} @@ -133,7 +133,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn i_f4(..., x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | LL | fn i_f4(..., x: isize, ...) {} @@ -147,31 +147,31 @@ LL | const fn i_f5(x: isize, ...) {} | | | `const` because of this -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:64:29 | LL | const fn i_f5(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:71:23 | LL | fn t_f1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:73:23 | LL | fn t_f2(x: isize, ...); | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:75:13 | LL | fn t_f3(...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:77:13 | LL | fn t_f4(...); @@ -183,7 +183,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn t_f5(..., x: isize) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:79:13 | LL | fn t_f5(..., x: isize) {} @@ -195,7 +195,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn t_f6(..., x: isize); | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:82:13 | LL | fn t_f6(..., x: isize); From fc7de9979e418b0ea467bb2833b07486d7c54940 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Aug 2025 13:36:10 +0000 Subject: [PATCH 03/13] Ensure we emit an allocator shim when only some crate types need one --- compiler/rustc_codegen_ssa/src/back/link.rs | 17 ++++++++++--- compiler/rustc_codegen_ssa/src/base.rs | 27 +++++++++++++++++---- tests/ui/linking/mixed-allocator-shim.rs | 15 ++++++++++++ 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 tests/ui/linking/mixed-allocator-shim.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 19c919c0e4efe..48b01ea2df197 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -58,6 +58,7 @@ use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; use super::rpath::{self, RPathConfig}; use super::{apple, versioned_llvm_target}; +use crate::base::needs_allocator_shim_for_linking; use crate::{ CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file, }; @@ -2080,9 +2081,17 @@ fn add_local_crate_regular_objects(cmd: &mut dyn Linker, codegen_results: &Codeg } /// Add object files for allocator code linked once for the whole crate tree. -fn add_local_crate_allocator_objects(cmd: &mut dyn Linker, codegen_results: &CodegenResults) { - if let Some(obj) = codegen_results.allocator_module.as_ref().and_then(|m| m.object.as_ref()) { - cmd.add_object(obj); +fn add_local_crate_allocator_objects( + cmd: &mut dyn Linker, + codegen_results: &CodegenResults, + crate_type: CrateType, +) { + if needs_allocator_shim_for_linking(&codegen_results.crate_info.dependency_formats, crate_type) + { + if let Some(obj) = codegen_results.allocator_module.as_ref().and_then(|m| m.object.as_ref()) + { + cmd.add_object(obj); + } } } @@ -2281,7 +2290,7 @@ fn linker_with_args( codegen_results, metadata, ); - add_local_crate_allocator_objects(cmd, codegen_results); + add_local_crate_allocator_objects(cmd, codegen_results, crate_type); // Avoid linking to dynamic libraries unless they satisfy some undefined symbols // at the point at which they are specified on the command line. diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 8abaf201abae2..97cdf8b697348 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -17,6 +17,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{ItemId, Target}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; +use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::{self, SymbolExportKind}; use rustc_middle::middle::lang_items; use rustc_middle::mir::BinOp; @@ -630,14 +631,30 @@ pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option { // If the crate doesn't have an `allocator_kind` set then there's definitely // no shim to generate. Otherwise we also check our dependency graph for all // our output crate types. If anything there looks like its a `Dynamic` - // linkage, then it's already got an allocator shim and we'll be using that - // one instead. If nothing exists then it's our job to generate the - // allocator! - let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| { + // linkage for all crate types we may link as, then it's already got an + // allocator shim and we'll be using that one instead. If nothing exists + // then it's our job to generate the allocator! If crate types disagree + // about whether an allocator shim is necessary or not, we generate one + // and let needs_allocator_shim_for_linking decide at link time whether or + // not to use it for any particular linker invocation. + let all_crate_types_any_dynamic_crate = tcx.dependency_formats(()).iter().all(|(_, list)| { use rustc_middle::middle::dependency_format::Linkage; list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); - if any_dynamic_crate { None } else { tcx.allocator_kind(()) } + if all_crate_types_any_dynamic_crate { None } else { tcx.allocator_kind(()) } +} + +/// Decide if this particular crate type needs an allocator shim linked in. +/// This may return true even when allocator_kind_for_codegen returns false. In +/// this case no allocator shim shall be linked. +pub(crate) fn needs_allocator_shim_for_linking( + dependency_formats: &Dependencies, + crate_type: CrateType, +) -> bool { + use rustc_middle::middle::dependency_format::Linkage; + let any_dynamic_crate = + dependency_formats[&crate_type].iter().any(|&linkage| linkage == Linkage::Dynamic); + !any_dynamic_crate } pub fn codegen_crate( diff --git a/tests/ui/linking/mixed-allocator-shim.rs b/tests/ui/linking/mixed-allocator-shim.rs new file mode 100644 index 0000000000000..b81fbdc5205e7 --- /dev/null +++ b/tests/ui/linking/mixed-allocator-shim.rs @@ -0,0 +1,15 @@ +//@ build-pass +//@ compile-flags: --crate-type staticlib,dylib -Zstaticlib-prefer-dynamic +//@ no-prefer-dynamic + +// Test that compiling for multiple crate types in a single compilation with +// mismatching allocator shim requirements doesn't result in the allocator shim +// missing entirely. +// In this particular test the dylib crate type will statically link libstd and +// thus need an allocator shim, while the staticlib crate type will dynamically +// link libstd and thus not need an allocator shim. +// The -Zstaticlib-prefer-dynamic flag could be avoided by doing it the other +// way around, but testing that the staticlib correctly has the allocator shim +// in that case would require a run-make test instead. + +pub fn foo() {} From 1d309008306f6695bdbbd535245067202ab44802 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Aug 2025 15:16:48 +0000 Subject: [PATCH 04/13] Fix typo in comment --- compiler/rustc_codegen_ssa/src/back/linker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index df1e91b12f904..03c30dc0c5929 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1827,7 +1827,7 @@ fn exported_symbols_for_non_proc_macro( let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { // Do not export mangled symbols from cdylibs and don't attempt to export compiler-builtins - // from any cdylib. The latter doesn't work anyway as we use hidden visibility for + // from any dylib. The latter doesn't work anyway as we use hidden visibility for // compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning. if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) { symbols.push(( From f4888c2a680aff0bd191704a8d44716eee94103e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:59:22 +0000 Subject: [PATCH 05/13] Correctly handle different crate types disagreeing if the allocator shim is exported Previously it would attempt to export the allocator shim even linking for a crate type which pulls in the allocator shim from a dylib rather than locally defining it. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 15 +++++- compiler/rustc_codegen_ssa/src/back/lto.rs | 8 ++- .../src/back/symbol_export.rs | 52 +++++++++---------- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 03c30dc0c5929..a2efd420a327a 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -11,8 +11,9 @@ use rustc_metadata::{ }; use rustc_middle::bug; use rustc_middle::middle::dependency_format::Linkage; -use rustc_middle::middle::exported_symbols; -use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind}; +use rustc_middle::middle::exported_symbols::{ + self, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, +}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip}; @@ -22,6 +23,8 @@ use tracing::{debug, warn}; use super::command::Command; use super::symbol_export; +use crate::back::symbol_export::allocator_shim_symbols; +use crate::base::needs_allocator_shim_for_linking; use crate::errors; #[cfg(test)] @@ -1838,6 +1841,14 @@ fn exported_symbols_for_non_proc_macro( } }); + // Mark allocator shim symbols as exported only if they were generated. + if export_threshold == SymbolExportLevel::Rust + && needs_allocator_shim_for_linking(tcx.dependency_formats(()), crate_type) + && tcx.allocator_kind(()).is_some() + { + symbols.extend(allocator_shim_symbols(tcx)); + } + symbols } diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index c95038375a1bd..e6df6a2469f37 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -8,8 +8,9 @@ use rustc_middle::ty::TyCtxt; use rustc_session::config::{CrateType, Lto}; use tracing::info; -use crate::back::symbol_export::{self, symbol_name_for_instance_in_crate}; +use crate::back::symbol_export::{self, allocator_shim_symbols, symbol_name_for_instance_in_crate}; use crate::back::write::CodegenContext; +use crate::base::allocator_kind_for_codegen; use crate::errors::{DynamicLinkingWithLTO, LtoDisallowed, LtoDylib, LtoProcMacro}; use crate::traits::*; @@ -115,6 +116,11 @@ pub(super) fn exported_symbols_for_lto( } } + // Mark allocator shim symbols as exported only if they were generated. + if export_threshold == SymbolExportLevel::Rust && allocator_kind_for_codegen(tcx).is_some() { + symbols_below_threshold.extend(allocator_shim_symbols(tcx).map(|(name, _kind)| name)); + } + symbols_below_threshold } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d8a1480e911fe..b49e67217fb01 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -18,7 +18,7 @@ use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::spec::TlsModel; use tracing::debug; -use crate::base::allocator_kind_for_codegen; +use crate::back::symbol_export; fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(tcx.crate_types()) @@ -217,31 +217,6 @@ fn exported_non_generic_symbols_provider_local<'tcx>( )); } - // Mark allocator shim symbols as exported only if they were generated. - if allocator_kind_for_codegen(tcx).is_some() { - for symbol_name in ALLOCATOR_METHODS - .iter() - .map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str())) - .chain([ - mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), - mangle_internal_symbol(tcx, OomStrategy::SYMBOL), - mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), - ]) - { - let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); - - symbols.push(( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::Rust, - kind: SymbolExportKind::Text, - used: false, - rustc_std_internal_symbol: true, - }, - )); - } - } - // Sort so we get a stable incr. comp. hash. symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx)); @@ -516,6 +491,31 @@ pub(crate) fn provide(providers: &mut Providers) { upstream_monomorphizations_for_provider; } +pub(crate) fn allocator_shim_symbols( + tcx: TyCtxt<'_>, +) -> impl Iterator { + ALLOCATOR_METHODS + .iter() + .map(move |method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str())) + .chain([ + mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + mangle_internal_symbol(tcx, OomStrategy::SYMBOL), + mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), + ]) + .map(move |symbol_name| { + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); + + ( + symbol_export::exporting_symbol_name_for_instance_in_crate( + tcx, + exported_symbol, + LOCAL_CRATE, + ), + SymbolExportKind::Text, + ) + }) +} + fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel { // We export anything that's not mangled at the "C" layer as it probably has // to do with ABI concerns. We do not, however, apply such treatment to From 8930d3a7504a7bda441782c65a9d6320e7674ba3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 28 Aug 2025 16:52:14 +0300 Subject: [PATCH 06/13] resolve: Avoid a regression from splitting prelude into two scopes --- compiler/rustc_resolve/src/ident.rs | 23 ++++++++++++++++--- .../imports/overwritten-extern-flag-ambig.rs | 13 +++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 tests/ui/imports/overwritten-extern-flag-ambig.rs diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index dae42645becdd..bc06a22757113 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -422,6 +422,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // to detect potential ambiguities. let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None; let mut determinacy = Determinacy::Determined; + let mut extern_prelude_item_binding = None; + let mut extern_prelude_flag_binding = None; // Shadowed bindings don't need to be marked as used or non-speculatively loaded. macro finalize_scope() { if innermost_result.is_none() { finalize } else { None } @@ -558,7 +560,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::ExternPreludeItems => { // FIXME: use `finalize_scope` here. match this.reborrow().extern_prelude_get_item(ident, finalize.is_some()) { - Some(binding) => Ok((binding, Flags::empty())), + Some(binding) => { + extern_prelude_item_binding = Some(binding); + Ok((binding, Flags::empty())) + } None => Err(Determinacy::determined( this.graph_root.unexpanded_invocations.borrow().is_empty(), )), @@ -566,7 +571,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } Scope::ExternPreludeFlags => { match this.extern_prelude_get_flag(ident, finalize_scope!().is_some()) { - Some(binding) => Ok((binding, Flags::empty())), + Some(binding) => { + extern_prelude_flag_binding = Some(binding); + Ok((binding, Flags::empty())) + } None => Err(Determinacy::Determined), } } @@ -686,7 +694,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else { None }; - if let Some(kind) = ambiguity_error_kind { + // Skip ambiguity errors for extern flag bindings "overridden" + // by extern item bindings. + // FIXME: Remove with lang team approval. + let issue_145575_hack = Some(binding) + == extern_prelude_flag_binding + && extern_prelude_item_binding.is_some() + && extern_prelude_item_binding != Some(innermost_binding); + if let Some(kind) = ambiguity_error_kind + && !issue_145575_hack + { let misc = |f: Flags| { if f.contains(Flags::MISC_SUGGEST_CRATE) { AmbiguityErrorMisc::SuggestCrate diff --git a/tests/ui/imports/overwritten-extern-flag-ambig.rs b/tests/ui/imports/overwritten-extern-flag-ambig.rs new file mode 100644 index 0000000000000..80f394d34de02 --- /dev/null +++ b/tests/ui/imports/overwritten-extern-flag-ambig.rs @@ -0,0 +1,13 @@ +// Test for issue #145575. + +//@ check-pass +//@ edition: 2018 + +extern crate core as std; + +mod inner { + use crate::*; + use std::str; // OK for now +} + +fn main() {} From 0711bba9ea368204b1a7f833e0e44c529ce140c8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 31 Aug 2025 20:43:44 +0000 Subject: [PATCH 07/13] Ignore test when dylibs are not supported --- tests/ui/linking/mixed-allocator-shim.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/linking/mixed-allocator-shim.rs b/tests/ui/linking/mixed-allocator-shim.rs index b81fbdc5205e7..e4f20a11ebb37 100644 --- a/tests/ui/linking/mixed-allocator-shim.rs +++ b/tests/ui/linking/mixed-allocator-shim.rs @@ -1,6 +1,7 @@ //@ build-pass //@ compile-flags: --crate-type staticlib,dylib -Zstaticlib-prefer-dynamic //@ no-prefer-dynamic +//@ needs-crate-type: dylib // Test that compiling for multiple crate types in a single compilation with // mismatching allocator shim requirements doesn't result in the allocator shim From 2784327c1c8c4a656d3d2d2039b954e38fdbcd08 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Sun, 31 Aug 2025 20:28:45 -0400 Subject: [PATCH 08/13] alloc: make Cow From impls const --- library/alloc/src/bstr.rs | 6 ++++-- library/alloc/src/ffi/c_str.rs | 6 ++++-- library/alloc/src/lib.rs | 1 + library/alloc/src/string.rs | 9 ++++++--- library/alloc/src/vec/cow.rs | 12 ++++++++---- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/bstr.rs b/library/alloc/src/bstr.rs index 338c7ac7f8876..5e21ec5334c42 100644 --- a/library/alloc/src/bstr.rs +++ b/library/alloc/src/bstr.rs @@ -245,7 +245,8 @@ impl<'a> From<&'a ByteStr> for ByteString { } #[unstable(feature = "bstr", issue = "134915")] -impl<'a> From for Cow<'a, ByteStr> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a> const From for Cow<'a, ByteStr> { #[inline] fn from(s: ByteString) -> Self { Cow::Owned(s) @@ -598,7 +599,8 @@ impl Clone for Box { } #[unstable(feature = "bstr", issue = "134915")] -impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a> const From<&'a ByteStr> for Cow<'a, ByteStr> { #[inline] fn from(s: &'a ByteStr) -> Self { Cow::Borrowed(s) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index b0c8c4b1ca4a7..fec9a0c3f1ba8 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -869,7 +869,8 @@ impl From for Box { } #[stable(feature = "cow_from_cstr", since = "1.28.0")] -impl<'a> From for Cow<'a, CStr> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a> const From for Cow<'a, CStr> { /// Converts a [`CString`] into an owned [`Cow`] without copying or allocating. #[inline] fn from(s: CString) -> Cow<'a, CStr> { @@ -878,7 +879,8 @@ impl<'a> From for Cow<'a, CStr> { } #[stable(feature = "cow_from_cstr", since = "1.28.0")] -impl<'a> From<&'a CStr> for Cow<'a, CStr> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a> const From<&'a CStr> for Cow<'a, CStr> { /// Converts a [`CStr`] into a borrowed [`Cow`] without copying or allocating. #[inline] fn from(s: &'a CStr) -> Cow<'a, CStr> { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 711092ae8eb25..00603bad8eee8 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -109,6 +109,7 @@ #![feature(coerce_unsized)] #![feature(const_default)] #![feature(const_eval_select)] +#![feature(const_from)] #![feature(const_heap)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 1d0dd4be1b66a..a93777f32e426 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -3109,7 +3109,8 @@ impl<'a> From> for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&'a str> for Cow<'a, str> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a> const From<&'a str> for Cow<'a, str> { /// Converts a string slice into a [`Borrowed`] variant. /// No heap allocation is performed, and the string /// is not copied. @@ -3130,7 +3131,8 @@ impl<'a> From<&'a str> for Cow<'a, str> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From for Cow<'a, str> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a> const From for Cow<'a, str> { /// Converts a [`String`] into an [`Owned`] variant. /// No heap allocation is performed, and the string /// is not copied. @@ -3153,7 +3155,8 @@ impl<'a> From for Cow<'a, str> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_from_string_ref", since = "1.28.0")] -impl<'a> From<&'a String> for Cow<'a, str> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a> const From<&'a String> for Cow<'a, str> { /// Converts a [`String`] reference into a [`Borrowed`] variant. /// No heap allocation is performed, and the string /// is not copied. diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index 4deb35efffc14..ac752fc72dc9b 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -2,7 +2,8 @@ use super::Vec; use crate::borrow::Cow; #[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a, T: Clone> const From<&'a [T]> for Cow<'a, [T]> { /// Creates a [`Borrowed`] variant of [`Cow`] /// from a slice. /// @@ -15,7 +16,8 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { } #[stable(feature = "cow_from_array_ref", since = "1.77.0")] -impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a, T: Clone, const N: usize> const From<&'a [T; N]> for Cow<'a, [T]> { /// Creates a [`Borrowed`] variant of [`Cow`] /// from a reference to an array. /// @@ -28,7 +30,8 @@ impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> { } #[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From> for Cow<'a, [T]> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a, T: Clone> const From> for Cow<'a, [T]> { /// Creates an [`Owned`] variant of [`Cow`] /// from an owned instance of [`Vec`]. /// @@ -41,7 +44,8 @@ impl<'a, T: Clone> From> for Cow<'a, [T]> { } #[stable(feature = "cow_from_vec_ref", since = "1.28.0")] -impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a, T: Clone> const From<&'a Vec> for Cow<'a, [T]> { /// Creates a [`Borrowed`] variant of [`Cow`] /// from a reference to [`Vec`]. /// From ac89fcbc55181754dd58b90ed31175f72ed93589 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 31 Aug 2025 18:31:59 -0700 Subject: [PATCH 09/13] rustdoc-search: skip loading unneeded fnData --- src/librustdoc/html/static/js/rustdoc.d.ts | 2 +- src/librustdoc/html/static/js/search.js | 23 +++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 74f646008ebd7..938ccc7d2c32e 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -289,7 +289,7 @@ declare namespace rustdoc { exactModulePath: string, entry: EntryData?, path: PathData?, - type: FunctionData?, + functionData: FunctionData?, deprecated: boolean, parent: { path: PathData, name: string}?, } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index fa812a2b67b5a..5da37c97c6a73 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1802,14 +1802,15 @@ class DocSearch { /** * @param {number} id + * @param {boolean} loadFunctionData * @returns {Promise} */ - async getRow(id) { - const [name_, entry, path, type] = await Promise.all([ + async getRow(id, loadFunctionData) { + const [name_, entry, path, functionData] = await Promise.all([ this.getName(id), this.getEntryData(id), this.getPathData(id), - this.getFunctionData(id), + loadFunctionData ? this.getFunctionData(id) : null, ]); if (!entry && !path) { return null; @@ -1853,7 +1854,7 @@ class DocSearch { `${exactModulePathData.exactModulePath}::${exactModuleName}`), entry, path, - type, + functionData, deprecated: entry ? entry.deprecated : false, parent: parentName !== null && parentPath !== null ? { name: parentName, path: parentPath } : @@ -2563,11 +2564,11 @@ class DocSearch { name: item.parent.name, ty: item.parent.path.ty, } : undefined, - type: item.type && item.type.functionSignature ? - item.type.functionSignature : + type: item.functionData && item.functionData.functionSignature ? + item.functionData.functionSignature : undefined, - paramNames: item.type && item.type.paramNames ? - item.type.paramNames : + paramNames: item.functionData && item.functionData.paramNames ? + item.functionData.paramNames : undefined, dist: result.dist, path_dist: result.path_dist, @@ -2642,7 +2643,7 @@ class DocSearch { /** * @type {rustdoc.Row?} */ - const item = await this.getRow(result.id); + const item = await this.getRow(result.id, typeInfo !== null); if (!item) { continue; } @@ -3749,7 +3750,7 @@ class DocSearch { is_alias: true, elems: [], // only used in type-based queries returned: [], // only used in type-based queries - original: await this.getRow(alias), + original: await this.getRow(alias, false), }; }; /** @@ -3804,7 +3805,7 @@ class DocSearch { * @returns {Promise} */ const handleNameSearch = async id => { - const row = await this.getRow(id); + const row = await this.getRow(id, false); if (!row || !row.entry) { return null; } From f6e7c81061c24a2210149ff94670d8672bd0224a Mon Sep 17 00:00:00 2001 From: jullang Date: Sun, 31 Aug 2025 19:27:03 +0000 Subject: [PATCH 10/13] Add compiler error when trying to use concat metavar expr in repetitions Replace unimplemented()! with a more helpful compiler error. --- compiler/rustc_expand/src/mbe/transcribe.rs | 7 ++++++- tests/crashes/140479.rs | 5 ----- .../in-repetition.rs | 21 +++++++++++++++++++ .../in-repetition.stderr | 8 +++++++ 4 files changed, 35 insertions(+), 6 deletions(-) delete mode 100644 tests/crashes/140479.rs create mode 100644 tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs create mode 100644 tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 174844d6ad639..e4e4866b64cdf 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -556,7 +556,12 @@ fn metavar_expr_concat<'tx>( }; match &named_matches[*curr_idx] { // FIXME(c410-f3r) Nested repetitions are unimplemented - MatchedSeq(_) => unimplemented!(), + MatchedSeq(_) => { + return Err(dcx.struct_span_err( + ident.span, + "nested repetitions with `${concat(...)}` metavariable expressions are not yet supported", + )); + } MatchedSingle(pnr) => extract_symbol_from_pnr(dcx, pnr, ident.span)?, } } diff --git a/tests/crashes/140479.rs b/tests/crashes/140479.rs deleted file mode 100644 index ed3ca887546f9..0000000000000 --- a/tests/crashes/140479.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: #140479 -macro_rules! a { ( $( { $ [ $b:c ] } )) => ( $(${ concat(d, $b)} ))} -fn e() { - a!({}) -} diff --git a/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs new file mode 100644 index 0000000000000..d2bd31b06d606 --- /dev/null +++ b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs @@ -0,0 +1,21 @@ +// issue: +// Ensure a proper compiler error, instead of an ICE occurs. +// FIXME(macro_metavar_expr_concat): this error message could be improved +#![feature(macro_metavar_expr_concat)] + +macro_rules! InRepetition { + ( + $( + $($arg:ident),+ + )+ + ) => { + $( + $( + ${concat(_, $arg)} //~ ERROR nested repetitions with `${concat(...)}` metavariable expressions are not yet supported + )* + )* + }; +} +InRepetition!(other); + +fn main() {} diff --git a/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr new file mode 100644 index 0000000000000..ec39ca799e198 --- /dev/null +++ b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr @@ -0,0 +1,8 @@ +error: nested repetitions with `${concat(...)}` metavariable expressions are not yet supported + --> $DIR/in-repetition.rs:14:30 + | +LL | ${concat(_, $arg)} + | ^^^ + +error: aborting due to 1 previous error + From 8dfd6b8ec208f4f31dd0e41c32e9239bf262068c Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Mon, 1 Sep 2025 08:55:25 -0400 Subject: [PATCH 11/13] fix a constness ordering bug in rustfmt Normally, changes to rustfmt go into the separate repo. But, in this case, the bug is introduced in a local change and therefore isn't present in the rustfmt repo. --- src/tools/rustfmt/src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 6555679c39448..75e468b35256c 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1175,8 +1175,8 @@ pub(crate) fn format_trait( let mut result = String::with_capacity(128); let header = format!( "{}{}{}{}trait ", - format_constness(constness), format_visibility(context, &item.vis), + format_constness(constness), format_safety(safety), format_auto(is_auto), ); From d8df6312d5b3290c6976e5b55f5ae8344cab1bb4 Mon Sep 17 00:00:00 2001 From: Moritz Hedtke Date: Mon, 1 Sep 2025 17:26:20 +0200 Subject: [PATCH 12/13] Make `Parser::parse_for_head` public for rustfmt usage --- compiler/rustc_parse/src/parser/expr.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7de4f6efd0b0f..9b09cbba7afcc 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2910,7 +2910,8 @@ impl<'a> Parser<'a> { } } - fn parse_for_head(&mut self) -> PResult<'a, (Box, Box)> { + // Public to use it for custom `for` expressions in rustfmt forks like https://github.com/tucant/rustfmt + pub fn parse_for_head(&mut self) -> PResult<'a, (Box, Box)> { let begin_paren = if self.token == token::OpenParen { // Record whether we are about to parse `for (`. // This is used below for recovery in case of `for ( $stuff ) $block` From 6fc0cf428885a4939fc3b6f60f638ce09e48339f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 1 Sep 2025 21:39:01 +0200 Subject: [PATCH 13/13] Remove dead code stemming from an old effects desugaring --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_hir/src/hir.rs | 1 - compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_analysis/src/collect/generics_of.rs | 6 +++--- .../rustc_hir_analysis/src/hir_ty_lowering/generics.rs | 9 +-------- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_middle/src/ty/generics.rs | 2 +- compiler/rustc_public/src/unstable/convert/stable/ty.rs | 8 ++++---- src/librustdoc/clean/mod.rs | 6 ++---- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/json/conversions.rs | 2 +- 11 files changed, 16 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 70595391b85bc..a6a4cc842f0e0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2028,7 +2028,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ( hir::ParamName::Plain(self.lower_ident(param.ident)), - hir::GenericParamKind::Const { ty, default, synthetic: false }, + hir::GenericParamKind::Const { ty, default }, ) } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e397c286de289..cdade500a268e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -784,7 +784,6 @@ pub enum GenericParamKind<'hir> { ty: &'hir Ty<'hir>, /// Optional default value for the const generic param default: Option<&'hir ConstArg<'hir>>, - synthetic: bool, }, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 9b2f8ae75fa70..25a7ae239f312 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1085,7 +1085,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>( GenericParamKind::Type { ref default, .. } => { visit_opt!(visitor, visit_ty_unambig, default) } - GenericParamKind::Const { ref ty, ref default, synthetic: _ } => { + GenericParamKind::Const { ref ty, ref default } => { try_visit!(visitor.visit_ty_unambig(ty)); if let Some(default) = default { try_visit!(visitor.visit_const_param_default(*hir_id, default)); diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index ce0e51f106f59..333cea23c4148 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -305,7 +305,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic } } - GenericParamKind::Const { ty: _, default, synthetic } => { + GenericParamKind::Const { ty: _, default } => { if default.is_some() { match param_default_policy.expect("no policy for generic param default") { ParamDefaultPolicy::Allowed => {} @@ -316,7 +316,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } } - ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic } + ty::GenericParamDefKind::Const { has_default: default.is_some() } } }; Some(ty::GenericParamDef { @@ -523,7 +523,7 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector { type Result = ControlFlow<()>; fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) -> Self::Result { - if let GenericParamKind::Const { ty, default: _, synthetic: _ } = p.kind { + if let GenericParamKind::Const { ty, default: _ } = p.kind { let prev = self.in_param_ty; self.in_param_ty = true; let res = self.visit_ty_unambig(ty); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index fc519c194bb9d..f5a64ede398ea 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -419,14 +419,7 @@ pub(crate) fn check_generic_arg_count( .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })) .count(); let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count; - let synth_const_param_count = gen_params - .own_params - .iter() - .filter(|param| { - matches!(param.kind, ty::GenericParamDefKind::Const { synthetic: true, .. }) - }) - .count(); - let named_const_param_count = param_counts.consts - synth_const_param_count; + let named_const_param_count = param_counts.consts; let infer_lifetimes = (gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params(); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index be5859b57c5e0..a89f059bb351f 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2379,7 +2379,7 @@ impl<'a> State<'a> { self.print_type(default); } } - GenericParamKind::Const { ty, ref default, synthetic: _ } => { + GenericParamKind::Const { ty, ref default } => { self.word_space(":"); self.print_type(ty); if let Some(default) = default { diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index c7b3b5415492b..b6b10e2458575 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -13,7 +13,7 @@ use crate::ty::{EarlyBinder, GenericArgsRef}; pub enum GenericParamDefKind { Lifetime, Type { has_default: bool, synthetic: bool }, - Const { has_default: bool, synthetic: bool }, + Const { has_default: bool }, } impl GenericParamDefKind { diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 5a661072bc7ee..207038db40d6e 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -656,13 +656,13 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { use crate::ty::GenericParamDefKind; - match self { + match *self { ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime, ty::GenericParamDefKind::Type { has_default, synthetic } => { - GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic } + GenericParamDefKind::Type { has_default, synthetic } } - ty::GenericParamDefKind::Const { has_default, synthetic: _ } => { - GenericParamDefKind::Const { has_default: *has_default } + ty::GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Const { has_default } } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4ff94cc6f3b64..93932936a2e0e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -557,7 +557,7 @@ fn clean_generic_param_def( }, ) } - ty::GenericParamDefKind::Const { has_default, synthetic } => ( + ty::GenericParamDefKind::Const { has_default } => ( def.name, GenericParamDefKind::Const { ty: Box::new(clean_middle_ty( @@ -580,7 +580,6 @@ fn clean_generic_param_def( } else { None }, - synthetic, }, ), }; @@ -636,14 +635,13 @@ fn clean_generic_param<'tcx>( }, ) } - hir::GenericParamKind::Const { ty, default, synthetic } => ( + hir::GenericParamKind::Const { ty, default } => ( param.name.ident().name, GenericParamDefKind::Const { ty: Box::new(clean_ty(ty, cx)), default: default.map(|ct| { Box::new(lower_const_arg_for_rustdoc(cx.tcx, ct, FeedConstTy::No).to_string()) }), - synthetic, }, ), }; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index fcff15650ce2e..dcd67cb7ebc77 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1396,7 +1396,7 @@ pub(crate) enum GenericParamDefKind { Lifetime { outlives: ThinVec }, Type { bounds: ThinVec, default: Option>, synthetic: bool }, // Option> makes this type smaller than `Option` would. - Const { ty: Box, default: Option>, synthetic: bool }, + Const { ty: Box, default: Option> }, } impl GenericParamDefKind { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index f0520716228a5..6fe94f9d291b4 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -466,7 +466,7 @@ impl FromClean for GenericParamDefKind { default: default.into_json(renderer), is_synthetic: *synthetic, }, - Const { ty, default, synthetic: _ } => GenericParamDefKind::Const { + Const { ty, default } => GenericParamDefKind::Const { type_: ty.into_json(renderer), default: default.as_ref().map(|x| x.as_ref().clone()), },