@@ -124,7 +124,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
124
124
[ sym:: coverage, ..] => self . check_coverage ( attr, span, target) ,
125
125
[ sym:: optimize, ..] => self . check_optimize ( hir_id, attr, span, target) ,
126
126
[ sym:: no_sanitize, ..] => self . check_no_sanitize ( attr, span, target) ,
127
- [ sym:: non_exhaustive, ..] => self . check_non_exhaustive ( hir_id, attr, span, target) ,
127
+ [ sym:: non_exhaustive, ..] => self . check_non_exhaustive ( hir_id, attr, span, target, item ) ,
128
128
[ sym:: marker, ..] => self . check_marker ( hir_id, attr, span, target) ,
129
129
[ sym:: target_feature, ..] => {
130
130
self . check_target_feature ( hir_id, attr, span, target, attrs)
@@ -685,9 +685,30 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
685
685
}
686
686
687
687
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid.
688
- fn check_non_exhaustive ( & self , hir_id : HirId , attr : & Attribute , span : Span , target : Target ) {
688
+ fn check_non_exhaustive (
689
+ & self ,
690
+ hir_id : HirId ,
691
+ attr : & Attribute ,
692
+ span : Span ,
693
+ target : Target ,
694
+ item : Option < ItemLike < ' _ > > ,
695
+ ) {
689
696
match target {
690
- Target :: Struct | Target :: Enum | Target :: Variant => { }
697
+ Target :: Struct => {
698
+ if let Some ( ItemLike :: Item ( hir:: Item {
699
+ kind : hir:: ItemKind :: Struct ( hir:: VariantData :: Struct { fields, .. } , _) ,
700
+ ..
701
+ } ) ) = item
702
+ && !fields. is_empty ( )
703
+ && fields. iter ( ) . any ( |f| f. default . is_some ( ) )
704
+ {
705
+ self . dcx ( ) . emit_err ( errors:: NonExhaustiveWithDefaultFieldValues {
706
+ attr_span : attr. span ,
707
+ defn_span : span,
708
+ } ) ;
709
+ }
710
+ }
711
+ Target :: Enum | Target :: Variant => { }
691
712
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
692
713
// `#[non_exhaustive]` attribute with just a lint, because we previously
693
714
// erroneously allowed it and some crates used it accidentally, to be compatible
0 commit comments