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.
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);
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);
}
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>),
| Node::Block(..)
| Node::Ctor(..)
| Node::Pat(..)
+ | Node::PatField(..)
| Node::Arm(..)
| Node::Local(..)
| Node::Crate(..)
GenericParam(GenericParamKind),
MacroDef,
Param,
+ PatField,
}
impl Display for Target {
},
Target::MacroDef => "macro def",
Target::Param => "function param",
+ Target::PatField => "pattern field",
}
}
}
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) => {
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(",");
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);
| Node::Infer(_)
| Node::TraitRef(_)
| Node::Pat(_)
+ | Node::PatField(_)
| Node::Local(_)
| Node::Param(_)
| Node::Arm(_)
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)),
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"),
| 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;
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 {
| hir::Node::TypeBinding(..)
| hir::Node::TraitRef(..)
| hir::Node::Pat(..)
+ | hir::Node::PatField(..)
| hir::Node::Arm(..)
| hir::Node::Local(..)
| hir::Node::Ctor(..)
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
}
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
|
LL | ().get_four();
| ^^^^^^^^^^^^^^
-error: aborting due to 26 previous errors
+error: aborting due to 27 previous errors