- let mut markers = variants.iter().filter(|v| is_non_exhaustive_marker(v));
- if_chain! {
- if let Some(marker) = markers.next();
- if markers.count() == 0 && variants.len() > 1;
- then {
- span_lint_and_then(
- cx,
- MANUAL_NON_EXHAUSTIVE,
- item.span,
- "this seems like a manual implementation of the non-exhaustive pattern",
- |diag| {
- if_chain! {
- if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive));
- let header_span = cx.sess().source_map().span_until_char(item.span, '{');
- if let Some(snippet) = snippet_opt(cx, header_span);
- then {
+impl EarlyLintPass for ManualNonExhaustiveStruct {
+ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
+ if !meets_msrv(self.msrv, msrvs::NON_EXHAUSTIVE) {
+ return;
+ }
+
+ if let ast::ItemKind::Struct(variant_data, _) = &item.kind {
+ let (fields, delimiter) = match variant_data {
+ ast::VariantData::Struct(fields, _) => (&**fields, '{'),
+ ast::VariantData::Tuple(fields, _) => (&**fields, '('),
+ ast::VariantData::Unit(_) => return,
+ };
+ if fields.len() <= 1 {
+ return;
+ }
+ let mut iter = fields.iter().filter_map(|f| match f.vis.kind {
+ VisibilityKind::Public => None,
+ VisibilityKind::Inherited => Some(Ok(f)),
+ VisibilityKind::Restricted { .. } => Some(Err(())),
+ });
+ if let Some(Ok(field)) = iter.next()
+ && iter.next().is_none()
+ && field.ty.kind.is_unit()
+ && field.ident.map_or(true, |name| name.as_str().starts_with('_'))
+ {
+ span_lint_and_then(
+ cx,
+ MANUAL_NON_EXHAUSTIVE,
+ item.span,
+ "this seems like a manual implementation of the non-exhaustive pattern",
+ |diag| {
+ if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive))
+ && let header_span = cx.sess().source_map().span_until_char(item.span, delimiter)
+ && let Some(snippet) = snippet_opt(cx, header_span)
+ {