Skip to main content

rustc_ast_lowering/delegation/
attributes.rs

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