Check attributes on pattern fields.
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.
This commit is contained in:
parent
b998821e4c
commit
1b464c73b7
10 changed files with 64 additions and 22 deletions
|
@ -193,6 +193,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||||
|
|
||||||
fn visit_pat(&mut self, pat: &'hir Pat<'hir>) {
|
fn visit_pat(&mut self, pat: &'hir Pat<'hir>) {
|
||||||
self.insert(pat.span, pat.hir_id, Node::Pat(pat));
|
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| {
|
self.with_parent(pat.hir_id, |this| {
|
||||||
intravisit::walk_pat(this, pat);
|
intravisit::walk_pat(this, pat);
|
||||||
|
|
|
@ -64,12 +64,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
);
|
);
|
||||||
|
|
||||||
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField {
|
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
|
||||||
hir_id: self.next_id(),
|
let hir_id = self.lower_node_id(f.id);
|
||||||
ident: self.lower_ident(f.ident),
|
self.lower_attrs(hir_id, &f.attrs);
|
||||||
pat: self.lower_pat(&f.pat),
|
|
||||||
is_shorthand: f.is_shorthand,
|
hir::PatField {
|
||||||
span: self.lower_span(f.span),
|
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);
|
break hir::PatKind::Struct(qpath, fs, etc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3338,6 +3338,7 @@ pub enum Node<'hir> {
|
||||||
TypeBinding(&'hir TypeBinding<'hir>),
|
TypeBinding(&'hir TypeBinding<'hir>),
|
||||||
TraitRef(&'hir TraitRef<'hir>),
|
TraitRef(&'hir TraitRef<'hir>),
|
||||||
Pat(&'hir Pat<'hir>),
|
Pat(&'hir Pat<'hir>),
|
||||||
|
PatField(&'hir PatField<'hir>),
|
||||||
Arm(&'hir Arm<'hir>),
|
Arm(&'hir Arm<'hir>),
|
||||||
Block(&'hir Block<'hir>),
|
Block(&'hir Block<'hir>),
|
||||||
Local(&'hir Local<'hir>),
|
Local(&'hir Local<'hir>),
|
||||||
|
@ -3388,6 +3389,7 @@ impl<'hir> Node<'hir> {
|
||||||
| Node::Block(..)
|
| Node::Block(..)
|
||||||
| Node::Ctor(..)
|
| Node::Ctor(..)
|
||||||
| Node::Pat(..)
|
| Node::Pat(..)
|
||||||
|
| Node::PatField(..)
|
||||||
| Node::Arm(..)
|
| Node::Arm(..)
|
||||||
| Node::Local(..)
|
| Node::Local(..)
|
||||||
| Node::Crate(..)
|
| Node::Crate(..)
|
||||||
|
|
|
@ -56,6 +56,7 @@ pub enum Target {
|
||||||
GenericParam(GenericParamKind),
|
GenericParam(GenericParamKind),
|
||||||
MacroDef,
|
MacroDef,
|
||||||
Param,
|
Param,
|
||||||
|
PatField,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Target {
|
impl Display for Target {
|
||||||
|
@ -183,6 +184,7 @@ impl Target {
|
||||||
},
|
},
|
||||||
Target::MacroDef => "macro def",
|
Target::MacroDef => "macro def",
|
||||||
Target::Param => "function param",
|
Target::Param => "function param",
|
||||||
|
Target::PatField => "pattern field",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ impl<'a> State<'a> {
|
||||||
Node::TypeBinding(a) => self.print_type_binding(a),
|
Node::TypeBinding(a) => self.print_type_binding(a),
|
||||||
Node::TraitRef(a) => self.print_trait_ref(a),
|
Node::TraitRef(a) => self.print_trait_ref(a),
|
||||||
Node::Pat(a) => self.print_pat(a),
|
Node::Pat(a) => self.print_pat(a),
|
||||||
|
Node::PatField(a) => self.print_patfield(&a),
|
||||||
Node::Arm(a) => self.print_arm(a),
|
Node::Arm(a) => self.print_arm(a),
|
||||||
Node::Infer(_) => self.word("_"),
|
Node::Infer(_) => self.word("_"),
|
||||||
Node::Block(a) => {
|
Node::Block(a) => {
|
||||||
|
@ -1799,20 +1800,7 @@ impl<'a> State<'a> {
|
||||||
if !empty {
|
if !empty {
|
||||||
self.space();
|
self.space();
|
||||||
}
|
}
|
||||||
self.commasep_cmnt(
|
self.commasep_cmnt(Consistent, &fields, |s, f| s.print_patfield(f), |f| f.pat.span);
|
||||||
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,
|
|
||||||
);
|
|
||||||
if etc {
|
if etc {
|
||||||
if !fields.is_empty() {
|
if !fields.is_empty() {
|
||||||
self.word_space(",");
|
self.word_space(",");
|
||||||
|
@ -1907,6 +1895,20 @@ impl<'a> State<'a> {
|
||||||
self.ann.post(self, AnnNode::Pat(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<'_>) {
|
pub fn print_param(&mut self, arg: &hir::Param<'_>) {
|
||||||
self.print_outer_attributes(self.attrs(arg.hir_id));
|
self.print_outer_attributes(self.attrs(arg.hir_id));
|
||||||
self.print_pat(arg.pat);
|
self.print_pat(arg.pat);
|
||||||
|
|
|
@ -297,6 +297,7 @@ impl<'hir> Map<'hir> {
|
||||||
| Node::Infer(_)
|
| Node::Infer(_)
|
||||||
| Node::TraitRef(_)
|
| Node::TraitRef(_)
|
||||||
| Node::Pat(_)
|
| Node::Pat(_)
|
||||||
|
| Node::PatField(_)
|
||||||
| Node::Local(_)
|
| Node::Local(_)
|
||||||
| Node::Param(_)
|
| Node::Param(_)
|
||||||
| Node::Arm(_)
|
| Node::Arm(_)
|
||||||
|
@ -1030,6 +1031,7 @@ impl<'hir> Map<'hir> {
|
||||||
Node::TypeBinding(tb) => tb.span,
|
Node::TypeBinding(tb) => tb.span,
|
||||||
Node::TraitRef(tr) => tr.path.span,
|
Node::TraitRef(tr) => tr.path.span,
|
||||||
Node::Pat(pat) => pat.span,
|
Node::Pat(pat) => pat.span,
|
||||||
|
Node::PatField(field) => field.span,
|
||||||
Node::Arm(arm) => arm.span,
|
Node::Arm(arm) => arm.span,
|
||||||
Node::Block(block) => block.span,
|
Node::Block(block) => block.span,
|
||||||
Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
|
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::TypeBinding(_)) => node_str("type binding"),
|
||||||
Some(Node::TraitRef(_)) => node_str("trait ref"),
|
Some(Node::TraitRef(_)) => node_str("trait ref"),
|
||||||
Some(Node::Pat(_)) => node_str("pat"),
|
Some(Node::Pat(_)) => node_str("pat"),
|
||||||
|
Some(Node::PatField(_)) => node_str("pattern field"),
|
||||||
Some(Node::Param(_)) => node_str("param"),
|
Some(Node::Param(_)) => node_str("param"),
|
||||||
Some(Node::Arm(_)) => node_str("arm"),
|
Some(Node::Arm(_)) => node_str("arm"),
|
||||||
Some(Node::Block(_)) => node_str("block"),
|
Some(Node::Block(_)) => node_str("block"),
|
||||||
|
|
|
@ -652,7 +652,8 @@ impl CheckAttrVisitor<'_> {
|
||||||
| Target::ForeignStatic
|
| Target::ForeignStatic
|
||||||
| Target::ForeignTy
|
| Target::ForeignTy
|
||||||
| Target::GenericParam(..)
|
| Target::GenericParam(..)
|
||||||
| Target::MacroDef => None,
|
| Target::MacroDef
|
||||||
|
| Target::PatField => None,
|
||||||
} {
|
} {
|
||||||
tcx.sess.emit_err(errors::DocAliasBadLocation { span, attr_str, location });
|
tcx.sess.emit_err(errors::DocAliasBadLocation { span, attr_str, location });
|
||||||
return false;
|
return false;
|
||||||
|
@ -2076,6 +2077,15 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
||||||
|
|
||||||
intravisit::walk_param(self, param);
|
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 {
|
fn is_c_like_enum(item: &Item<'_>) -> bool {
|
||||||
|
|
|
@ -256,6 +256,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
|
||||||
| hir::Node::TypeBinding(..)
|
| hir::Node::TypeBinding(..)
|
||||||
| hir::Node::TraitRef(..)
|
| hir::Node::TraitRef(..)
|
||||||
| hir::Node::Pat(..)
|
| hir::Node::Pat(..)
|
||||||
|
| hir::Node::PatField(..)
|
||||||
| hir::Node::Arm(..)
|
| hir::Node::Arm(..)
|
||||||
| hir::Node::Local(..)
|
| hir::Node::Local(..)
|
||||||
| hir::Node::Ctor(..)
|
| hir::Node::Ctor(..)
|
||||||
|
|
|
@ -122,4 +122,10 @@ fn main() {
|
||||||
Some(res) => res,
|
Some(res) => res,
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PatternField {
|
||||||
|
foo: i32,
|
||||||
|
}
|
||||||
|
let s = PatternField { foo: 123 };
|
||||||
|
let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,12 @@ error: `#[must_use]` has no effect when applied to an match arm
|
||||||
LL | #[must_use]
|
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
|
error: `#[must_use]` has no effect when applied to an associated const
|
||||||
--> $DIR/unused_attributes-must_use.rs:68:5
|
--> $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();
|
LL | ().get_four();
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 26 previous errors
|
error: aborting due to 27 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue