Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6d2e82b
update rotate operation doc
notJoon Aug 11, 2025
f5a5f0f
use verbose for associated functions suggestion
chenyukang Nov 21, 2025
e802180
add suggestion for associated function
chenyukang Nov 21, 2025
1b790cd
Weak for Arc pointer is marked as DynSend/DynSync
azhogin Dec 11, 2025
04fedf7
Remove unused code in `cfg_old`
JonathanBrouwer Dec 12, 2025
acea7df
Remove last remaining usages of `UnsupportedLiteral`
JonathanBrouwer Dec 12, 2025
3f63f52
Don't pass an unused `--color` to compiletest
Zalathar Dec 12, 2025
0e7dc32
Inline `BootstrapCommand::force_coloring_in_ci` into its only call site
Zalathar Dec 12, 2025
93c3ac2
`declare_lint_pass` for `INLINE_ALWAYS_MISMATCHING_TARGET_FEATURES`
JamieCunliffe Dec 12, 2025
02bace8
Add a sanity check in case of any duplicate nodes
zetanumbers Dec 12, 2025
0ab4b8b
Remove the E0536 error code
JonathanBrouwer Dec 12, 2025
c7b5fb5
Also check in case it tries to mark red node as green
zetanumbers Dec 12, 2025
0748492
Fix: Prevent macro-expanded extern crates from shadowing extern argum…
Delta17920 Dec 10, 2025
0a3fd24
Support attribute inheritance in delegation
aerooneqq Dec 12, 2025
146711f
Use `let...else` instead of `match foo { ... _ => return };` and `if …
estebank Dec 9, 2025
a49c175
`#![deny(clippy::manual_let_else)]` in some rustc modules
estebank Dec 9, 2025
97c7742
revert one change from rustc_next_trait_solver
estebank Dec 12, 2025
397339e
Rollup merge of #145278 - notJoon:doc/rotate-operation, r=antoyo
jhpratt Dec 13, 2025
b32845c
Rollup merge of #148837 - estebank:let-else, r=Kivooeo
jhpratt Dec 13, 2025
d175f11
Rollup merge of #149177 - chenyukang:yukang-fix-assoc-func-149038, r=…
jhpratt Dec 13, 2025
e7ba4a5
Rollup merge of #149843 - aerooneqq:inherit-attributes-in-delegation,…
jhpratt Dec 13, 2025
47f1502
Rollup merge of #149860 - Delta17920:fix/149821-root-cause, r=petroch…
jhpratt Dec 13, 2025
bcde603
Rollup merge of #149874 - azhogin:azhogin/arc_weak_dyn_send_sync, r=e…
jhpratt Dec 13, 2025
6b29f18
Rollup merge of #149903 - JonathanBrouwer:cfg_old_cleanup, r=jdonszel…
jhpratt Dec 13, 2025
aec4781
Rollup merge of #149911 - Zalathar:no-color, r=jieyouxu
jhpratt Dec 13, 2025
754b4a4
Rollup merge of #149916 - zetanumbers:double_node_sanity, r=petrochenkov
jhpratt Dec 13, 2025
3eba6b1
Rollup merge of #149924 - JamieCunliffe:inline-lint-unknown, r=davidtwco
jhpratt Dec 13, 2025
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: 3 additions & 4 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1533,11 +1533,10 @@ impl Expr {
// then type of result is trait object.
// Otherwise we don't assume the result type.
ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => {
if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) {
TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
} else {
let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) else {
return None;
}
};
TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
}

