Skip to content

Commit 226f00a

Browse files
committed
WIP on attributes inheritance
1 parent f520900 commit 226f00a

File tree

3 files changed

+138
-27
lines changed

3 files changed

+138
-27
lines changed

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 111 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ use rustc_errors::ErrorGuaranteed;
4747
use rustc_hir::attrs::{AttributeKind, InlineAttr};
4848
use rustc_hir::def_id::DefId;
4949
use rustc_middle::span_bug;
50-
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
50+
use rustc_middle::ty::{Asyncness, DelegationFnSigAttrs, ResolverAstLowering};
5151
use rustc_span::symbol::kw;
52-
use rustc_span::{Ident, Span, Symbol};
52+
use rustc_span::{Ident, Span, Symbol, sym};
5353
use {rustc_ast as ast, rustc_hir as hir};
5454

5555
use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
@@ -62,6 +62,40 @@ pub(crate) struct DelegationResults<'hir> {
6262
pub generics: &'hir hir::Generics<'hir>,
6363
}
6464

65+
struct AttributeAdditionInfo {
66+
pub factory: fn(Span) -> hir::Attribute,
67+
pub equals: fn(&hir::Attribute) -> bool,
68+
pub kind: AttributeAdditionKind,
69+
}
70+
71+
struct AttributeAdditionStatus {
72+
pub info: &'static AttributeAdditionInfo,
73+
pub already_exists: bool,
74+
}
75+
76+
enum AttributeAdditionKind {
77+
Default,
78+
Inherit { symbol: Symbol, flag: DelegationFnSigAttrs },
79+
}
80+
81+
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
82+
83+
static ATTRS_ADDITIONS: &'static [AttributeAdditionInfo; 2] = &[
84+
AttributeAdditionInfo {
85+
factory: |span| hir::Attribute::Parsed(AttributeKind::MustUse { span, reason: None }),
86+
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::MustUse { .. })),
87+
kind: AttributeAdditionKind::Inherit {
88+
symbol: sym::must_use,
89+
flag: DelegationFnSigAttrs::MUST_USE,
90+
},
91+
},
92+
AttributeAdditionInfo {
93+
factory: |span| hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span)),
94+
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))),
95+
kind: AttributeAdditionKind::Default,
96+
},
97+
];
98+
6599
impl<'hir> LoweringContext<'_, 'hir> {
66100
fn is_method(&self, def_id: DefId, span: Span) -> bool {
67101
match self.tcx.def_kind(def_id) {
@@ -88,7 +122,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
88122
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
89123
match sig_id {
90124
Ok(sig_id) => {
91-
self.add_inline_attribute_if_needed(span);
125+
self.add_attributes_if_needed(span, sig_id);
92126

93127
let is_method = self.is_method(sig_id, span);
94128
let (param_count, c_variadic) = self.param_count(sig_id);
@@ -103,29 +137,80 @@ impl<'hir> LoweringContext<'_, 'hir> {
103137
}
104138
}
105139

106-
fn add_inline_attribute_if_needed(&mut self, span: Span) {
107-
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
108-
let create_inline_attr_slice =
109-
|| [hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span))];
110-
111-
let new_attributes = match self.attrs.get(&PARENT_ID) {
112-
Some(attrs) => {
113-
// Check if reuse already specifies any inline attribute, if so, do nothing
114-
if attrs
115-
.iter()
116-
.any(|a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))))
117-
{
118-
return;
119-
}
140+
fn add_attributes_if_needed(&mut self, span: Span, sig_id: DefId) {
141+
let mut candidate_additions = ATTRS_ADDITIONS
142+
.iter()
143+
.map(|a| AttributeAdditionStatus { info: a, already_exists: false })
144+
.collect::<Vec<_>>();
120145

121-
self.arena.alloc_from_iter(
122-
attrs.into_iter().map(|a| a.clone()).chain(create_inline_attr_slice()),
123-
)
124-
}
125-
None => self.arena.alloc_from_iter(create_inline_attr_slice()),
146+
self.check_if_attributes_already_exist(&mut candidate_additions);
147+
let new_attributes = self.create_new_attributes(&candidate_additions, span, sig_id);
148+
149+
if new_attributes.is_empty() {
150+
return;
151+
}
152+
153+
let new_arena_allocated_attributes = match self.attrs.get(&PARENT_ID) {
154+
Some(existing_attrs) => self.arena.alloc_from_iter(
155+
existing_attrs.iter().map(|a| a.clone()).chain(new_attributes.into_iter()),
156+
),
157+
None => self.arena.alloc_from_iter(new_attributes.into_iter()),
126158
};
127159

128-
self.attrs.insert(PARENT_ID, new_attributes);
160+
self.attrs.insert(PARENT_ID, new_arena_allocated_attributes);
161+
}
162+
163+
fn check_if_attributes_already_exist(
164+
&mut self,
165+
candidate_additions: &mut Vec<AttributeAdditionStatus>,
166+
) {
167+
if let Some(existing_attrs) = self.attrs.get(&PARENT_ID) {
168+
for attr in existing_attrs.iter() {
169+
for addition in candidate_additions.iter_mut() {
170+
if addition.already_exists {
171+
continue;
172+
}
173+
174+
if (addition.info.equals)(attr) {
175+
addition.already_exists = true;
176+
}
177+
}
178+
}
179+
}
180+
}
181+
182+
fn create_new_attributes(
183+
&mut self,
184+
candidate_additions: &Vec<AttributeAdditionStatus>,
185+
span: Span,
186+
sig_id: DefId,
187+
) -> Vec<hir::Attribute> {
188+
candidate_additions
189+
.into_iter()
190+
.filter_map(|a| match a.already_exists {
191+
true => None,
192+
false => match a.info.kind {
193+
AttributeAdditionKind::Default => Some((a.info.factory)(span)),
194+
AttributeAdditionKind::Inherit { symbol, flag } => {
195+
// Check if an anttribute present on the target of delegation,
196+
// either in this crate or others
197+
let should_inherit = match sig_id.as_local() {
198+
None => self.tcx.get_attr(sig_id, symbol).is_some(),
199+
Some(local_id) => self
200+
.resolver
201+
.delegation_fn_sigs
202+
.get(&local_id)
203+
.is_some_and(|sig| sig.attrs_flags.contains(flag)),
204+
};
205+
206+
match should_inherit {
207+
true => Some((a.info.factory)(span)),
208+
false => None,
209+
}
210+
}
211+
},
212+
})
213+
.collect::<Vec<_>>()
129214
}
130215

131216
fn get_delegation_sig_id(
@@ -220,7 +305,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
220305
// We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
221306
// and here we need the hir attributes.
222307
let default_safety =
223-
if sig.target_feature || self.tcx.def_kind(parent) == DefKind::ForeignMod {
308+
if sig.attrs_flags.contains(DelegationFnSigAttrs::TARGET_FEATURE)
309+
|| self.tcx.def_kind(parent) == DefKind::ForeignMod
310+
{
224311
hir::Safety::Unsafe
225312
} else {
226313
hir::Safety::Safe

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,21 @@ pub struct ResolverAstLowering {
221221
pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
222222
}
223223

224+
bitflags::bitflags! {
225+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
226+
pub struct DelegationFnSigAttrs: u8 {
227+
const TARGET_FEATURE = 1 << 0;
228+
const MUST_USE = 1 << 1;
229+
}
230+
}
231+
224232
#[derive(Debug)]
225233
pub struct DelegationFnSig {
226234
pub header: ast::FnHeader,
227235
pub param_count: usize,
228236
pub has_self: bool,
229237
pub c_variadic: bool,
230-
pub target_feature: bool,
238+
pub attrs_flags: DelegationFnSigAttrs,
231239
}
232240

233241
#[derive(Clone, Copy, Debug, HashStable)]

compiler/rustc_resolve/src/late.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par
2828
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
2929
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
3030
use rustc_middle::middle::resolve_bound_vars::Set1;
31-
use rustc_middle::ty::{AssocTag, DelegationFnSig, Visibility};
31+
use rustc_middle::ty::{AssocTag, DelegationFnSig, DelegationFnSigAttrs, Visibility};
3232
use rustc_middle::{bug, span_bug};
3333
use rustc_session::config::{CrateType, ResolveDocLinks};
3434
use rustc_session::lint;
@@ -5294,13 +5294,29 @@ impl ItemInfoCollector<'_, '_, '_> {
52945294
id: NodeId,
52955295
attrs: &[Attribute],
52965296
) {
5297+
static NAMES_TO_FLAGS: [(Symbol, DelegationFnSigAttrs); 2] = [
5298+
(sym::target_feature, DelegationFnSigAttrs::TARGET_FEATURE),
5299+
(sym::must_use, DelegationFnSigAttrs::MUST_USE),
5300+
];
5301+
5302+
let mut attrs_flags = DelegationFnSigAttrs::empty();
5303+
for attr in attrs {
5304+
for (name, flag) in NAMES_TO_FLAGS {
5305+
if !attrs_flags.contains(flag) && attr.has_name(name) {
5306+
attrs_flags.set(flag, true);
5307+
continue;
5308+
}
5309+
}
5310+
}
5311+
52975312
let sig = DelegationFnSig {
52985313
header,
52995314
param_count: decl.inputs.len(),
53005315
has_self: decl.has_self(),
53015316
c_variadic: decl.c_variadic(),
5302-
target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)),
5317+
attrs_flags,
53035318
};
5319+
53045320
self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
53055321
}
53065322
}

0 commit comments

Comments
 (0)