Skip to main content

rustc_attr_parsing/attributes/
non_exhaustive.rs

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