Skip to content

Commit

Permalink
error-msg: impl better suggestion for E0532
Browse files Browse the repository at this point in the history
  • Loading branch information
Ezrashaw committed Mar 15, 2023
1 parent bd43458 commit bd17322
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 17 deletions.
48 changes: 32 additions & 16 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,25 +1289,41 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
let span = find_span(&source, err);
err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here"));
let (tail, descr, applicability) = match source {
PathSource::Pat | PathSource::TupleStruct(..) => {
("", "pattern", Applicability::MachineApplicable)
}
_ => (": val", "literal", Applicability::HasPlaceholders),
};

let (tail, descr, applicability, old_fields) = match source {
PathSource::Pat => ("", "pattern", Applicability::MachineApplicable, None),
PathSource::TupleStruct(_, args) => (
"",
"pattern",
Applicability::MachineApplicable,
Some(
args.iter()
.map(|a| self.r.tcx.sess.source_map().span_to_snippet(*a).ok())
.collect::<Vec<Option<String>>>(),
),
),
_ => (": val", "literal", Applicability::HasPlaceholders, None),
};
let field_ids = self.r.field_def_ids(def_id);
let (fields, applicability) = match field_ids {
Some(field_ids) => (
field_ids
.iter()
.map(|&field_id| {
format!("{}{tail}", self.r.tcx.item_name(field_id))
})
.collect::<Vec<String>>()
.join(", "),
applicability,
),
Some(field_ids) => {
let fields = field_ids.iter().map(|&id| self.r.tcx.item_name(id));

let fields = if let Some(old_fields) = old_fields {
fields
.enumerate()
.map(|(idx, new)| (new, old_fields.get(idx)))
.map(|(new, old)| {
let new = new.to_ident_string();
if let Some(Some(old)) = old && new != *old { format!("{}: {}", new, old) } else { new }
})
.collect::<Vec<String>>()
} else {
fields.map(|f| format!("{f}{tail}")).collect::<Vec<String>>()
};

(fields.join(", "), applicability)
}
None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
};
let pad = match field_ids {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/issues/issue-19086.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | FooB { x: i32, y: i32 }
| ----------------------- `FooB` defined here
...
LL | FooB(a, b) => println!("{} {}", a, b),
| ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }`
| ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: b }`

error: aborting due to previous error

Expand Down
44 changes: 44 additions & 0 deletions tests/ui/pattern/issue-106862.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// run-rustfix

#![allow(unused)]

use Foo::{FooB, FooA};

enum Foo {
FooA { opt_x: Option<i32>, y: i32 },
FooB { x: i32, y: i32 }
}

fn main() {
let f = FooB { x: 3, y: 4 };

match f {
FooB { x: a, y: b } => println!("{} {}", a, b),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
_ => (),
}

match f {
FooB { x, y } => println!("{} {}", x, y),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
_ => (),
}

match f {
FooA { opt_x: Some(x), y } => println!("{} {}", x, y),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooA`
_ => (),
}

match f {
FooB { x: a, y: _ } => println!("{}", a),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
_ => (),
}

match f {
FooB { x, y } => (),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
_ => (),
}
}
44 changes: 44 additions & 0 deletions tests/ui/pattern/issue-106862.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// run-rustfix

#![allow(unused)]

use Foo::{FooB, FooA};

enum Foo {
FooA { opt_x: Option<i32>, y: i32 },
FooB { x: i32, y: i32 }
}

fn main() {
let f = FooB { x: 3, y: 4 };

match f {
FooB(a, b) => println!("{} {}", a, b),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
_ => (),
}

match f {
FooB(x, y) => println!("{} {}", x, y),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
_ => (),
}

match f {
FooA(Some(x), y) => println!("{} {}", x, y),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooA`
_ => (),
}

match f {
FooB(a, _, _) => println!("{}", a),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
_ => (),
}

match f {
FooB() => (),
//~^ ERROR expected tuple struct or tuple variant, found variant `FooB`
_ => (),
}
}
48 changes: 48 additions & 0 deletions tests/ui/pattern/issue-106862.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
--> $DIR/issue-106862.rs:16:9
|
LL | FooB { x: i32, y: i32 }
| ----------------------- `FooB` defined here
...
LL | FooB(a, b) => println!("{} {}", a, b),
| ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: b }`

error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
--> $DIR/issue-106862.rs:22:9
|
LL | FooB { x: i32, y: i32 }
| ----------------------- `FooB` defined here
...
LL | FooB(x, y) => println!("{} {}", x, y),
| ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }`

error[E0532]: expected tuple struct or tuple variant, found variant `FooA`
--> $DIR/issue-106862.rs:28:9
|
LL | FooA { opt_x: Option<i32>, y: i32 },
| ----------------------------------- `FooA` defined here
...
LL | FooA(Some(x), y) => println!("{} {}", x, y),
| ^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FooA { opt_x: Some(x), y }`

error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
--> $DIR/issue-106862.rs:34:9
|
LL | FooB { x: i32, y: i32 }
| ----------------------- `FooB` defined here
...
LL | FooB(a, _, _) => println!("{}", a),
| ^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: _ }`

error[E0532]: expected tuple struct or tuple variant, found variant `FooB`
--> $DIR/issue-106862.rs:40:9
|
LL | FooB { x: i32, y: i32 }
| ----------------------- `FooB` defined here
...
LL | FooB() => (),
| ^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0532`.

0 comments on commit bd17322

Please sign in to comment.