]> git.lizzy.rs Git - rust.git/commitdiff
Check attributes on pattern fields.
authorEric Huss <eric@huss.org>
Tue, 3 May 2022 18:52:53 +0000 (11:52 -0700)
committerEric Huss <eric@huss.org>
Fri, 12 Aug 2022 04:48:39 +0000 (21:48 -0700)
Attributes on pattern struct fields were not being checked for validity.
This adds the fields as HIR nodes so that the `CheckAttrVisitor` can
visit those nodes to check their attributes.

compiler/rustc_ast_lowering/src/index.rs
compiler/rustc_ast_lowering/src/pat.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/target.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
src/test/ui/lint/unused/unused_attributes-must_use.rs
src/test/ui/lint/unused/unused_attributes-must_use.stderr

index e08c1d063c10544aca6fd83785b103c4597c9d30..ecc26faf20da60575f930545feaf719cdf890e73 100644 (file)
@@ -193,6 +193,11 @@ fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
 
     fn visit_pat(&mut self, pat: &'hir Pat<'hir>) {
         self.insert(pat.span, pat.hir_id, Node::Pat(pat));
+        if let PatKind::Struct(_, fields, _) = pat.kind {
+            for field in fields {
+                self.insert(field.span, field.hir_id, Node::PatField(field));
+            }
+        }
 
         self.with_parent(pat.hir_id, |this| {
             intravisit::walk_pat(this, pat);
index bd2e76e5528dab08b8a07e00353bc7bdbfb1e906..51f67e505f4eeae82458a7b138a95b7a112ce8be 100644 (file)
@@ -64,12 +64,17 @@ pub(crate) fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         );
 
-                        let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField {
-                            hir_id: self.next_id(),
-                            ident: self.lower_ident(f.ident),
-                            pat: self.lower_pat(&f.pat),
-                            is_shorthand: f.is_shorthand,
-                            span: self.lower_span(f.span),
+                        let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
+                            let hir_id = self.lower_node_id(f.id);
+                            self.lower_attrs(hir_id, &f.attrs);
+
+                            hir::PatField {
+                                hir_id,
+                                ident: self.lower_ident(f.ident),
+                                pat: self.lower_pat(&f.pat),
+                                is_shorthand: f.is_shorthand,
+                                span: self.lower_span(f.span),
+                            }
                         }));
                         break hir::PatKind::Struct(qpath, fs, etc);
                     }
index 7a87a3e4882601700eb7e5ebd1ef9272d4769d8a..9885d33d4442060aaf13a4e393be5208305a9af9 100644 (file)
@@ -3338,6 +3338,7 @@ pub enum Node<'hir> {
     TypeBinding(&'hir TypeBinding<'hir>),
     TraitRef(&'hir TraitRef<'hir>),
     Pat(&'hir Pat<'hir>),
+    PatField(&'hir PatField<'hir>),
     Arm(&'hir Arm<'hir>),
     Block(&'hir Block<'hir>),
     Local(&'hir Local<'hir>),
@@ -3388,6 +3389,7 @@ pub fn ident(&self) -> Option<Ident> {
             | Node::Block(..)
             | Node::Ctor(..)
             | Node::Pat(..)
+            | Node::PatField(..)
             | Node::Arm(..)
             | Node::Local(..)
             | Node::Crate(..)
index 6236dea10c88f3c23258a1821f56199c7bef3085..1b05c82eade87d372e110f5af9c91a4bb7fb4cce 100644 (file)
@@ -56,6 +56,7 @@ pub enum Target {
     GenericParam(GenericParamKind),
     MacroDef,
     Param,
+    PatField,
 }
 
 impl Display for Target {
@@ -183,6 +184,7 @@ pub fn name(self) -> &'static str {
             },
             Target::MacroDef => "macro def",
             Target::Param => "function param",
+            Target::PatField => "pattern field",
         }
     }
 }
