Skip to content

Commit 7b36047

Browse files
committed
Make Node::ExprField a child of Node::Expr.
This was incorrectly inserting the ExprField as a sibling of the struct expression. This required adjusting various parts which were looking at parent node of a field expression to find the struct.
1 parent dcd5177 commit 7b36047

File tree

5 files changed

+139
-148
lines changed

5 files changed

+139
-148
lines changed

compiler/rustc_ast_lowering/src/index.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -226,17 +226,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
226226

227227
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
228228
self.insert(expr.span, expr.hir_id, Node::Expr(expr));
229-
if let ExprKind::Struct(_, fields, _) = expr.kind {
230-
for field in fields {
231-
self.insert(field.span, field.hir_id, Node::ExprField(field));
232-
}
233-
}
234229

235230
self.with_parent(expr.hir_id, |this| {
236231
intravisit::walk_expr(this, expr);
237232
});
238233
}
239234

235+
fn visit_expr_field(&mut self, field: &'hir ExprField<'hir>) {
236+
self.insert(field.span, field.hir_id, Node::ExprField(field));
237+
self.with_parent(field.hir_id, |this| {
238+
intravisit::walk_expr_field(this, field);
239+
});
240+
}
241+
240242
fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) {
241243
self.insert(stmt.span, stmt.hir_id, Node::Stmt(stmt));
242244

compiler/rustc_lint/src/types.rs

+47-51
Original file line numberDiff line numberDiff line change
@@ -125,45 +125,51 @@ fn lint_overflowing_range_endpoint<'tcx>(
125125
lit_val: u128,
126126
max: u128,
127127
expr: &'tcx hir::Expr<'tcx>,
128-
parent_expr: &'tcx hir::Expr<'tcx>,
129128
ty: &str,
130129
) -> bool {
131130
// We only want to handle exclusive (`..`) ranges,
132131
// which are represented as `ExprKind::Struct`.
132+
let par_id = cx.tcx.hir().get_parent_node(expr.hir_id);
133+
let Node::ExprField(field) = cx.tcx.hir().get(par_id) else { return false };
134+
let field_par_id = cx.tcx.hir().get_parent_node(field.hir_id);
135+
let Node::Expr(struct_expr) = cx.tcx.hir().get(field_par_id) else { return false };
136+
if !is_range_literal(struct_expr) {
137+
return false;
138+
};
139+
let ExprKind::Struct(_, eps, _) = &struct_expr.kind else { return false };
140+
if eps.len() != 2 {
141+
return false;
142+
}
143+
133144
let mut overwritten = false;
134-
if let ExprKind::Struct(_, eps, _) = &parent_expr.kind {
135-
if eps.len() != 2 {
136-
return false;
137-
}
138-
// We can suggest using an inclusive range
139-
// (`..=`) instead only if it is the `end` that is
140-
// overflowing and only by 1.
141-
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
142-
cx.struct_span_lint(OVERFLOWING_LITERALS, parent_expr.span, |lint| {
143-
let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
144-
err.set_arg("ty", ty);
145-
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
146-
use ast::{LitIntType, LitKind};
147-
// We need to preserve the literal's suffix,
148-
// as it may determine typing information.
149-
let suffix = match lit.node {
150-
LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
151-
LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
152-
LitKind::Int(_, LitIntType::Unsuffixed) => "",
153-
_ => bug!(),
154-
};
155-
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
156-
err.span_suggestion(
157-
parent_expr.span,
158-
fluent::lint::suggestion,
159-
suggestion,
160-
Applicability::MachineApplicable,
161-
);
162-
err.emit();
163-
overwritten = true;
164-
}
165-
});
166-
}
145+
// We can suggest using an inclusive range
146+
// (`..=`) instead only if it is the `end` that is
147+
// overflowing and only by 1.
148+
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
149+
cx.struct_span_lint(OVERFLOWING_LITERALS, struct_expr.span, |lint| {
150+
let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
151+
err.set_arg("ty", ty);
152+
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
153+
use ast::{LitIntType, LitKind};
154+
// We need to preserve the literal's suffix,
155+
// as it may determine typing information.
156+
let suffix = match lit.node {
157+
LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
158+
LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
159+
LitKind::Int(_, LitIntType::Unsuffixed) => "",
160+
_ => bug!(),
161+
};
162+
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
163+
err.span_suggestion(
164+
struct_expr.span,
165+
fluent::lint::suggestion,
166+
suggestion,
167+
Applicability::MachineApplicable,
168+
);
169+
err.emit();
170+
overwritten = true;
171+
}
172+
});
167173
}
168174
overwritten
169175
}
@@ -339,16 +345,9 @@ fn lint_int_literal<'tcx>(
339345
return;
340346
}
341347

342-
let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
343-
if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
344-
if let hir::ExprKind::Struct(..) = par_e.kind {
345-
if is_range_literal(par_e)
346-
&& lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
347-
{
348-
// The overflowing literal lint was overridden.
349-
return;
350-
}
351-
}
348+
if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
349+
// The overflowing literal lint was overridden.
350+
return;
352351
}
353352

354353
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
@@ -408,16 +407,13 @@ fn lint_uint_literal<'tcx>(
408407
return;
409408
}
410409
}
411-
hir::ExprKind::Struct(..) if is_range_literal(par_e) => {
412-
let t = t.name_str();
413-
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
414-
// The overflowing literal lint was overridden.
415-
return;
416-
}
417-
}
418410
_ => {}
419411
}
420412
}
413+
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
414+
// The overflowing literal lint was overridden.
415+
return;
416+
}
421417
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
422418
report_bin_hex_error(
423419
cx,

compiler/rustc_typeck/src/check/demand.rs

+9-16
Original file line numberDiff line numberDiff line change
@@ -638,11 +638,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
638638
}?;
639639

