Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
006588a
codegen-llvm shim function for function aliases for macos
jdonszelmann Jan 14, 2026
d6db0ed
run tests on apple
jdonszelmann Jan 27, 2026
b147997
test backtraces
jdonszelmann Jan 27, 2026
91064bf
dont enforce tails
jdonszelmann Feb 18, 2026
88e96b8
rustc_expand: improve diagnostics for non-repeatable metavars in repe…
Unique-Usman Feb 12, 2026
37684bd
Make all multipart suggestions verbose
estebank Feb 14, 2026
6a8c42d
Add CURRENT_RUSTC_VERSION support for Clippy
blyxyas Feb 18, 2026
385eaf4
Update enzyme submodule to match upstream
ZuseZ4 Feb 18, 2026
0487f58
explicitly show behavior of <_>::assoc_fn
yaahc Feb 18, 2026
bd54cd6
Port #[rustc_doc_primitive] to the new attribute parser
Ozzy1423 Feb 16, 2026
4a0f916
fix stale comments left over from ed3711e
Zeromemer Feb 18, 2026
0512fb0
Enable "View all comments" link feature in `triagebot.toml`
Urgau Feb 18, 2026
46126ac
Rollup merge of #151733 - jdonszelmann:eii-on-apple, r=oli-obk
JonathanBrouwer Feb 19, 2026
610e63b
Rollup merge of #152558 - Unique-Usman:ua/decmacrorepeatable, r=estebank
JonathanBrouwer Feb 19, 2026
9330931
Rollup merge of #152596 - estebank:multipart_suggestions, r=petrochenkov
JonathanBrouwer Feb 19, 2026
6b227bb
Rollup merge of #152815 - blyxyas:current-rustc-version-clippy, r=Mar…
JonathanBrouwer Feb 19, 2026
9a90ad4
Rollup merge of #152733 - Ozzy1423:attr-doc, r=jdonszelmann
JonathanBrouwer Feb 19, 2026
8b74e12
Rollup merge of #152817 - ZuseZ4:update-enzyme-to-main, r=Kobzol
JonathanBrouwer Feb 19, 2026
f171394
Rollup merge of #152819 - yaahc:explicit_probe_assembly, r=Kivooeo
JonathanBrouwer Feb 19, 2026
8f8af0b
Rollup merge of #152823 - Zeromemer:fix-stale-comments, r=jhpratt
JonathanBrouwer Feb 19, 2026
cad5b1a
Rollup merge of #152824 - Urgau:triagebot-view-all-comments, r=Kobzol
JonathanBrouwer Feb 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,10 @@ impl AttributeExt for Attribute {
}
false
}

fn is_rustc_doc_primitive(&self) -> bool {
self.has_name(sym::rustc_doc_primitive)
}
}

impl Attribute {
Expand Down Expand Up @@ -935,6 +939,9 @@ pub trait AttributeExt: Debug {

/// Returns `true` is this attribute contains `doc(keyword)` or `doc(attribute)`.
fn is_doc_keyword_or_attribute(&self) -> bool;

/// Returns `true` if this is a `#[rustc_doc_primitive]` attribute.
fn is_rustc_doc_primitive(&self) -> bool;
}

// FIXME(fn_delegation): use function delegation instead of manually forwarding
Expand Down
24 changes: 24 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1319,3 +1319,27 @@ impl<S: Stage> NoArgsAttributeParser<S> for PreludeImportParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Use)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport;
}

pub(crate) struct RustcDocPrimitiveParser;

impl<S: Stage> SingleAttributeParser<S> for RustcDocPrimitiveParser {
const PATH: &[Symbol] = &[sym::rustc_doc_primitive];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
cx.expected_name_value(args.span().unwrap_or(cx.attr_span), None);
return None;
};

let Some(value_str) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
};

Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str))
}
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ attribute_parsers!(
Single<RustcDefPath>,
Single<RustcDeprecatedSafe2024Parser>,
Single<RustcDiagnosticItemParser>,
Single<RustcDocPrimitiveParser>,
Single<RustcForceInlineParser>,
Single<RustcIfThisChangedParser>,
Single<RustcLayoutScalarValidRangeEndParser>,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if let Some(pat) = finder.parent_pat {
sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string()));
}
err.multipart_suggestion_verbose(
err.multipart_suggestion(
"borrow this binding in the pattern to avoid moving the value",
sugg,
Applicability::MachineApplicable,
Expand Down Expand Up @@ -1509,7 +1509,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
} else {
"consider cloning the value if the performance cost is acceptable"
};
err.multipart_suggestion_verbose(msg, sugg, Applicability::MachineApplicable);
err.multipart_suggestion(msg, sugg, Applicability::MachineApplicable);
true
}

Expand Down Expand Up @@ -2759,7 +2759,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.chain(finder.closure_call_changes)
.collect();

