Skip to content

Commit 3bb9fc4

Browse files
authored
Rollup merge of #57769 - estebank:cast-suggestion-struct-field, r=matthewjasper
Suggest correct cast for struct fields with shorthand syntax ``` error[E0308]: mismatched types --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19 | LL | let _ = RGB { r, g, b }; | ^ expected f64, found f32 help: you can cast an `f32` to `f64` in a lossless way | LL | let _ = RGB { r: r.into(), g, b }; | ^^^^^^^^^^^ ``` Fix #52497.
2 parents 627e001 + 5b44b3c commit 3bb9fc4

6 files changed

+132
-12
lines changed

src/librustc_typeck/check/demand.rs

+36-12
Original file line numberDiff line numberDiff line change
@@ -454,12 +454,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
454454
false
455455
}
456456

457-
pub fn check_for_cast(&self,
458-
err: &mut DiagnosticBuilder<'tcx>,
459-
expr: &hir::Expr,
460-
checked_ty: Ty<'tcx>,
461-
expected_ty: Ty<'tcx>)
462-
-> bool {
457+
pub fn check_for_cast(
458+
&self,
459+
err: &mut DiagnosticBuilder<'tcx>,
460+
expr: &hir::Expr,
461+
checked_ty: Ty<'tcx>,
462+
expected_ty: Ty<'tcx>,
463+
) -> bool {
463464
let parent_id = self.tcx.hir().get_parent_node(expr.id);
464465
if let Some(parent) = self.tcx.hir().find(parent_id) {
465466
// Shouldn't suggest `.into()` on `const`s.
@@ -487,17 +488,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
487488
// For now, don't suggest casting with `as`.
488489
let can_cast = false;
489490

491+
let mut prefix = String::new();
492+
if let Some(hir::Node::Expr(hir::Expr {
493+
node: hir::ExprKind::Struct(_, fields, _),
494+
..
495+
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.id)) {
496+
// `expr` is a literal field for a struct, only suggest if appropriate
497+
for field in fields {
498+
if field.expr.id == expr.id && field.is_shorthand {
499+
// This is a field literal
500+
prefix = format!("{}: ", field.ident);
501+
break;
502+
}
503+
}
504+
if &prefix == "" {
505+
// Likely a field was meant, but this field wasn't found. Do not suggest anything.
506+
return false;
507+
}
508+
}
509+
490510
let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8);
491511

492512
if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
493513
let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
494-
let cast_suggestion = format!("{}{}{} as {}",
495-
if needs_paren { "(" } else { "" },
496-
src,
497-
if needs_paren { ")" } else { "" },
498-
expected_ty);
514+
let cast_suggestion = format!(
515+
"{}{}{}{} as {}",
516+
prefix,
517+
if needs_paren { "(" } else { "" },
518+
src,
519+
if needs_paren { ")" } else { "" },
520+
expected_ty,
521+
);
499522
let into_suggestion = format!(
500-
"{}{}{}.into()",
523+
"{}{}{}{}.into()",
524+
prefix,
501525
if needs_paren { "(" } else { "" },
502526
src,
503527
if needs_paren { ")" } else { "" },
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
struct RGB { r: f64, g: f64, b: f64 }
2+
3+
fn main() {
4+
let (r, g, c): (f32, f32, f32) = (0., 0., 0.);
5+
let _ = RGB { r, g, c };
6+
//~^ ERROR mismatched types
7+
//~| ERROR mismatched types
8+
//~| ERROR struct `RGB` has no field named `c`
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19
3+
|
4+
LL | let _ = RGB { r, g, c };
5+
| ^ expected f64, found f32
6+
help: you can cast an `f32` to `f64` in a lossless way
7+
|
8+
LL | let _ = RGB { r: r.into(), g, c };
9+
| ^^^^^^^^^^^
10+
11+
error[E0308]: mismatched types
12+
--> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22
13+
|
14+
LL | let _ = RGB { r, g, c };
15+
| ^ expected f64, found f32
16+
help: you can cast an `f32` to `f64` in a lossless way
17+
|
18+
LL | let _ = RGB { r, g: g.into(), c };
19+
| ^^^^^^^^^^^
20+
21+
error[E0560]: struct `RGB` has no field named `c`
22+
--> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
23+
|
24+
LL | let _ = RGB { r, g, c };
25+
| ^ help: a field with a similar name exists: `b`
26+
27+
error: aborting due to 3 previous errors
28+
29+
Some errors occurred: E0308, E0560.
30+
For more information about an error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
struct RGB { r: f64, g: f64, b: f64 }
5+
6+
fn main() {
7+
let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
8+
let _ = RGB { r: r.into(), g: g.into(), b: b.into() };
9+
//~^ ERROR mismatched types
10+
//~| ERROR mismatched types
11+
//~| ERROR mismatched types
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
struct RGB { r: f64, g: f64, b: f64 }
5+
6+
fn main() {
7+
let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
8+
let _ = RGB { r, g, b };
9+
//~^ ERROR mismatched types
10+
//~| ERROR mismatched types
11+
//~| ERROR mismatched types
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/type-mismatch-struct-field-shorthand.rs:8:19
3+
|
4+
LL | let _ = RGB { r, g, b };
5+
| ^ expected f64, found f32
6+
help: you can cast an `f32` to `f64` in a lossless way
7+
|
8+
LL | let _ = RGB { r: r.into(), g, b };
9+
| ^^^^^^^^^^^
10+
11+
error[E0308]: mismatched types
12+
--> $DIR/type-mismatch-struct-field-shorthand.rs:8:22
13+
|
14+
LL | let _ = RGB { r, g, b };
15+
| ^ expected f64, found f32
16+
help: you can cast an `f32` to `f64` in a lossless way
17+
|
18+
LL | let _ = RGB { r, g: g.into(), b };
19+
| ^^^^^^^^^^^
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/type-mismatch-struct-field-shorthand.rs:8:25
23+
|
24+
LL | let _ = RGB { r, g, b };
25+
| ^ expected f64, found f32
26+
help: you can cast an `f32` to `f64` in a lossless way
27+
|
28+
LL | let _ = RGB { r, g, b: b.into() };
29+
| ^^^^^^^^^^^
30+
31+
error: aborting due to 3 previous errors
32+
33+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)