Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
14f4690
Silence recursive RUSTC_LOG_FORMAT_JSON messages
khyperia May 31, 2026
f3a0d22
apply Cortex-A53 errata 843419 mitigation to the AArch64 Linux targets
japaric Apr 17, 2026
1fcc953
`#[inline]` for `Encode` and `Decode`
cyrgani Jun 3, 2026
fb79578
`#[inline]` for `Mark`
cyrgani Jun 3, 2026
9aeb7c0
add regression tests
qaijuang Jun 4, 2026
8e63eff
don't link doc(hidden) associated type projections
qaijuang Jun 4, 2026
31e3588
Do not always generate first delegation argument
aerooneqq Jun 4, 2026
fa56cfe
add UI test for invalid LLVM target in custom target
TaKO8Ki Jun 5, 2026
e2cc7e6
avoid ICE when formatting TargetMachine config errors
TaKO8Ki Jun 5, 2026
29545e2
Forbid optimize(none) with inline(always) or inline.
veluca93 Jun 5, 2026
dfa5c7b
Add a smoke test for the optimize attribute.
veluca93 Jun 5, 2026
0071bd1
Warn when `#[macro_use]` or `#[macro_escape]` is used on the crate root
JonathanBrouwer Jun 5, 2026
26acc2a
chore : Remove unused properties
lms0806 Jun 5, 2026
c34ea95
Add @aapoalas to libs review rotation
aapoalas Jun 2, 2026
a408c6a
Rollup merge of #155453 - ferrocene:a53-linux-fix-errata, r=wesleywiser
GuillaumeGomez Jun 5, 2026
7705e92
Rollup merge of #156798 - aerooneqq:delegation-dont-generate-first-ar…
GuillaumeGomez Jun 5, 2026
70458f2
Rollup merge of #157438 - qaijuang:rustdoc-hidden-assoc-type-link, r=…
GuillaumeGomez Jun 5, 2026
cc27261
Rollup merge of #157450 - cyrgani:pm-inline, r=petrochenkov
GuillaumeGomez Jun 5, 2026
b01e3ad
Rollup merge of #157190 - khyperia:nonrecursive-tracing-json, r=jieyouxu
GuillaumeGomez Jun 5, 2026
d32da0c
Rollup merge of #157396 - aapoalas:aapoalas-libs-review-rotation, r=a…
GuillaumeGomez Jun 5, 2026
3778d94
Rollup merge of #157470 - TaKO8Ki:fix-target-machine-config-diag-ice,…
GuillaumeGomez Jun 5, 2026
3232177
Rollup merge of #157474 - veluca93:optimize-error-optimize-inline, r=…
GuillaumeGomez Jun 5, 2026
0339b64
Rollup merge of #157475 - veluca93:optimize-smoke, r=jieyouxu
GuillaumeGomez Jun 5, 2026
46a6974
Rollup merge of #157479 - JonathanBrouwer:macro-use-root, r=Kivooeo
GuillaumeGomez Jun 5, 2026
cd56fd8
Rollup merge of #157486 - lms0806:issue_157478, r=JonathanBrouwer
GuillaumeGomez Jun 5, 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
9 changes: 8 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3908,6 +3908,13 @@ pub struct EiiImpl {
pub is_default: bool,
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable, PartialEq, Eq)]
pub enum DelegationSource {
Single,
List,
Glob,
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Delegation {
/// Path resolution id.
Expand All @@ -3918,7 +3925,7 @@ pub struct Delegation {
pub rename: Option<Ident>,
pub body: Option<Box<Block>>,
/// The item was expanded from a glob delegation item.
pub from_glob: bool,
pub source: DelegationSource,
}

impl Delegation {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ macro_rules! common_visitor_and_walkers {
Delegation,
DelegationMac,
DelegationSuffixes,
DelegationSource,
DelimArgs,
DelimSpan,
EnumDef,
Expand Down
107 changes: 92 additions & 15 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,29 @@
//! also be emitted during HIR ty lowering.

use std::iter;
use std::ops::ControlFlow;

use ast::visit::Visitor;
use hir::def::{DefKind, Res};
use hir::{BodyId, HirId};
use rustc_abi::ExternAbi;
use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_ast::*;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir::attrs::{AttributeKind, InlineAttr};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, FnDeclFlags};
use rustc_middle::span_bug;
use rustc_middle::ty::{Asyncness, TyCtxt};
use rustc_middle::ty::{Asyncness, PerOwnerResolverData, TyCtxt};
use rustc_span::symbol::kw;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};

use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults};
use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee};
use crate::errors::{
CycleInDelegationSignatureResolution, DelegationAttemptedBlockWithDefsDeletion,
DelegationBlockSpecifiedWhenNoParams, UnresolvedDelegationCallee,
};
use crate::{
AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
ResolverAstLoweringExt, index_crate,
Expand Down Expand Up @@ -198,10 +203,14 @@ impl<'hir> LoweringContext<'_, 'hir> {

let (param_count, c_variadic) = self.param_count(sig_id);

if !self.check_block_soundness(delegation, sig_id, is_method, param_count) {
return self.generate_delegation_error(span, delegation);
}

let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method);

let (body_id, call_expr_id) =
self.lower_delegation_body(delegation, is_method, param_count, &mut generics, span);
self.lower_delegation_body(delegation, sig_id, param_count, &mut generics, span);

let decl = self.lower_delegation_decl(
sig_id,
Expand All @@ -227,6 +236,82 @@ impl<'hir> LoweringContext<'_, 'hir> {
DelegationResults { body_id, sig, ident, generics }
}

fn check_block_soundness(
&self,
delegation: &Delegation,
sig_id: DefId,
is_method: bool,
param_count: usize,
) -> bool {
let Some(block) = delegation.body.as_ref() else { return true };
let should_generate_block = self.should_generate_block(delegation, sig_id, is_method);

// Report an error if user has explicitly specified delegation's target expression
// in a single delegation when reused function has no params.
if param_count == 0 && should_generate_block {
self.dcx().emit_err(DelegationBlockSpecifiedWhenNoParams { span: block.span });
return false;
}

struct DefinitionsFinder<'a> {
all_owners: &'a NodeMap<PerOwnerResolverData<'a>>,
// `self.owner.node_id_to_def_id`
nested_def_ids: &'a NodeMap<LocalDefId>,
}

impl<'a> ast::visit::Visitor<'a> for DefinitionsFinder<'a> {
type Result = ControlFlow<()>;

fn visit_id(&mut self, id: NodeId) -> Self::Result {
/*
(from `tests\ui\delegation\target-expr-removal-defs-inside.rs`):
```rust
reuse impl Trait for S1 {
some::path::<{ fn foo() {} }>::xd();
fn foo() {}
self.0
}
```

Constant from unresolved path will be in `nested_owners`,
`fn foo() {}` will not be in `nested_owners` but will be in `owners`,
both have `LocalDefId`, so we check those two maps.
*/
match self.all_owners.contains_key(&id) || self.nested_def_ids.contains_key(&id) {
true => ControlFlow::Break(()),
false => ControlFlow::Continue(()),
}
}
}

let mut collector = DefinitionsFinder {
all_owners: &self.resolver.owners,
nested_def_ids: &self.owner.node_id_to_def_id,
};

let contains_defs = collector.visit_block(block).is_break();

// If there are definitions inside and we can't delete target expression, so report an error.
// FIXME(fn_delegation): support deletion of target expression with defs inside.
if !should_generate_block && contains_defs {
self.dcx().emit_err(DelegationAttemptedBlockWithDefsDeletion { span: block.span });
return false;
}

true
}

fn should_generate_block(
&self,
delegation: &Delegation,
sig_id: DefId,
is_method: bool,
) -> bool {
is_method
|| matches!(self.tcx.def_kind(sig_id), DefKind::Fn)
|| matches!(delegation.source, DelegationSource::Single)
}

fn add_attrs_if_needed(&mut self, span: Span, sig_id: DefId) {
let new_attrs =
self.create_new_attrs(ATTRS_ADDITIONS, span, sig_id, self.attrs.get(&PARENT_ID));
Expand Down Expand Up @@ -415,7 +500,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_delegation_body(
&mut self,
delegation: &Delegation,
is_method: bool,
sig_id: DefId,
param_count: usize,
generics: &mut GenericsGenerationResults<'hir>,
span: Span,
Expand All @@ -428,6 +513,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut args: Vec<hir::Expr<'_>> = Vec::with_capacity(param_count);
let mut stmts: &[hir::Stmt<'hir>] = &[];

let is_method = this.is_method(sig_id, span);

for idx in 0..param_count {
let (param, pat_node_id) = this.generate_param(is_method, idx, span);
parameters.push(param);
Expand All @@ -437,6 +524,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

let arg = if let Some(block) = block
&& idx == 0
&& this.should_generate_block(delegation, sig_id, is_method)
{
let mut self_resolver = SelfResolver {
ctxt: this,
Expand Down Expand Up @@ -467,17 +555,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
args.push(arg);
}

// If we have no params in signature function but user still wrote some code in
// delegation body, then add this code as first arg, eventually an error will be shown,
// also nested delegations may need to access information about this code (#154332),
// so it is better to leave this code as opposed to bodies of extern functions,
// which are completely erased from existence.
if param_count == 0
&& let Some(block) = block
{
args.push(this.lower_block_expr(&block));
}

let (final_expr, hir_id) =
this.finalize_body_lowering(delegation, stmts, args, generics, span);

Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,3 +535,17 @@ pub(crate) struct CycleInDelegationSignatureResolution {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("delegation's target expression is specified for function with no params")]
pub(crate) struct DelegationBlockSpecifiedWhenNoParams {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("attempted to delete delegation's target expression that contains definitions inside")]
pub(crate) struct DelegationAttemptedBlockWithDefsDeletion {
#[primary_span]
pub span: Span,
}
1 change: 0 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const MACRO_USE_TEMPLATE: AttributeTemplate = template!(
const MACRO_USE_ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::Mod),
Allow(Target::ExternCrate),
Allow(Target::Crate),
Error(Target::WherePredicate),
]);

Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_codegen_llvm/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);

impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
let diag: Diag<'_, G> = self.0.into_diag(dcx, level);
// Reuse the formatted primary message from `LlvmError` without emitting it.
let diag: Diag<'_, ()> = self.0.into_diag(dcx, level);
let (message, _) = diag.messages.first().expect("`LlvmError` with no message");
let message = format_diag_message(message, &diag.args);
let message = format_diag_message(message, &diag.args).into_owned();
diag.cancel();

Diag::new(
dcx,
level,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,11 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>(
ident: rename.unwrap_or(ident),
rename,
body: deleg.body.clone(),
from_glob,
source: if from_glob {
ast::DelegationSource::Glob
} else {
ast::DelegationSource::List
},
})),
tokens: None,
}
Expand Down
108 changes: 106 additions & 2 deletions compiler/rustc_log/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,20 @@
//! debugging, you can make changes inside those crates and quickly run main.rs
//! to read the debug logs.

