Skip to content

Commit dae6dc6

Browse files
Fix try wrapping expression in variant suggestion with struct field shorthand
1 parent de9b573 commit dae6dc6

File tree

3 files changed

+92
-34
lines changed

3 files changed

+92
-34
lines changed

compiler/rustc_typeck/src/check/demand.rs

+62-25
Original file line numberDiff line numberDiff line change
@@ -338,31 +338,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
338338
})
339339
.collect();
340340

341-
if let [variant] = &compatible_variants[..] {
342-
// Just a single matching variant.
343-
err.multipart_suggestion(
344-
&format!("try wrapping the expression in `{}`", variant),
345-
vec![
346-
(expr.span.shrink_to_lo(), format!("{}(", variant)),
347-
(expr.span.shrink_to_hi(), ")".to_string()),
348-
],
349-
Applicability::MaybeIncorrect,
350-
);
351-
} else if compatible_variants.len() > 1 {
352-
// More than one matching variant.
353-
err.multipart_suggestions(
354-
&format!(
355-
"try wrapping the expression in a variant of `{}`",
356-
self.tcx.def_path_str(expected_adt.did)
357-
),
358-
compatible_variants.into_iter().map(|variant| {
359-
vec![
360-
(expr.span.shrink_to_lo(), format!("{}(", variant)),
361-
(expr.span.shrink_to_hi(), ")".to_string()),
362-
]
363-
}),
364-
Applicability::MaybeIncorrect,
365-
);
341+
if self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span) {
342+
if let Ok(code) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
343+
match &compatible_variants[..] {
344+
[] => { /* No variants to format */ }
345+
[variant] => {
346+
// Just a single matching variant.
347+
err.span_suggestion_verbose(
348+
expr.span,
349+
&format!("try wrapping the expression in `{}`", variant),
350+
format!("{}: {}({})", code, variant, code),
351+
Applicability::MaybeIncorrect,
352+
);
353+
}
354+
_ => {
355+
// More than one matching variant.
356+
err.span_suggestions(
357+
expr.span,
358+
&format!(
359+
"try wrapping the expression in a variant of `{}`",
360+
self.tcx.def_path_str(expected_adt.did)
361+
),
362+
compatible_variants
363+
.into_iter()
364+
.map(|variant| format!("{}: {}({})", code, variant, code)),
365+
Applicability::MaybeIncorrect,
366+
);
367+
}
368+
}
369+
} else {
370+
/* Can't format this without a snippet */
371+
}
372+
} else {
373+
match &compatible_variants[..] {
374+
[] => { /* No variants to format */ }
375+
[variant] => {
376+
// Just a single matching variant.
377+
err.multipart_suggestion_verbose(
378+
&format!("try wrapping the expression in `{}`", variant),
379+
vec![
380+
(expr.span.shrink_to_lo(), format!("{}(", variant)),
381+
(expr.span.shrink_to_hi(), ")".to_string()),
382+
],
383+
Applicability::MaybeIncorrect,
384+
);
385+
}
386+
_ => {
387+
// More than one matching variant.
388+
err.multipart_suggestions(
389+
&format!(
390+
"try wrapping the expression in a variant of `{}`",
391+
self.tcx.def_path_str(expected_adt.did)
392+
),
393+
compatible_variants.into_iter().map(|variant| {
394+
vec![
395+
(expr.span.shrink_to_lo(), format!("{}(", variant)),
396+
(expr.span.shrink_to_hi(), ")".to_string()),
397+
]
398+
}),
399+
Applicability::MaybeIncorrect,
400+
);
401+
}
402+
}
366403
}
367404
}
368405
}

src/test/ui/did_you_mean/compatible-variants.rs

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ enum Hey<A, B> {
33
B(B),
44
}
55

6+
struct Foo {
7+
bar: Option<i32>,
8+
}
9+
610
fn f() {}
711

