Skip to content

Commit 1385a32

Browse files
authored
Rollup merge of #108971 - Ezrashaw:E0532-better-binding-names, r=WaffleLapkin
error-msg: impl better suggestion for `E0532` Fixes #106862 No test as there is already a test which is nearly identical to the example in the linked issue.
2 parents aa881f1 + bd17322 commit 1385a32

File tree

5 files changed

+169
-17
lines changed

5 files changed

+169
-17
lines changed

compiler/rustc_resolve/src/late/diagnostics.rs

+32-16
Original file line numberDiff line numberDiff line change
@@ -1289,25 +1289,41 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
12891289
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
12901290
let span = find_span(&source, err);
12911291
err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here"));
1292-
let (tail, descr, applicability) = match source {
1293-
PathSource::Pat | PathSource::TupleStruct(..) => {
1294-
("", "pattern", Applicability::MachineApplicable)
1295-
}
1296-
_ => (": val", "literal", Applicability::HasPlaceholders),
1297-
};
12981292

1293+
let (tail, descr, applicability, old_fields) = match source {
1294+
PathSource::Pat => ("", "pattern", Applicability::MachineApplicable, None),
1295+
PathSource::TupleStruct(_, args) => (
1296+
"",
1297+
"pattern",
1298+
Applicability::MachineApplicable,
1299+
Some(
1300+
args.iter()
1301+
.map(|a| self.r.tcx.sess.source_map().span_to_snippet(*a).ok())
1302+
.collect::<Vec<Option<String>>>(),
1303+
),
1304+
),
1305+
_ => (": val", "literal", Applicability::HasPlaceholders, None),
1306+
};
12991307
let field_ids = self.r.field_def_ids(def_id);
13001308
let (fields, applicability) = match field_ids {
1301-
Some(field_ids) => (
1302-
field_ids
1303-
.iter()
1304-
.map(|&field_id| {
1305-
format!("{}{tail}", self.r.tcx.item_name(field_id))
1306-
})
1307-
.collect::<Vec<String>>()
1308-
.join(", "),
1309-
applicability,
1310-
),
1309+
Some(field_ids) => {
1310+
let fields = field_ids.iter().map(|&id| self.r.tcx.item_name(id));
1311+
1312+
let fields = if let Some(old_fields) = old_fields {
1313+
fields
1314+
.enumerate()
1315+
.map(|(idx, new)| (new, old_fields.get(idx)))
1316+
.map(|(new, old)| {
1317+
let new = new.to_ident_string();
1318+
if let Some(Some(old)) = old && new != *old { format!("{}: {}", new, old) } else { new }
1319+
})
1320+
.collect::<Vec<String>>()
1321+
} else {
1322+
fields.map(|f| format!("{f}{tail}")).collect::<Vec<String>>()
1323+
};
1324+
1325+
(fields.join(", "), applicability)
1326+
}
13111327
None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
13121328
};
13131329
let pad = match field_ids {

tests/ui/issues/issue-19086.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | FooB { x: i32, y: i32 }
55
| ----------------------- `FooB` defined here
66
...
77
LL | FooB(a, b) => println!("{} {}", a, b),
8-
| ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }`
8+
| ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: b }`
99

1010
error: aborting due to previous error
1111

tests/ui/pattern/issue-106862.fixed

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// run-rustfix
2+
3+
#![allow(unused)]
4+
5+
use Foo::{FooB, FooA};
6+
7+
enum Foo {
8+
FooA { opt_x: Option<i32>, y: i32 },
9+
FooB { x: i32, y: i32 }
10+
}
11+
12+
fn main() {
13+
let f = FooB { x: 3, y: 4 };
14+
15+
match f {
16+
FooB { x: a, y: b } => println!("{} {}", a, b),
17+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
18+
_ => (),
19+
}
20+
21+
match f {
22+
FooB { x, y } => println!("{} {}", x, y),
23+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
24+
_ => (),
25+
}
26+
27+
match f {
28+
FooA { opt_x: Some(x), y } => println!("{} {}", x, y),
29+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooA`
30+
_ => (),
31+
}
32+
33+
match f {
34+
FooB { x: a, y: _ } => println!("{}", a),
35+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
36+
_ => (),
37+
}
38+
39+
match f {
40+
FooB { x, y } => (),
41+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
42+
_ => (),
43+
}
44+
}

tests/ui/pattern/issue-106862.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// run-rustfix
2+
3+
#![allow(unused)]
4+
5+
use Foo::{FooB, FooA};
6+
7+
enum Foo {
8+
FooA { opt_x: Option<i32>, y: i32 },
9+
FooB { x: i32, y: i32 }
10+
}
11+
12+
fn main() {
13+
let f = FooB { x: 3, y: 4 };
14+
15+
match f {
16+
FooB(a, b) => println!("{} {}", a, b),
17+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
18+
_ => (),
19+
}
20+
21+
match f {
22+
FooB(x, y) => println!("{} {}", x, y),
23+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
24+
_ => (),
25+
}
26+
27+
match f {
28+
FooA(Some(x), y) => println!("{} {}", x, y),
29+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooA`
30+
_ => (),
31+
}
32+
33+
match f {
34+
FooB(a, _, _) => println!("{}", a),
35+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
36+
_ => (),
37+
}
38+
39+
match f {
40+
FooB() => (),
41+
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
42+
_ => (),
43+
}
44+
}

tests/ui/pattern/issue-106862.stderr

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
2+
--> $DIR/issue-106862.rs:16:9
3+
|
4+
LL | FooB { x: i32, y: i32 }
5+
| ----------------------- `FooB` defined here
6+
...
7+
LL | FooB(a, b) => println!("{} {}", a, b),
8+
| ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: b }`
9+
10+
error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
11+
--> $DIR/issue-106862.rs:22:9
12+
|
13+
LL | FooB { x: i32, y: i32 }
14+
| ----------------------- `FooB` defined here
15+
...
16+
LL | FooB(x, y) => println!("{} {}", x, y),
17+
| ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }`
18+
19+
error[E0532]: expected tuple struct or tuple variant, found variant `FooA`
20+
--> $DIR/issue-106862.rs:28:9
21+
|
22+
LL | FooA { opt_x: Option<i32>, y: i32 },
23+
| ----------------------------------- `FooA` defined here
24+
...
25+
LL | FooA(Some(x), y) => println!("{} {}", x, y),
26+
| ^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FooA { opt_x: Some(x), y }`
27+
28+
error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
29+
--> $DIR/issue-106862.rs:34:9
30+
|
31+
LL | FooB { x: i32, y: i32 }
32+
| ----------------------- `FooB` defined here
33+
...
34+
LL | FooB(a, _, _) => println!("{}", a),
35+
| ^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: _ }`
36+
37+
error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
38+
--> $DIR/issue-106862.rs:40:9
39+
|
40+
LL | FooB { x: i32, y: i32 }
41+
| ----------------------- `FooB` defined here
42+
...
43+
LL | FooB() => (),
44+
| ^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }`
45+
46+
error: aborting due to 5 previous errors
47+
48+
For more information about this error, try `rustc --explain E0532`.

0 commit comments

Comments
 (0)