use std::cell::Cell;
use std::env::{self, VarError};
use std::fmt::{self, Display};
use std::fs::File;
use std::io::{self, IsTerminal};
use std::sync::Mutex;

use tracing::dispatcher::SetGlobalDefaultError;
use tracing::{Event, Subscriber};
use tracing::{Event, Subscriber, span};
use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter};
use tracing_subscriber::fmt::FmtContext;
use tracing_subscriber::fmt::format::{self, FmtSpan, FormatEvent, FormatFields};
use tracing_subscriber::fmt::writer::BoxMakeWriter;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::layer::{Context, SubscriberExt};
use tracing_subscriber::{Layer, Registry};
// Re-export tracing
pub use {tracing, tracing_core, tracing_subscriber};
Expand Down Expand Up @@ -175,6 +176,7 @@ where
.with_thread_ids(verbose_thread_ids)
.with_thread_names(verbose_thread_ids)
.with_span_events(FmtSpan::ACTIVE);
let fmt_layer = NonrecursiveLayer { inner: fmt_layer };
Layer::boxed(fmt_layer)
} else {
let mut layer = tracing_tree::HierarchicalLayer::default()
Expand Down Expand Up @@ -286,3 +288,105 @@ impl From<SetGlobalDefaultError> for Error {
Error::AlreadyInit(tracing_error)
}
}

thread_local! {
static NONRECURSIVE_GUARD_LOCK: Cell<bool> = const { Cell::new(false) };
}

struct NonrecursiveGuard;

impl NonrecursiveGuard {
fn lock() -> Option<NonrecursiveGuard> {
if !NONRECURSIVE_GUARD_LOCK.replace(true) { Some(NonrecursiveGuard) } else { None }
}
}

impl Drop for NonrecursiveGuard {
fn drop(&mut self) {
NONRECURSIVE_GUARD_LOCK.set(false);
}
}

/// Many debug messages that rustc emits produce additional debug messages when formatting the
/// arguments to the original debug message. [`tracing_tree::HierarchicalLayer`] (used by the
/// default output format) filters these out, but [`tracing_subscriber::fmt::format::Json`] (used by
/// `RUSTC_LOG_FORMAT_JSON`) does not. So, implement a simple recursion check to filter these
/// messages out.
struct NonrecursiveLayer<S> {
inner: S,
}

impl<S: Subscriber, L: Layer<S>> Layer<S> for NonrecursiveLayer<L> {
fn on_register_dispatch(&self, subscriber: &tracing::Dispatch) {
self.inner.on_register_dispatch(subscriber)
}

fn on_layer(&mut self, subscriber: &mut S) {
self.inner.on_layer(subscriber)
}

fn register_callsite(
&self,
metadata: &'static tracing::Metadata<'static>,
) -> tracing_core::Interest {
self.inner.register_callsite(metadata)
}

fn enabled(&self, metadata: &tracing::Metadata<'_>, ctx: Context<'_, S>) -> bool {
self.inner.enabled(metadata, ctx)
}

fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
if let Some(_) = NonrecursiveGuard::lock() {
self.inner.on_new_span(attrs, id, ctx)
}
}

fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
if let Some(_) = NonrecursiveGuard::lock() {
self.inner.on_record(span, values, ctx)
}
}

fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, S>) {
if let Some(_) = NonrecursiveGuard::lock() {
self.inner.on_follows_from(span, follows, ctx)
}
}

fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool {
if let Some(_) = NonrecursiveGuard::lock() {
self.inner.event_enabled(event, ctx)
} else {
false
}
}

fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
if let Some(_) = NonrecursiveGuard::lock() {
self.inner.on_event(event, ctx)
}
}

fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
if let Some(_) = NonrecursiveGuard::lock() {
self.inner.on_enter(id, ctx)
}
}

fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
if let Some(_) = NonrecursiveGuard::lock() {
self.inner.on_exit(id, ctx)
}
}

fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
if let Some(_) = NonrecursiveGuard::lock() {
self.inner.on_close(id, ctx)
}
}

fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: Context<'_, S>) {
self.inner.on_id_change(old, new, ctx)
}
}
Loading
Loading