812
fn a() -> Option<()> {
@@ -40,4 +44,8 @@ fn main() {
4044
let _: Hey<i32, bool> = false;
4145
//~^ ERROR mismatched types
4246
//~| HELP try wrapping
47+
let bar = 1i32;
48+
let _ = Foo { bar };
49+
//~^ ERROR mismatched types
50+
//~| HELP try wrapping
4351
}

src/test/ui/did_you_mean/compatible-variants.stderr

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/compatible-variants.rs:9:5
2+
--> $DIR/compatible-variants.rs:13:5
33
|
44
LL | fn a() -> Option<()> {
55
| ---------- expected `Option<()>` because of return type
@@ -21,7 +21,7 @@ LL + Some(())
2121
|
2222

2323
error[E0308]: mismatched types
24-
--> $DIR/compatible-variants.rs:17:5
24+
--> $DIR/compatible-variants.rs:21:5
2525
|
2626
LL | fn b() -> Result<(), ()> {
2727
| -------------- expected `Result<(), ()>` because of return type
@@ -37,7 +37,7 @@ LL + Ok(())
3737
|
3838

3939
error[E0308]: mismatched types
40-
--> $DIR/compatible-variants.rs:23:25
40+
--> $DIR/compatible-variants.rs:27:25
4141
|
4242
LL | let _: Option<()> = while false {};
4343
| ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
@@ -52,7 +52,7 @@ LL | let _: Option<()> = Some(while false {});
5252
| +++++ +
5353

5454
error[E0308]: mismatched types
55-
--> $DIR/compatible-variants.rs:27:9
55+
--> $DIR/compatible-variants.rs:31:9
5656
|
5757
LL | while false {}
5858
| ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
@@ -69,7 +69,7 @@ LL + Some(())
6969
|
7070

7171
error[E0308]: mismatched types
72-
--> $DIR/compatible-variants.rs:31:31
72+
--> $DIR/compatible-variants.rs:35:31
7373
|
7474
LL | let _: Result<i32, i32> = 1;
7575
| ---------------- ^ expected enum `Result`, found integer
@@ -86,7 +86,7 @@ LL | let _: Result<i32, i32> = Err(1);
8686
| ++++ +
8787

8888
error[E0308]: mismatched types
89-
--> $DIR/compatible-variants.rs:34:26
89+
--> $DIR/compatible-variants.rs:38:26
9090
|
9191
LL | let _: Option<i32> = 1;
9292
| ----------- ^ expected enum `Option`, found integer
@@ -101,7 +101,7 @@ LL | let _: Option<i32> = Some(1);
101101
| +++++ +
102102

103103
error[E0308]: mismatched types
104-
--> $DIR/compatible-variants.rs:37:28
104+
--> $DIR/compatible-variants.rs:41:28
105105
|
106106
LL | let _: Hey<i32, i32> = 1;
107107
| ------------- ^ expected enum `Hey`, found integer
@@ -118,7 +118,7 @@ LL | let _: Hey<i32, i32> = Hey::B(1);
118118
| +++++++ +
119119

120120
error[E0308]: mismatched types
121-
--> $DIR/compatible-variants.rs:40:29
121+
--> $DIR/compatible-variants.rs:44:29
122122
|
123123
LL | let _: Hey<i32, bool> = false;
124124
| -------------- ^^^^^ expected enum `Hey`, found `bool`
@@ -132,6 +132,19 @@ help: try wrapping the expression in `Hey::B`
132132
LL | let _: Hey<i32, bool> = Hey::B(false);
133133
| +++++++ +
134134

135-
error: aborting due to 8 previous errors
135+
error[E0308]: mismatched types
136+
--> $DIR/compatible-variants.rs:48:19
137+
|
138+
LL | let _ = Foo { bar };
139+
| ^^^ expected enum `Option`, found `i32`
140+
|
141+
= note: expected enum `Option<i32>`
142+
found type `i32`
143+
help: try wrapping the expression in `Some`
144+
|
145+
LL | let _ = Foo { bar: Some(bar) };
146+
| ~~~~~~~~~~~~~~
147+
148+
error: aborting due to 9 previous errors
136149

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

0 commit comments

Comments
 (0)