640640
match hir.find(hir.get_parent_node(expr.hir_id))? {
641-
Node::Expr(hir::Expr { kind: hir::ExprKind::Struct(_, fields, ..), .. }) => {
642-
for field in *fields {
643-
if field.ident.name == local.name && field.is_shorthand {
644-
return Some(local.name);
645-
}
641+
Node::ExprField(field) => {
642+
if field.ident.name == local.name && field.is_shorthand {
643+
return Some(local.name);
646644
}
647645
}
648646
_ => {}
@@ -1073,21 +1071,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10731071

10741072
let mut sugg = vec![];
10751073

1076-
if let Some(hir::Node::Expr(hir::Expr {
1077-
kind: hir::ExprKind::Struct(_, fields, _), ..
1078-
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
1074+
if let Some(hir::Node::ExprField(field)) =
1075+
self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
10791076
{
10801077
// `expr` is a literal field for a struct, only suggest if appropriate
1081-
match (*fields)
1082-
.iter()
1083-
.find(|field| field.expr.hir_id == expr.hir_id && field.is_shorthand)
1084-
{
1078+
if field.is_shorthand {
10851079
// This is a field literal
1086-
Some(field) => {
1087-
sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident)));
1088-
}
1080+
sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident)));
1081+
} else {
10891082
// Likely a field was meant, but this field wasn't found. Do not suggest anything.
1090-
None => return false,
1083+
return false;
10911084
}
10921085
};
10931086

src/test/ui/lint/lint-attr-everywhere-early.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ help: remove these parentheses
2525
|
2626
LL - type BareFnPtr = fn(#[deny(unused_parens)](i32));
2727
LL + type BareFnPtr = fn(#[deny(unused_parens)]i32);
28-
|
28+
|
2929

3030
error: type `ITEM_OUTER` should have an upper camel case name
3131
--> $DIR/lint-attr-everywhere-early.rs:30:8
@@ -198,7 +198,7 @@ help: remove these parentheses
198198
|
199199
LL - type assoc_type = (i32);
200200
LL + type assoc_type = i32;
201-
|
201+
|
202202

203203
error: unnecessary parentheses around type
204204
--> $DIR/lint-attr-everywhere-early.rs:87:31
@@ -215,7 +215,7 @@ help: remove these parentheses
215215
|
216216
LL - #[deny(unused_parens)]f1: (i32),
217217
LL + #[deny(unused_parens)]f1: i32,
218-
|
218+
|
219219

220220
error: unnecessary parentheses around type
221221
--> $DIR/lint-attr-everywhere-early.rs:89:42
@@ -232,7 +232,7 @@ help: remove these parentheses
232232
|
233233
LL - struct StructTuple(#[deny(unused_parens)](i32));
234234
LL + struct StructTuple(#[deny(unused_parens)]i32);
235-
|
235+
|
236236

237237
error: variant `VARIANT_CAMEL` should have an upper camel case name
238238
--> $DIR/lint-attr-everywhere-early.rs:93:5
@@ -261,7 +261,7 @@ help: remove these parentheses
261261
|
262262
LL - fn foreign_denied_from_inner(x: (i32));
263263
LL + fn foreign_denied_from_inner(x: i32);
264-
|
264+
|
265265

266266
error: unnecessary parentheses around type
267267
--> $DIR/lint-attr-everywhere-early.rs:104:37
@@ -278,7 +278,7 @@ help: remove these parentheses
278278
|
279279
LL - fn foreign_denied_from_outer(x: (i32));
280280
LL + fn foreign_denied_from_outer(x: i32);
281-
|
281+
|
282282

283283
error: unnecessary parentheses around type
284284
--> $DIR/lint-attr-everywhere-early.rs:107:43
@@ -295,7 +295,7 @@ help: remove these parentheses
295295
|
296296
LL - fn function(#[deny(unused_parens)] param: (i32)) {}
297297
LL + fn function(#[deny(unused_parens)] param: i32) {}
298-
|
298+
|
299299

300300
error: type parameter `foo` should have an upper camel case name
301301
--> $DIR/lint-attr-everywhere-early.rs:109:42
@@ -324,7 +324,7 @@ help: remove these parentheses
324324
|
325325
LL - let x = (1);
326326
LL + let x = 1;
327-
|
327+
|
328328

329329
error: unnecessary parentheses around type
330330
--> $DIR/lint-attr-everywhere-early.rs:121:50
@@ -341,7 +341,7 @@ help: remove these parentheses
341341
|
342342
LL - let closure = |#[deny(unused_parens)] param: (i32)| {};
343343
LL + let closure = |#[deny(unused_parens)] param: i32| {};
344-
|
344+
|
345345

346346
error: unnecessary parentheses around block return value
347347
--> $DIR/lint-attr-everywhere-early.rs:125:46
@@ -358,7 +358,7 @@ help: remove these parentheses
358358
|
359359
LL - let f = Match{#[deny(unused_parens)]f1: {(123)}};
360360
LL + let f = Match{#[deny(unused_parens)]f1: {123}};
361-
|
361+
|
362362

363363
error: usage of an `unsafe` block
364364
--> $DIR/lint-attr-everywhere-early.rs:132:13

0 commit comments

Comments
 (0)