about summary refs log tree commit diff
path: root/compiler/rustc_lint
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-15 05:50:54 +0000
committerbors <bors@rust-lang.org>2022-08-15 05:50:54 +0000
commit6ce76091c7cef21692a15dce1f0a4c415d245be4 (patch)
treec41de2e296638ec3db9cb8db375fd857da3a8737 /compiler/rustc_lint
parent80ed61fbd64936ed676c2050e7e660b5ad78c9f2 (diff)
parent900a9d3f4e80315b1fccd909336febede92503ed (diff)
downloadrust-6ce76091c7cef21692a15dce1f0a4c415d245be4.tar.gz
rust-6ce76091c7cef21692a15dce1f0a4c415d245be4.zip
Auto merge of #96745 - ehuss:even-more-attribute-validation, r=cjgillot
Visit attributes in more places.

This adds 3 loosely related changes (I can split PRs if desired):

- Attribute checking on pattern struct fields.
- Attribute checking on struct expression fields.
- Lint level visiting on pattern struct fields, struct expression fields, and generic parameters.

There are still some lints which ignore lint levels in various positions. This is a consequence of how the lints themselves are implemented. For example, lint levels on associated consts don't work with `unused_braces`.
Diffstat (limited to 'compiler/rustc_lint')
-rw-r--r--compiler/rustc_lint/src/early.rs13
-rw-r--r--compiler/rustc_lint/src/levels.rs18
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs17
-rw-r--r--compiler/rustc_lint/src/types.rs98
4 files changed, 81 insertions, 65 deletions
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index cbf1a677555..580a4566869 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -101,6 +101,12 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         run_early_pass!(self, check_pat_post, p);
     }
 
+    fn visit_pat_field(&mut self, field: &'a ast::PatField) {
+        self.with_lint_attrs(field.id, &field.attrs, |cx| {
+            ast_visit::walk_pat_field(cx, field);
+        });
+    }
+
     fn visit_anon_const(&mut self, c: &'a ast::AnonConst) {
         self.check_id(c.id);
         ast_visit::walk_anon_const(self, c);
@@ -219,9 +225,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
     }
 
     fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
-        run_early_pass!(self, check_generic_param, param);
-        self.check_id(param.id);
-        ast_visit::walk_generic_param(self, param);
+        self.with_lint_attrs(param.id, &param.attrs, |cx| {
+            run_early_pass!(cx, check_generic_param, param);
+            ast_visit::walk_generic_param(cx, param);
+        });
     }
 
     fn visit_generics(&mut self, g: &'a ast::Generics) {
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 7ab9302d835..1cabb58bbeb 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -766,6 +766,12 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
         })
     }
 
+    fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
+        self.with_lint_attrs(field.hir_id, |builder| {
+            intravisit::walk_expr_field(builder, field);
+        })
+    }
+
     fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
         self.with_lint_attrs(s.hir_id, |builder| {
             intravisit::walk_field_def(builder, s);
@@ -801,6 +807,18 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
             intravisit::walk_impl_item(builder, impl_item);
         });
     }
