Skip to main content

rustc_attr_parsing/attributes/
non_exhaustive.rs

1use rustc_ast::{ItemKind, VariantData};
2use rustc_feature::AttributeStability;
3
4use super::prelude::*;
5use crate::diagnostics::NonExhaustiveWithDefaultFieldValues;
6
7pub(crate) struct NonExhaustiveParser;
8
9impl NoArgsAttributeParser for NonExhaustiveParser {
10    const PATH: &[Symbol] = &[sym::non_exhaustive];
11    const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
12    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
13        Allow(Target::Enum),
14        Allow(Target::Struct),
15        Allow(Target::Variant),
16        Warn(Target::Field),
17        Warn(Target::Arm),
18        Warn(Target::MacroDef),
19        Warn(Target::MacroCall),
20    ]);
21    const STABILITY: AttributeStability = AttributeStability::Stable;
22    const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive;
23
24    fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
25        if cx.target != Target::Struct {
26            return;
27        }
28
29        let item = cx.target_item.expect("missing AST target item for Target::Struct");
30        let ItemKind::Struct(_, _, data) = &item.kind else {
31            {
    ::core::panicking::panic_fmt(format_args!("expected struct AST target item for Target::Struct"));
};panic!("expected struct AST target item for Target::Struct");
32        };
33        if let VariantData::Struct { fields, .. } = data
34            && fields.iter().any(|f| f.default_value().is_some())
35        {
36            cx.emit_err(NonExhaustiveWithDefaultFieldValues {
37                attr_span,
38                defn_span: cx.target_span,
39            });
40        }
41    }
42}