ExprKind::Underscore => TyKind::Infer,
Expand Down
19 changes: 8 additions & 11 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,20 +447,17 @@ impl MetaItem {
thin_vec![PathSegment::path_root(span)]
};
loop {
if let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
iter.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref()
{
segments.push(PathSegment::from_ident(Ident::new(name, span)));
} else {
else {
return None;
}
if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) =
iter.peek()
{
iter.next();
} else {
};
segments.push(PathSegment::from_ident(Ident::new(name, span)));
let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) = iter.peek()
else {
break;
}
};
iter.next();
}
let span = span.with_hi(segments.last().unwrap().ident.span.hi());
Path { span, segments, tokens: None }
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(array_windows))]
#![deny(clippy::manual_let_else)]
#![doc(test(attr(deny(warnings), allow(internal_features))))]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
Expand Down
156 changes: 133 additions & 23 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ use hir::def::{DefKind, PartialRes, Res};
use hir::{BodyId, HirId};
use rustc_abi::ExternAbi;
use rustc_ast::*;
use rustc_attr_parsing::{AttributeParser, ShouldEmit};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::Target;
use rustc_hir::attrs::{AttributeKind, InlineAttr};
use rustc_hir::def_id::DefId;
use rustc_middle::span_bug;
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
use rustc_middle::ty::{Asyncness, DelegationFnSigAttrs, ResolverAstLowering};
use rustc_span::symbol::kw;
use rustc_span::{Ident, Span, Symbol};
use rustc_span::{DUMMY_SP, Ident, Span, Symbol};
use {rustc_ast as ast, rustc_hir as hir};

use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
Expand All @@ -62,6 +64,41 @@ pub(crate) struct DelegationResults<'hir> {
pub generics: &'hir hir::Generics<'hir>,
}

struct AttributeAdditionInfo {
pub equals: fn(&hir::Attribute) -> bool,
pub kind: AttributeAdditionKind,
}

enum AttributeAdditionKind {
Default { factory: fn(Span) -> hir::Attribute },
Inherit { flag: DelegationFnSigAttrs, factory: fn(Span, &hir::Attribute) -> hir::Attribute },
}

const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;

static ATTRIBUTES_ADDITIONS: &[AttributeAdditionInfo] = &[
AttributeAdditionInfo {
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::MustUse { .. })),
kind: AttributeAdditionKind::Inherit {
factory: |span, original_attribute| {
let reason = match original_attribute {
hir::Attribute::Parsed(AttributeKind::MustUse { reason, .. }) => *reason,
_ => None,
};

hir::Attribute::Parsed(AttributeKind::MustUse { span, reason })
},
flag: DelegationFnSigAttrs::MUST_USE,
},
},
AttributeAdditionInfo {
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))),
kind: AttributeAdditionKind::Default {
factory: |span| hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span)),
},
},
];

impl<'hir> LoweringContext<'_, 'hir> {
fn is_method(&self, def_id: DefId, span: Span) -> bool {
match self.tcx.def_kind(def_id) {
Expand All @@ -88,7 +125,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
match sig_id {
Ok(sig_id) => {
self.add_inline_attribute_if_needed(span);
self.add_attributes_if_needed(span, sig_id);

let is_method = self.is_method(sig_id, span);
let (param_count, c_variadic) = self.param_count(sig_id);
Expand All @@ -103,29 +140,100 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn add_inline_attribute_if_needed(&mut self, span: Span) {
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
let create_inline_attr_slice =
|| [hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span))];

let new_attributes = match self.attrs.get(&PARENT_ID) {
Some(attrs) => {
// Check if reuse already specifies any inline attribute, if so, do nothing
if attrs
.iter()
.any(|a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))))
fn add_attributes_if_needed(&mut self, span: Span, sig_id: DefId) {
let new_attributes = self.create_new_attributes(
ATTRIBUTES_ADDITIONS,
span,
sig_id,
self.attrs.get(&PARENT_ID),
);

if new_attributes.is_empty() {
return;
}

let new_arena_allocated_attributes = match self.attrs.get(&PARENT_ID) {
Some(existing_attrs) => self.arena.alloc_from_iter(
existing_attrs.iter().map(|a| a.clone()).chain(new_attributes.into_iter()),
),
None => self.arena.alloc_from_iter(new_attributes.into_iter()),
};

self.attrs.insert(PARENT_ID, new_arena_allocated_attributes);
}

fn create_new_attributes(
&self,
candidate_additions: &[AttributeAdditionInfo],
span: Span,
sig_id: DefId,
existing_attrs: Option<&&[hir::Attribute]>,
) -> Vec<hir::Attribute> {
let local_original_attributes = self.parse_local_original_attributes(sig_id);

candidate_additions
.iter()
.filter_map(|addition_info| {
if let Some(existing_attrs) = existing_attrs
&& existing_attrs
.iter()
.any(|existing_attr| (addition_info.equals)(existing_attr))
{
return;
return None;
}

self.arena.alloc_from_iter(
attrs.into_iter().map(|a| a.clone()).chain(create_inline_attr_slice()),
)
}
None => self.arena.alloc_from_iter(create_inline_attr_slice()),
};
match addition_info.kind {
AttributeAdditionKind::Default { factory } => Some(factory(span)),
AttributeAdditionKind::Inherit { flag, factory } => {
let original_attribute = match sig_id.as_local() {
Some(local_id) => self
.resolver
.delegation_fn_sigs
.get(&local_id)
.is_some_and(|sig| sig.attrs_flags.contains(flag))
.then(|| {
local_original_attributes
.as_ref()
.map(|attrs| {
attrs
.iter()
.find(|base_attr| (addition_info.equals)(base_attr))
})
.flatten()
})
.flatten(),
None => self
.tcx
.get_all_attrs(sig_id)
.iter()
.find(|base_attr| (addition_info.equals)(base_attr)),
};

self.attrs.insert(PARENT_ID, new_attributes);
original_attribute.map(|a| factory(span, a))
}
}
})
.collect::<Vec<_>>()
}