index e0179bd3ed1e85afc11a512ad3dc452dcf1a0621..641175d452973957f144417654cbd5a198291a7d 100644 (file)
@@ -89,6 +89,7 @@ pub fn print_node(&mut self, node: Node<'_>) {
             Node::TypeBinding(a) => self.print_type_binding(a),
             Node::TraitRef(a) => self.print_trait_ref(a),
             Node::Pat(a) => self.print_pat(a),
+            Node::PatField(a) => self.print_patfield(&a),
             Node::Arm(a) => self.print_arm(a),
             Node::Infer(_) => self.word("_"),
             Node::Block(a) => {
@@ -1799,20 +1800,7 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
                 if !empty {
                     self.space();
                 }
-                self.commasep_cmnt(
-                    Consistent,
-                    fields,
-                    |s, f| {
-                        s.cbox(INDENT_UNIT);
-                        if !f.is_shorthand {
-                            s.print_ident(f.ident);
-                            s.word_nbsp(":");
-                        }
-                        s.print_pat(f.pat);
-                        s.end()
-                    },
-                    |f| f.pat.span,
-                );
+                self.commasep_cmnt(Consistent, &fields, |s, f| s.print_patfield(f), |f| f.pat.span);
                 if etc {
                     if !fields.is_empty() {
                         self.word_space(",");
@@ -1907,6 +1895,20 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
         self.ann.post(self, AnnNode::Pat(pat))
     }
 
+    pub fn print_patfield(&mut self, field: &hir::PatField<'_>) {
+        if self.attrs(field.hir_id).is_empty() {
+            self.space();
+        }
+        self.cbox(INDENT_UNIT);
+        self.print_outer_attributes(&self.attrs(field.hir_id));
+        if !field.is_shorthand {
+            self.print_ident(field.ident);
+            self.word_nbsp(":");
+        }
+        self.print_pat(field.pat);
+        self.end();
+    }
+
     pub fn print_param(&mut self, arg: &hir::Param<'_>) {
         self.print_outer_attributes(self.attrs(arg.hir_id));
         self.print_pat(arg.pat);
index 47b04c33ec1cd67b131be9439b977f2997b3c862..06fdef4142ee136404a7ae2c124543aea6ad68ed 100644 (file)
@@ -297,6 +297,7 @@ pub(super) fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> {
             | Node::Infer(_)
             | Node::TraitRef(_)
             | Node::Pat(_)
+            | Node::PatField(_)
             | Node::Local(_)
             | Node::Param(_)
             | Node::Arm(_)
@@ -1030,6 +1031,7 @@ pub fn span_with_body(self, hir_id: HirId) -> Span {
             Node::TypeBinding(tb) => tb.span,
             Node::TraitRef(tr) => tr.path.span,
             Node::Pat(pat) => pat.span,
+            Node::PatField(field) => field.span,
             Node::Arm(arm) => arm.span,
             Node::Block(block) => block.span,
             Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
@@ -1247,6 +1249,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
         Some(Node::TypeBinding(_)) => node_str("type binding"),
         Some(Node::TraitRef(_)) => node_str("trait ref"),
         Some(Node::Pat(_)) => node_str("pat"),
+        Some(Node::PatField(_)) => node_str("pattern field"),
         Some(Node::Param(_)) => node_str("param"),
         Some(Node::Arm(_)) => node_str("arm"),
         Some(Node::Block(_)) => node_str("block"),
index f75fffb6871f73aed9194c51de005b04c80da836..42f5806c1f7c04b70e20f546de5e0c0edf0f3636 100644 (file)
@@ -652,7 +652,8 @@ fn check_doc_alias_value(
             | Target::ForeignStatic
             | Target::ForeignTy
             | Target::GenericParam(..)
-            | Target::MacroDef => None,
+            | Target::MacroDef
+            | Target::PatField => None,
         } {
             tcx.sess.emit_err(errors::DocAliasBadLocation { span, attr_str, location });
             return false;
@@ -2076,6 +2077,15 @@ fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
 
         intravisit::walk_param(self, param);
     }
+
+    fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
+        if let hir::PatKind::Struct(_, fields, _) = p.kind {
+            for field in fields {
+                self.check_attributes(field.hir_id, field.span, Target::PatField, None);
+            }
+        }
+        intravisit::walk_pat(self, p);
+    }
 }
 
 fn is_c_like_enum(item: &Item<'_>) -> bool {
index a2c23db162b037414956a99403093dc11062d827..f1f4b05b33bccc58d2ebaa806d326b7b8a2ffdb8 100644 (file)
@@ -256,6 +256,7 @@ fn find_target_expression_from_destination(
                 | hir::Node::TypeBinding(..)
                 | hir::Node::TraitRef(..)
                 | hir::Node::Pat(..)
+                | hir::Node::PatField(..)
                 | hir::Node::Arm(..)
                 | hir::Node::Local(..)
                 | hir::Node::Ctor(..)
index 1c4abb9491e00740c22324828d5de81fd442f9ff..87f498c0aeeaee5f0cf8f89123933648c43b7d62 100644 (file)
@@ -122,4 +122,10 @@ fn main() {
         Some(res) => res,
         None => 0,
     };
+
+    struct PatternField {
+        foo: i32,
+    }
+    let s = PatternField { foo: 123 };
+    let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect
 }
index 317d81c591d55cd5cdb0cec79b306eb14ae84376..3d2672687f896e370fc347df995c4f9264c580ab 100644 (file)
@@ -105,6 +105,12 @@ error: `#[must_use]` has no effect when applied to an match arm
 LL |         #[must_use]
    |         ^^^^^^^^^^^
 
+error: `#[must_use]` has no effect when applied to a pattern field
+  --> $DIR/unused_attributes-must_use.rs:130:24
+   |
+LL |     let PatternField { #[must_use] foo } = s;
+   |                        ^^^^^^^^^^^
+
 error: `#[must_use]` has no effect when applied to an associated const
   --> $DIR/unused_attributes-must_use.rs:68:5
    |
@@ -171,5 +177,5 @@ error: unused return value of `Use::get_four` that must be used
 LL |     ().get_four();
    |     ^^^^^^^^^^^^^^
 
-error: aborting due to 26 previous errors
+error: aborting due to 27 previous errors