diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2019-01-19 20:18:56 -0800 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2019-01-19 20:18:56 -0800 |
| commit | b36bf76dec593269b3c5006c38063315bed5ad51 (patch) | |
| tree | 4912fc570762b4cbc2a43426b7ec0dde3a3758cb | |
| parent | 0c0c585281740aba4c91cbfd385f5e1fbe313d11 (diff) | |
| download | rust-b36bf76dec593269b3c5006c38063315bed5ad51.tar.gz rust-b36bf76dec593269b3c5006c38063315bed5ad51.zip | |
Suggest correct cast for struct fields with shorthand syntax
6 files changed, 132 insertions, 12 deletions
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index c0cedd77440..2aecc0f2ace 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -454,12 +454,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { false } - pub fn check_for_cast(&self, - err: &mut DiagnosticBuilder<'tcx>, - expr: &hir::Expr, - checked_ty: Ty<'tcx>, - expected_ty: Ty<'tcx>) - -> bool { + pub fn check_for_cast( + &self, + err: &mut DiagnosticBuilder<'tcx>, + expr: &hir::Expr, + checked_ty: Ty<'tcx>, + expected_ty: Ty<'tcx>, + ) -> bool { let parent_id = self.tcx.hir().get_parent_node(expr.id); if let Some(parent) = self.tcx.hir().find(parent_id) { // Shouldn't suggest `.into()` on `const`s. @@ -487,17 +488,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // For now, don't suggest casting with `as`. let can_cast = false; + let mut prefix = String::new(); + if let Some(hir::Node::Expr(hir::Expr { + node: hir::ExprKind::Struct(_, fields, _), + .. + })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.id)) { + // `expr` is a literal field for a struct, only suggest if appropriate + for field in fields { + if field.expr.id == expr.id { + // This is a field literal + prefix = format!("{}: ", field.ident); + break; + } + } + if &prefix == "" { + // Likely a field was meant, but this field wasn't found. Do not suggest anything. + return false; + } + } + let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8); if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) { let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty); - let cast_suggestion = format!("{}{}{} as {}", - if needs_paren { "(" } else { "" }, - src, - if needs_paren { ")" } else { "" }, - expected_ty); + let cast_suggestion = format!( + "{}{}{}{} as {}", + prefix, + if needs_paren { "(" } else { "" }, + src, + if needs_paren { ")" } else { "" }, + expected_ty, + ); let into_suggestion = format!( - "{}{}{}.into()", + "{}{}{}{}.into()", + prefix, if needs_paren { "(" } else { "" }, src, if needs_paren { ")" } else { "" }, diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs new file mode 100644 index 00000000000..2ce12220723 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs @@ -0,0 +1,9 @@ +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, c): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r, g, c }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR struct `RGB` has no field named `c` +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr new file mode 100644 index 00000000000..d0f9e1f7f7c --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19 + | +LL | let _ = RGB { r, g, c }; + | ^ expected f64, found f32 +help: you can cast an `f32` to `f64` in a lossless way + | +LL | let _ = RGB { r: r.into(), g, c }; + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22 + | +LL | let _ = RGB { r, g, c }; + | ^ expected f64, found f32 +help: you can cast an `f32` to `f64` in a lossless way + | +LL | let _ = RGB { r, g: g.into(), c }; + | ^^^^^^^^^^^ + +error[E0560]: struct `RGB` has no field named `c` + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25 + | +LL | let _ = RGB { r, g, c }; + | ^ help: a field with a similar name exists: `b` + +error: aborting due to 3 previous errors + +Some errors occurred: E0308, E0560. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed new file mode 100644 index 00000000000..91758c0b218 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(dead_code)] + +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, b): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r: r.into(), g: g.into(), b: b.into() }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs new file mode 100644 index 00000000000..9d3a17a72b2 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(dead_code)] + +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, b): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r, g, b }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr new file mode 100644 index 00000000000..6bc16ba8b70 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr @@ -0,0 +1,33 @@ +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 }; + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22 + | +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, g: g.into(), b }; + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25 + | +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, g, b: b.into() }; + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. |