fn parse_local_original_attributes(&self, sig_id: DefId) -> Option<Vec<hir::Attribute>> {
if let Some(local_id) = sig_id.as_local()
&& let Some(info) = self.resolver.delegation_fn_sigs.get(&local_id)
&& !info.to_inherit_attrs.is_empty()
{
Some(AttributeParser::parse_limited_all(
self.tcx.sess,
info.to_inherit_attrs.as_slice(),
None,
Target::Fn,
DUMMY_SP,
DUMMY_NODE_ID,
Some(self.tcx.features()),
ShouldEmit::Nothing,
))
} else {
None
}
}

fn get_delegation_sig_id(
Expand Down Expand Up @@ -220,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
// and here we need the hir attributes.
let default_safety =
if sig.target_feature || self.tcx.def_kind(parent) == DefKind::ForeignMod {
if sig.attrs_flags.contains(DelegationFnSigAttrs::TARGET_FEATURE)
|| self.tcx.def_kind(parent) == DefKind::ForeignMod
{
hir::Safety::Unsafe
} else {
hir::Safety::Safe
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_attr_parsing/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ attr_parsing_bundle_needs_static =

attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters

attr_parsing_cfg_predicate_identifier =
`cfg` predicate key must be an identifier

attr_parsing_deprecated_item_suggestion =
suggestions on deprecated items are unstable
.help = add `#![feature(deprecated_suggestion)]` to the crate root
Expand Down Expand Up @@ -41,9 +38,6 @@ attr_parsing_empty_link_name =
link name must not be empty
.label = empty link name

attr_parsing_expected_one_cfg_pattern =
expected 1 cfg-pattern

attr_parsing_expected_single_version_literal =
expected single version literal

Expand Down Expand Up @@ -241,12 +235,6 @@ attr_parsing_unstable_cfg_target_compact =
attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable
.help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`

attr_parsing_unsupported_literal_cfg_boolean =
literal in `cfg` predicate value must be a boolean
attr_parsing_unsupported_literal_cfg_string =
literal in `cfg` predicate value must be a string
attr_parsing_unsupported_literal_generic =
unsupported literal
attr_parsing_unsupported_literal_suggestion =
consider removing the prefix

Expand Down
22 changes: 20 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, ast, token};
use rustc_errors::{Applicability, PResult};
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate, Features, template};
use rustc_feature::{
AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template,
};
use rustc_hir::attrs::CfgEntry;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{AttrPath, RustcVersion};
Expand All @@ -23,7 +25,7 @@ use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
ParsedDescription,
};
use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics, try_gate_cfg};
use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics};

pub const CFG_TEMPLATE: AttributeTemplate = template!(
List: &["predicate"],
Expand Down Expand Up @@ -410,3 +412,19 @@ fn parse_cfg_attr_internal<'a>(

Ok((cfg_predicate, expanded_attrs))
}

fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
let gate = find_gated_cfg(|sym| sym == name);
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
gate_cfg(gated_cfg, span, sess, feats);
}
}

#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
let (cfg, feature, has_feature) = gated_cfg;
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
let explain = format!("`cfg({cfg})` is experimental and subject to change");
feature_err(sess, *feature, cfg_span, explain).emit();
}
}
Loading
Loading