err.multipart_suggestion_verbose(
err.multipart_suggestion(
"try explicitly passing `&Self` into the closure as an argument",
sugg,
Applicability::MachineApplicable,
Expand Down Expand Up @@ -3347,7 +3347,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {

let addition =
format!("let {}binding = {};\n{}", mutability, s, " ".repeat(p));
err.multipart_suggestion_verbose(
err.multipart_suggestion(
msg,
vec![
(stmt.span.shrink_to_lo(), addition),
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1511,11 +1511,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
)
}
};
err.multipart_suggestion_verbose(
msg,
sugg,
Applicability::MaybeIncorrect,
);
err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
for error in errors {
if let FulfillmentErrorCode::Select(
SelectionError::Unimplemented,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.source_map()
.indentation_before(stmt.span)
.unwrap_or_else(|| " ".to_string());
err.multipart_suggestion_verbose(
err.multipart_suggestion(
"consider cloning the value before moving it into the closure",
vec![
(
Expand Down Expand Up @@ -405,7 +405,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.source_map()
.indentation_before(closure_expr.span)
.unwrap_or_else(|| " ".to_string());
err.multipart_suggestion_verbose(
err.multipart_suggestion(
"consider cloning the value before moving it into the closure",
vec![
(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1340,7 +1340,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return;
}

err.multipart_suggestion_verbose(
err.multipart_suggestion(
format!(
"consider changing this to be a mutable {pointer_desc}{}{extra}",
if is_trait_sig {
Expand All @@ -1365,7 +1365,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if self.infcx.tcx.sess.source_map().is_imported(span) {
return;
}
err.multipart_suggestion_verbose(
err.multipart_suggestion(
"consider using `get_mut`",
vec![(span, suggestion)],
Applicability::MaybeIncorrect,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
});
if suggestions.len() > 0 {
suggestions.dedup();
diag.multipart_suggestion_verbose(
diag.multipart_suggestion(
msg!("consider restricting the type parameter to the `'static` lifetime"),
suggestions,
Applicability::MaybeIncorrect,
Expand Down Expand Up @@ -902,7 +902,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
}

diag.multipart_suggestion_verbose(
diag.multipart_suggestion(
format!(
"to declare that the trait object {captures}, you can add a lifetime parameter `'a` in the type alias"
),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ pub(crate) fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) {
}
}

pub(crate) fn count_params(llfn: &Value) -> c_uint {
LLVMCountParams(llfn)
}

/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
pub(crate) fn get_param(llfn: &Value, index: c_uint) -> &Value {
unsafe {
Expand Down
127 changes: 115 additions & 12 deletions compiler/rustc_codegen_llvm/src/mono_item.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::ffi::CString;

use rustc_abi::AddressSpace;
Expand All @@ -6,13 +7,17 @@ use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
use rustc_session::config::CrateType;
use rustc_target::callconv::{FnAbi, PassMode};
use rustc_target::spec::{Arch, RelocModel};
use tracing::debug;

use crate::abi::FnAbiLlvmExt;
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::errors::SymbolAlreadyDefined;
use crate::type_of::LayoutLlvmExt;
Expand Down Expand Up @@ -46,7 +51,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
self.assume_dso_local(g, false);

let attrs = self.tcx.codegen_instance_attrs(instance.def);
self.add_aliases(g, &attrs.foreign_item_symbol_aliases);
self.add_static_aliases(g, &attrs.foreign_item_symbol_aliases);

self.instances.borrow_mut().insert(instance, g);
}
Expand All @@ -60,11 +65,29 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
) {
assert!(!instance.args.has_infer());

let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
let attrs = self.tcx.codegen_instance_attrs(instance.def);

let lldecl =
self.predefine_without_aliases(instance, &attrs, linkage, visibility, symbol_name);
self.add_function_aliases(instance, lldecl, &attrs, &attrs.foreign_item_symbol_aliases);

self.instances.borrow_mut().insert(instance, lldecl);
}
}

impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
fn predefine_without_aliases(
&self,
instance: Instance<'tcx>,
attrs: &Cow<'_, CodegenFnAttrs>,
linkage: Linkage,
visibility: Visibility,
symbol_name: &str,
) -> &'ll llvm::Value {
let fn_abi: &FnAbi<'tcx, Ty<'tcx>> = self.fn_abi_of_instance(instance, ty::List::empty());
let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance));
llvm::set_linkage(lldecl, base::linkage_to_llvm(linkage));
let attrs = self.tcx.codegen_instance_attrs(instance.def);
base::set_link_section(lldecl, &attrs);
base::set_link_section(lldecl, attrs);
if (linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR)
&& self.tcx.sess.target.supports_comdat()
{
Expand All @@ -76,20 +99,45 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {

self.assume_dso_local(lldecl, false);

self.add_aliases(lldecl, &attrs.foreign_item_symbol_aliases);

self.instances.borrow_mut().insert(instance, lldecl);
lldecl
}
}

impl CodegenCx<'_, '_> {
fn add_aliases(&self, aliasee: &llvm::Value, aliases: &[(DefId, Linkage, Visibility)]) {
/// LLVM has the concept of an `alias`.
/// We need this for the "externally implementable items" feature,
/// though it's generally useful.
///
/// On macos, though this might be a more general problem, function symbols
/// have a fixed target architecture. This is necessary, since macos binaries
/// may contain code for both ARM and x86 macs.
///
/// LLVM *can* add attributes for target architecture to function symbols,
/// cannot do so for statics, but importantly, also cannot for aliases
/// *even* when aliases may refer to a function symbol.
///
/// This is not a problem: instead of using LLVM aliases, we can just generate
/// a new function symbol (with target architecture!) which effectively comes down to:
///
/// ```ignore (illustrative example)
/// fn alias_name(...args) {
/// original_name(...args)
/// }
/// ```
///
/// That's also an alias.
///
/// This does mean that the alias symbol has a different address than the original symbol
/// (assuming no optimizations by LLVM occur). This is unacceptable for statics.
/// So for statics we do want to use LLVM aliases, which is fine,
/// since for those we don't care about target architecture anyway.
///
/// So, this function is for static aliases. See [`add_function_aliases`](Self::add_function_aliases) for the alternative.
fn add_static_aliases(&self, aliasee: &llvm::Value, aliases: &[(DefId, Linkage, Visibility)]) {
let ty = self.get_type_of_global(aliasee);

for (alias, linkage, visibility) in aliases {
let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, *alias));
tracing::debug!("STATIC ALIAS: {alias:?} {linkage:?} {visibility:?}");

tracing::debug!("ALIAS: {alias:?} {linkage:?} {visibility:?}");
let lldecl = llvm::add_alias(
self.llmod,
ty,
Expand All @@ -103,6 +151,61 @@ impl CodegenCx<'_, '_> {
}
}

/// See [`add_static_aliases`](Self::add_static_aliases) for docs.
fn add_function_aliases(
&self,
aliasee_instance: Instance<'tcx>,
aliasee: &'ll llvm::Value,
attrs: &Cow<'_, CodegenFnAttrs>,
aliases: &[(DefId, Linkage, Visibility)],
) {
for (alias, linkage, visibility) in aliases {
let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, *alias));
tracing::debug!("FUNCTION ALIAS: {alias:?} {linkage:?} {visibility:?}");

// predefine another copy of the original instance
// with a new symbol name
let alias_lldecl = self.predefine_without_aliases(
aliasee_instance,
attrs,
*linkage,
*visibility,
symbol_name.name,
);

let fn_abi: &FnAbi<'tcx, Ty<'tcx>> =
self.fn_abi_of_instance(aliasee_instance, ty::List::empty());

// both the alias and the aliasee have the same ty
let fn_ty = fn_abi.llvm_type(self);
let start_llbb = Builder::append_block(self, alias_lldecl, "start");
let mut start_bx = Builder::build(self, start_llbb);

let num_params = llvm::count_params(alias_lldecl);
let mut args = Vec::with_capacity(num_params as usize);
for index in 0..num_params {
args.push(llvm::get_param(alias_lldecl, index));
}

let call = start_bx.call(
fn_ty,
Some(attrs),
Some(fn_abi),
aliasee,
&args,
None,
Some(aliasee_instance),
);

match &fn_abi.ret.mode {
PassMode::Ignore | PassMode::Indirect { .. } => start_bx.ret_void(),
PassMode::Direct(_) | PassMode::Pair { .. } | PassMode::Cast { .. } => {
start_bx.ret(call)
}
}
}
}

/// A definition or declaration can be assumed to be local to a group of
/// libraries that form a single DSO or executable.
/// Marks the local as DSO if so.
Expand Down
20 changes: 2 additions & 18 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,25 +838,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
}

with_fn! { with_multipart_suggestion,
/// Show a suggestion that has multiple parts to it.
/// In other words, multiple changes need to be applied as part of this suggestion.
pub fn multipart_suggestion(
&mut self,
msg: impl Into<DiagMessage>,
suggestion: Vec<(Span, String)>,
applicability: Applicability,
) -> &mut Self {
self.multipart_suggestion_with_style(
msg,
suggestion,
applicability,
SuggestionStyle::ShowCode,
)
} }

/// Show a suggestion that has multiple parts to it, always as its own subdiagnostic.
/// In other words, multiple changes need to be applied as part of this suggestion.
pub fn multipart_suggestion_verbose(
pub fn multipart_suggestion(
&mut self,
msg: impl Into<DiagMessage>,
suggestion: Vec<(Span, String)>,
Expand All @@ -868,7 +852,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
applicability,
SuggestionStyle::ShowAlways,
)
}
} }

/// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
pub fn multipart_suggestion_with_style(
Expand Down
Loading
Loading