rustc_ast_lowering/delegation/
attributes.rs1use rustc_attr_ir::{AttributeKind, InlineAttr};
2use rustc_hir as hir;
3use rustc_span::Span;
4use rustc_span::def_id::DefId;
5
6use crate::LoweringContext;
7use crate::delegation::DelegationResolution;
8
9struct AdditionInfo {
10 pub equals: fn(&rustc_attr_ir::Attribute) -> bool,
11 pub kind: AdditionKind,
12}
13
14enum AdditionKind {
15 Default { factory: fn(Span) -> rustc_attr_ir::Attribute },
16 Inherit { factory: fn(Span, &rustc_attr_ir::Attribute) -> rustc_attr_ir::Attribute },
17}
18
19static ADDITIONS: &[AdditionInfo] = &[
20 AdditionInfo {
21 equals: |a| #[allow(non_exhaustive_omitted_patterns)] match a {
rustc_attr_ir::Attribute::Parsed(AttributeKind::MustUse { .. }) => true,
_ => false,
}matches!(a, rustc_attr_ir::Attribute::Parsed(AttributeKind::MustUse { .. })),
22 kind: AdditionKind::Inherit {
23 factory: |span, original_attr| {
24 let reason = match original_attr {
25 rustc_attr_ir::Attribute::Parsed(AttributeKind::MustUse { reason, .. }) => {
26 *reason
27 }
28 _ => None,
29 };
30
31 rustc_attr_ir::Attribute::Parsed(AttributeKind::MustUse { span, reason })
32 },
33 },
34 },
35 AdditionInfo {
36 equals: |a| #[allow(non_exhaustive_omitted_patterns)] match a {
rustc_attr_ir::Attribute::Parsed(AttributeKind::Inline(..)) => true,
_ => false,
}matches!(a, rustc_attr_ir::Attribute::Parsed(AttributeKind::Inline(..))),
37 kind: AdditionKind::Default {
38 factory: |span| {
39 rustc_attr_ir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span))
40 },
41 },
42 },
43];
44
45impl<'hir> LoweringContext<'_, 'hir> {
46 pub(super) fn add_attrs_if_needed(&mut self, resolution: &DelegationResolution) {
47 let &DelegationResolution { span, sig_id, .. } = resolution;
48
49 const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
50 let new_attrs = self.create_new_attrs(span, sig_id, self.curr_owner.attrs.get(&PARENT_ID));
51
52 if !new_attrs.is_empty() {
53 let new_attrs = match self.curr_owner.attrs.get(&PARENT_ID) {
54 Some(existing_attrs) => self.arena.alloc_from_iter(
55 existing_attrs.iter().map(|a| a.clone()).chain(new_attrs.into_iter()),
56 ),
57 None => self.arena.alloc_from_iter(new_attrs.into_iter()),
58 };
59
60 self.curr_owner.attrs.insert(PARENT_ID, new_attrs);
61 }
62 }
63
64 fn create_new_attrs(
65 &self,
66 span: Span,
67 sig_id: DefId,
68 existing: Option<&&[rustc_attr_ir::Attribute]>,
69 ) -> Vec<rustc_attr_ir::Attribute> {
70 ADDITIONS
71 .iter()
72 .filter_map(|addition| {
73 existing
74 .is_none_or(|attrs| !attrs.iter().any(|a| (addition.equals)(a)))
75 .then(|| match addition.kind {
76 AdditionKind::Default { factory } => Some(factory(span)),
77 AdditionKind::Inherit { factory, .. } =>
78 {
79 #[allow(deprecated)]
80 self.tcx
81 .get_all_attrs(sig_id)
82 .iter()
83 .find_map(|a| (addition.equals)(a).then(|| factory(span, a)))
84 }
85 })
86 .flatten()
87 })
88 .collect::<Vec<_>>()
89 }
90}