+
+    fn visit_pat_field(&mut self, field: &'tcx hir::PatField<'tcx>) {
+        self.with_lint_attrs(field.hir_id, |builder| {
+            intravisit::walk_pat_field(builder, field);
+        })
+    }
+
+    fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
+        self.with_lint_attrs(p.hir_id, |builder| {
+            intravisit::walk_generic_param(builder, p);
+        });
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 8d04d68bf1c..2868aabfa07 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -437,19 +437,14 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
 
     fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
         if let PatKind::Binding(_, hid, ident, _) = p.kind {
-            if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
+            if let hir::Node::PatField(field) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
             {
-                if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind {
-                    if field_pats
-                        .iter()
-                        .any(|field| !field.is_shorthand && field.pat.hir_id == p.hir_id)
-                    {
-                        // Only check if a new name has been introduced, to avoid warning
-                        // on both the struct definition and this pattern.
-                        self.check_snake_case(cx, "variable", &ident);
-                    }
-                    return;
+                if !field.is_shorthand {
+                    // Only check if a new name has been introduced, to avoid warning
+                    // on both the struct definition and this pattern.
+                    self.check_snake_case(cx, "variable", &ident);
                 }
+                return;
             }
             self.check_snake_case(cx, "variable", &ident);
         }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 5c07afeb7aa..cafd2c6e679 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -125,45 +125,51 @@ fn lint_overflowing_range_endpoint<'tcx>(
     lit_val: u128,
     max: u128,
     expr: &'tcx hir::Expr<'tcx>,
-    parent_expr: &'tcx hir::Expr<'tcx>,
     ty: &str,
 ) -> bool {
     // We only want to handle exclusive (`..`) ranges,
     // which are represented as `ExprKind::Struct`.
+    let par_id = cx.tcx.hir().get_parent_node(expr.hir_id);
+    let Node::ExprField(field) = cx.tcx.hir().get(par_id) else { return false };
+    let field_par_id = cx.tcx.hir().get_parent_node(field.hir_id);
+    let Node::Expr(struct_expr) = cx.tcx.hir().get(field_par_id) else { return false };
+    if !is_range_literal(struct_expr) {
+        return false;
+    };
+    let ExprKind::Struct(_, eps, _) = &struct_expr.kind else { return false };
+    if eps.len() != 2 {
+        return false;
+    }
+
     let mut overwritten = false;
-    if let ExprKind::Struct(_, eps, _) = &parent_expr.kind {
-        if eps.len() != 2 {
-            return false;
-        }
-        // We can suggest using an inclusive range
-        // (`..=`) instead only if it is the `end` that is
-        // overflowing and only by 1.
-        if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
-            cx.struct_span_lint(OVERFLOWING_LITERALS, parent_expr.span, |lint| {
-                let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
-                err.set_arg("ty", ty);
-                if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
-                    use ast::{LitIntType, LitKind};
-                    // We need to preserve the literal's suffix,
-                    // as it may determine typing information.
-                    let suffix = match lit.node {
-                        LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
-                        LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
-                        LitKind::Int(_, LitIntType::Unsuffixed) => "",
-                        _ => bug!(),
-                    };
-                    let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
-                    err.span_suggestion(
-                        parent_expr.span,
-                        fluent::lint::suggestion,
-                        suggestion,
-                        Applicability::MachineApplicable,
-                    );
-                    err.emit();
-                    overwritten = true;
-                }
-            });
-        }
+    // We can suggest using an inclusive range
+    // (`..=`) instead only if it is the `end` that is
+    // overflowing and only by 1.
+    if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
+        cx.struct_span_lint(OVERFLOWING_LITERALS, struct_expr.span, |lint| {
+            let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
+            err.set_arg("ty", ty);
+            if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
+                use ast::{LitIntType, LitKind};
+                // We need to preserve the literal's suffix,
+                // as it may determine typing information.
+                let suffix = match lit.node {
+                    LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
+                    LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
+                    LitKind::Int(_, LitIntType::Unsuffixed) => "",
+                    _ => bug!(),
+                };
+                let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
+                err.span_suggestion(
+                    struct_expr.span,
+                    fluent::lint::suggestion,
+                    suggestion,
+                    Applicability::MachineApplicable,
+                );
+                err.emit();
+                overwritten = true;
+            }
+        });
     }
     overwritten
 }
@@ -339,16 +345,9 @@ fn lint_int_literal<'tcx>(
             return;
         }
 
-        let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
-        if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
-            if let hir::ExprKind::Struct(..) = par_e.kind {
-                if is_range_literal(par_e)
-                    && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
-                {
-                    // The overflowing literal lint was overridden.
-                    return;
-                }
-            }
+        if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
+            // The overflowing literal lint was overridden.
+            return;
         }
 
         cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
@@ -408,16 +407,13 @@ fn lint_uint_literal<'tcx>(
                         return;
                     }
                 }
-                hir::ExprKind::Struct(..) if is_range_literal(par_e) => {
-                    let t = t.name_str();
-                    if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
-                        // The overflowing literal lint was overridden.
-                        return;
-                    }
-                }
                 _ => {}
             }
         }
+        if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
+            // The overflowing literal lint was overridden.
+            return;
+        }
         if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
             report_bin_hex_error(
                 cx,