Skip to content

Commit 1b464c7

Browse files
committed
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.
1 parent b998821 commit 1b464c7

File tree

10 files changed

+64
-22
lines changed

10 files changed

+64
-22
lines changed

compiler/rustc_ast_lowering/src/index.rs

+5
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
193193

194194
fn visit_pat(&mut self, pat: &'hir Pat<'hir>) {
195195
self.insert(pat.span, pat.hir_id, Node::Pat(pat));
196+
if let PatKind::Struct(_, fields, _) = pat.kind {
197+
for field in fields {
198+
self.insert(field.span, field.hir_id, Node::PatField(field));
199+
}
200+
}
196201

197202
self.with_parent(pat.hir_id, |this| {
198203
intravisit::walk_pat(this, pat);

compiler/rustc_ast_lowering/src/pat.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6464
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
6565
);
6666

67-
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField {
68-
hir_id: self.next_id(),
69-
ident: self.lower_ident(f.ident),
70-
pat: self.lower_pat(&f.pat),
71-
is_shorthand: f.is_shorthand,
72-
span: self.lower_span(f.span),
67+
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
68+
let hir_id = self.lower_node_id(f.id);
69+
self.lower_attrs(hir_id, &f.attrs);
70+
71+
hir::PatField {
72+
hir_id,
73+
ident: self.lower_ident(f.ident),
74+
pat: self.lower_pat(&f.pat),
75+
is_shorthand: f.is_shorthand,
76+
span: self.lower_span(f.span),
77+
}
7378
}));
7479
break hir::PatKind::Struct(qpath, fs, etc);
7580
}

compiler/rustc_hir/src/hir.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3338,6 +3338,7 @@ pub enum Node<'hir> {
33383338
TypeBinding(&'hir TypeBinding<'hir>),
33393339
TraitRef(&'hir TraitRef<'hir>),
33403340
Pat(&'hir Pat<'hir>),
3341+
PatField(&'hir PatField<'hir>),
33413342
Arm(&'hir Arm<'hir>),
33423343
Block(&'hir Block<'hir>),
33433344
Local(&'hir Local<'hir>),
@@ -3388,6 +3389,7 @@ impl<'hir> Node<'hir> {
33883389
| Node::Block(..)
33893390
| Node::Ctor(..)
33903391
| Node::Pat(..)
3392+
| Node::PatField(..)
33913393
| Node::Arm(..)
33923394
| Node::Local(..)
33933395
| Node::Crate(..)

compiler/rustc_hir/src/target.rs

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub enum Target {
5656
GenericParam(GenericParamKind),
5757
MacroDef,
5858
Param,
59+
PatField,
5960
}
6061

6162
impl Display for Target {
@@ -183,6 +184,7 @@ impl Target {
183184
},
184185
Target::MacroDef => "macro def",
185186
Target::Param => "function param",
187+
Target::PatField => "pattern field",
186188
}
187189
}
188190
}

compiler/rustc_hir_pretty/src/lib.rs

+16-14
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ impl<'a> State<'a> {
8989
Node::TypeBinding(a) => self.print_type_binding(a),
9090
Node::TraitRef(a) => self.print_trait_ref(a),
9191
Node::Pat(a) => self.print_pat(a),
92+
Node::PatField(a) => self.print_patfield(&a),
9293
Node::Arm(a) => self.print_arm(a),
9394
Node::Infer(_) => self.word("_"),
9495
Node::Block(a) => {
@@ -1799,20 +1800,7 @@ impl<'a> State<'a> {
17991800
if !empty {
18001801
self.space();
18011802
}
1802-
self.commasep_cmnt(
1803-
Consistent,
1804-
fields,
1805-
|s, f| {
1806-
s.cbox(INDENT_UNIT);
1807-
if !f.is_shorthand {
1808-
s.print_ident(f.ident);
1809-
s.word_nbsp(":");
1810-
}
1811-
s.print_pat(f.pat);
1812-
s.end()
1813-
},
1814-
|f| f.pat.span,
1815-
);
1803+
self.commasep_cmnt(Consistent, &fields, |s, f| s.print_patfield(f), |f| f.pat.span);
18161804
if etc {
18171805
if !fields.is_empty() {
18181806
self.word_space(",");
@@ -1907,6 +1895,20 @@ impl<'a> State<'a> {
19071895
self.ann.post(self, AnnNode::Pat(pat))
19081896
}
19091897

1898+
pub fn print_patfield(&mut self, field: &hir::PatField<'_>) {
1899+
if self.attrs(field.hir_id).is_empty() {
1900+
self.space();
1901+
}
1902+
self.cbox(INDENT_UNIT);
1903+
self.print_outer_attributes(&self.attrs(field.hir_id));
1904+
if !field.is_shorthand {
1905+
self.print_ident(field.ident);
1906+
self.word_nbsp(":");
1907+
}
1908+
self.print_pat(field.pat);
1909+
self.end();
1910+
}
1911+
19101912
pub fn print_param(&mut self, arg: &hir::Param<'_>) {
19111913
self.print_outer_attributes(self.attrs(arg.hir_id));
19121914
self.print_pat(arg.pat);

compiler/rustc_middle/src/hir/map/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ impl<'hir> Map<'hir> {
297297
| Node::Infer(_)
298298
| Node::TraitRef(_)
299299
| Node::Pat(_)
300+
| Node::PatField(_)
300301
| Node::Local(_)
301302
| Node::Param(_)
302303
| Node::Arm(_)
@@ -1030,6 +1031,7 @@ impl<'hir> Map<'hir> {
10301031
Node::TypeBinding(tb) => tb.span,
10311032
Node::TraitRef(tr) => tr.path.span,
10321033
Node::Pat(pat) => pat.span,
1034+
Node::PatField(field) => field.span,
10331035
Node::Arm(arm) => arm.span,
10341036
Node::Block(block) => block.span,
10351037
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 {
12471249
Some(Node::TypeBinding(_)) => node_str("type binding"),
12481250
Some(Node::TraitRef(_)) => node_str("trait ref"),
12491251
Some(Node::Pat(_)) => node_str("pat"),
1252+
Some(Node::PatField(_)) => node_str("pattern field"),
12501253
Some(Node::Param(_)) => node_str("param"),
12511254
Some(Node::Arm(_)) => node_str("arm"),
12521255
Some(Node::Block(_)) => node_str("block"),

compiler/rustc_passes/src/check_attr.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,8 @@ impl CheckAttrVisitor<'_> {
652652
| Target::ForeignStatic
653653
| Target::ForeignTy
654654
| Target::GenericParam(..)
655-
| Target::MacroDef => None,
655+
| Target::MacroDef
656+
| Target::PatField => None,
656657
} {
657658
tcx.sess.emit_err(errors::DocAliasBadLocation { span, attr_str, location });
658659
return false;
@@ -2076,6 +2077,15 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
20762077

20772078
intravisit::walk_param(self, param);
20782079
}
2080+
2081+
fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
2082+
if let hir::PatKind::Struct(_, fields, _) = p.kind {
2083+
for field in fields {
2084+
self.check_attributes(field.hir_id, field.span, Target::PatField, None);
2085+
}
2086+
}
2087+
intravisit::walk_pat(self, p);
2088+
}
20792089
}
20802090

20812091
fn is_c_like_enum(item: &Item<'_>) -> bool {

compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
256256
| hir::Node::TypeBinding(..)
257257
| hir::Node::TraitRef(..)
258258
| hir::Node::Pat(..)
259+
| hir::Node::PatField(..)
259260
| hir::Node::Arm(..)
260261
| hir::Node::Local(..)
261262
| hir::Node::Ctor(..)

src/test/ui/lint/unused/unused_attributes-must_use.rs

+6
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,10 @@ fn main() {
122122
Some(res) => res,
123123
None => 0,
124124
};
125+
126+
struct PatternField {
127+
foo: i32,
128+
}
129+
let s = PatternField { foo: 123 };
130+
let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect
125131
}

src/test/ui/lint/unused/unused_attributes-must_use.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ error: `#[must_use]` has no effect when applied to an match arm
105105
LL | #[must_use]
106106
| ^^^^^^^^^^^
107107

108+
error: `#[must_use]` has no effect when applied to a pattern field
109+
--> $DIR/unused_attributes-must_use.rs:130:24
110+
|
111+
LL | let PatternField { #[must_use] foo } = s;
112+
| ^^^^^^^^^^^
113+
108114
error: `#[must_use]` has no effect when applied to an associated const
109115
--> $DIR/unused_attributes-must_use.rs:68:5
110116
|
@@ -171,5 +177,5 @@ error: unused return value of `Use::get_four` that must be used
171177
LL | ().get_four();
172178
| ^^^^^^^^^^^^^^
173179

174-
error: aborting due to 26 previous errors
180+
error: aborting due to 27 previous errors
175181

0 commit comments

Comments
 (0)