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