rustc_attr_parsing/attributes/
non_exhaustive.rs1use 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}