Check attributes on struct expression fields.
Attributes on struct expression fields were not being checked for validity. This adds the fields as HIR nodes so that `CheckAttrVisitor` can visit those nodes to check their attributes.
This commit is contained in:
parent
1b464c73b7
commit
b651c1cebe
10 changed files with 47 additions and 18 deletions
|
@ -1406,8 +1406,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
|
fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
|
||||||
|
let hir_id = self.lower_node_id(f.id);
|
||||||
|
self.lower_attrs(hir_id, &f.attrs);
|
||||||
hir::ExprField {
|
hir::ExprField {
|
||||||
hir_id: self.next_id(),
|
hir_id,
|
||||||
ident: self.lower_ident(f.ident),
|
ident: self.lower_ident(f.ident),
|
||||||
expr: self.lower_expr(&f.expr),
|
expr: self.lower_expr(&f.expr),
|
||||||
span: self.lower_span(f.span),
|
span: self.lower_span(f.span),
|
||||||
|
|
|
@ -224,6 +224,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
|
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
|
||||||
self.insert(expr.span, expr.hir_id, Node::Expr(expr));
|
self.insert(expr.span, expr.hir_id, Node::Expr(expr));
|
||||||
|
if let ExprKind::Struct(_, fields, _) = expr.kind {
|
||||||
|
for field in fields {
|
||||||
|
self.insert(field.span, field.hir_id, Node::ExprField(field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.with_parent(expr.hir_id, |this| {
|
self.with_parent(expr.hir_id, |this| {
|
||||||
intravisit::walk_expr(this, expr);
|
intravisit::walk_expr(this, expr);
|
||||||
|
|
|
@ -3332,6 +3332,7 @@ pub enum Node<'hir> {
|
||||||
Field(&'hir FieldDef<'hir>),
|
Field(&'hir FieldDef<'hir>),
|
||||||
AnonConst(&'hir AnonConst),
|
AnonConst(&'hir AnonConst),
|
||||||
Expr(&'hir Expr<'hir>),
|
Expr(&'hir Expr<'hir>),
|
||||||
|
ExprField(&'hir ExprField<'hir>),
|
||||||
Stmt(&'hir Stmt<'hir>),
|
Stmt(&'hir Stmt<'hir>),
|
||||||
PathSegment(&'hir PathSegment<'hir>),
|
PathSegment(&'hir PathSegment<'hir>),
|
||||||
Ty(&'hir Ty<'hir>),
|
Ty(&'hir Ty<'hir>),
|
||||||
|
@ -3390,6 +3391,7 @@ impl<'hir> Node<'hir> {
|
||||||
| Node::Ctor(..)
|
| Node::Ctor(..)
|
||||||
| Node::Pat(..)
|
| Node::Pat(..)
|
||||||
| Node::PatField(..)
|
| Node::PatField(..)
|
||||||
|
| Node::ExprField(..)
|
||||||
| Node::Arm(..)
|
| Node::Arm(..)
|
||||||
| Node::Local(..)
|
| Node::Local(..)
|
||||||
| Node::Crate(..)
|
| Node::Crate(..)
|
||||||
|
|
|
@ -57,6 +57,7 @@ pub enum Target {
|
||||||
MacroDef,
|
MacroDef,
|
||||||
Param,
|
Param,
|
||||||
PatField,
|
PatField,
|
||||||
|
ExprField,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Target {
|
impl Display for Target {
|
||||||
|
@ -185,6 +186,7 @@ impl Target {
|
||||||
Target::MacroDef => "macro def",
|
Target::MacroDef => "macro def",
|
||||||
Target::Param => "function param",
|
Target::Param => "function param",
|
||||||
Target::PatField => "pattern field",
|
Target::PatField => "pattern field",
|
||||||
|
Target::ExprField => "struct field",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ impl<'a> State<'a> {
|
||||||
Node::Variant(a) => self.print_variant(a),
|
Node::Variant(a) => self.print_variant(a),
|
||||||
Node::AnonConst(a) => self.print_anon_const(a),
|
Node::AnonConst(a) => self.print_anon_const(a),
|
||||||
Node::Expr(a) => self.print_expr(a),
|
Node::Expr(a) => self.print_expr(a),
|
||||||
|
Node::ExprField(a) => self.print_expr_field(&a),
|
||||||
Node::Stmt(a) => self.print_stmt(a),
|
Node::Stmt(a) => self.print_stmt(a),
|
||||||
Node::PathSegment(a) => self.print_path_segment(a),
|
Node::PathSegment(a) => self.print_path_segment(a),
|
||||||
Node::Ty(a) => self.print_type(a),
|
Node::Ty(a) => self.print_type(a),
|
||||||
|
@ -1124,20 +1125,7 @@ impl<'a> State<'a> {
|
||||||
) {
|
) {
|
||||||
self.print_qpath(qpath, true);
|
self.print_qpath(qpath, true);
|
||||||
self.word("{");
|
self.word("{");
|
||||||
self.commasep_cmnt(
|
self.commasep_cmnt(Consistent, fields, |s, field| s.print_expr_field(field), |f| f.span);
|
||||||
Consistent,
|
|
||||||
fields,
|
|
||||||
|s, field| {
|
|
||||||
s.ibox(INDENT_UNIT);
|
|
||||||
if !field.is_shorthand {
|
|
||||||
s.print_ident(field.ident);
|
|
||||||
s.word_space(":");
|
|
||||||
}
|
|
||||||
s.print_expr(field.expr);
|
|
||||||
s.end()
|
|
||||||
},
|
|
||||||
|f| f.span,
|
|
||||||
);
|
|
||||||
if let Some(expr) = wth {
|
if let Some(expr) = wth {
|
||||||
self.ibox(INDENT_UNIT);
|
self.ibox(INDENT_UNIT);
|
||||||
if !fields.is_empty() {
|
if !fields.is_empty() {
|
||||||
|
@ -1154,6 +1142,20 @@ impl<'a> State<'a> {
|
||||||
self.word("}");
|
self.word("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_expr_field(&mut self, field: &hir::ExprField<'_>) {
|
||||||
|
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_space(":");
|
||||||
|
}
|
||||||
|
self.print_expr(&field.expr);
|
||||||
|
self.end()
|
||||||
|
}
|
||||||
|
|
||||||
fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) {
|
fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) {
|
||||||
self.popen();
|
self.popen();
|
||||||
self.commasep_exprs(Inconsistent, exprs);
|
self.commasep_exprs(Inconsistent, exprs);
|
||||||
|
|
|
@ -298,6 +298,7 @@ impl<'hir> Map<'hir> {
|
||||||
| Node::TraitRef(_)
|
| Node::TraitRef(_)
|
||||||
| Node::Pat(_)
|
| Node::Pat(_)
|
||||||
| Node::PatField(_)
|
| Node::PatField(_)
|
||||||
|
| Node::ExprField(_)
|
||||||
| Node::Local(_)
|
| Node::Local(_)
|
||||||
| Node::Param(_)
|
| Node::Param(_)
|
||||||
| Node::Arm(_)
|
| Node::Arm(_)
|
||||||
|
@ -1021,6 +1022,7 @@ impl<'hir> Map<'hir> {
|
||||||
Node::Field(field) => field.span,
|
Node::Field(field) => field.span,
|
||||||
Node::AnonConst(constant) => self.body(constant.body).value.span,
|
Node::AnonConst(constant) => self.body(constant.body).value.span,
|
||||||
Node::Expr(expr) => expr.span,
|
Node::Expr(expr) => expr.span,
|
||||||
|
Node::ExprField(field) => field.span,
|
||||||
Node::Stmt(stmt) => stmt.span,
|
Node::Stmt(stmt) => stmt.span,
|
||||||
Node::PathSegment(seg) => {
|
Node::PathSegment(seg) => {
|
||||||
let ident_span = seg.ident.span;
|
let ident_span = seg.ident.span;
|
||||||
|
@ -1243,6 +1245,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
||||||
}
|
}
|
||||||
Some(Node::AnonConst(_)) => node_str("const"),
|
Some(Node::AnonConst(_)) => node_str("const"),
|
||||||
Some(Node::Expr(_)) => node_str("expr"),
|
Some(Node::Expr(_)) => node_str("expr"),
|
||||||
|
Some(Node::ExprField(_)) => node_str("expr field"),
|
||||||
Some(Node::Stmt(_)) => node_str("stmt"),
|
Some(Node::Stmt(_)) => node_str("stmt"),
|
||||||
Some(Node::PathSegment(_)) => node_str("path segment"),
|
Some(Node::PathSegment(_)) => node_str("path segment"),
|
||||||
Some(Node::Ty(_)) => node_str("type"),
|
Some(Node::Ty(_)) => node_str("type"),
|
||||||
|
|
|
@ -653,7 +653,8 @@ impl CheckAttrVisitor<'_> {
|
||||||
| Target::ForeignTy
|
| Target::ForeignTy
|
||||||
| Target::GenericParam(..)
|
| Target::GenericParam(..)
|
||||||
| Target::MacroDef
|
| Target::MacroDef
|
||||||
| Target::PatField => None,
|
| Target::PatField
|
||||||
|
| Target::ExprField => 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;
|
||||||
|
@ -2064,6 +2065,11 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.check_attributes(expr.hir_id, expr.span, target, None);
|
self.check_attributes(expr.hir_id, expr.span, target, None);
|
||||||
|
if let hir::ExprKind::Struct(_, fields, _) = expr.kind {
|
||||||
|
for field in fields {
|
||||||
|
self.check_attributes(field.hir_id, field.span, Target::PatField, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
intravisit::walk_expr(self, expr)
|
intravisit::walk_expr(self, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -257,6 +257,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
|
||||||
| hir::Node::TraitRef(..)
|
| hir::Node::TraitRef(..)
|
||||||
| hir::Node::Pat(..)
|
| hir::Node::Pat(..)
|
||||||
| hir::Node::PatField(..)
|
| hir::Node::PatField(..)
|
||||||
|
| hir::Node::ExprField(..)
|
||||||
| hir::Node::Arm(..)
|
| hir::Node::Arm(..)
|
||||||
| hir::Node::Local(..)
|
| hir::Node::Local(..)
|
||||||
| hir::Node::Ctor(..)
|
| hir::Node::Ctor(..)
|
||||||
|
|
|
@ -126,6 +126,6 @@ fn main() {
|
||||||
struct PatternField {
|
struct PatternField {
|
||||||
foo: i32,
|
foo: i32,
|
||||||
}
|
}
|
||||||
let s = PatternField { foo: 123 };
|
let s = PatternField { #[must_use] foo: 123 }; //~ ERROR `#[must_use]` has no effect
|
||||||
let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect
|
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:129:28
|
||||||
|
|
|
||||||
|
LL | let s = PatternField { #[must_use] foo: 123 };
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to a pattern field
|
error: `#[must_use]` has no effect when applied to a pattern field
|
||||||
--> $DIR/unused_attributes-must_use.rs:130:24
|
--> $DIR/unused_attributes-must_use.rs:130:24
|
||||||
|
|
|
|
||||||
|
@ -177,5 +183,5 @@ error: unused return value of `Use::get_four` that must be used
|
||||||
LL | ().get_four();
|
LL | ().get_four();
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 27 previous errors
|
error: aborting due to 28 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue