Skip to main content

rustc_ast_lowering/delegation/
attributes.rs

1use 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}