From 6f65b7e64be256df673bca2d6cc1f0e461b9eea7 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 6 Jul 2022 20:09:39 +0900 Subject: [PATCH 1/2] suggest adding a missing zero to a floating point number --- compiler/rustc_typeck/src/check/expr.rs | 23 ++++++++++-- ...issing-zero-to-floating-point-number.fixed | 7 ++++ ...g-missing-zero-to-floating-point-number.rs | 7 ++++ ...ssing-zero-to-floating-point-number.stderr | 36 +++++++++++++++++++ 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed create mode 100644 src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs create mode 100644 src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 45ea04f234288..a79257f0f5ebe 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -2162,14 +2162,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if !expr_t.is_primitive_ty() { self.ban_nonexisting_field(field, base, expr, expr_t); } else { - type_error_struct!( + let field_name = field.to_string(); + let mut err = type_error_struct!( self.tcx().sess, field.span, expr_t, E0610, "`{expr_t}` is a primitive type and therefore doesn't have fields", - ) - .emit(); + ); + if expr_t.is_integral() + && (field_name + .strip_prefix('e') + .or_else(|| field_name.strip_prefix('E')) + .map(|prefix| prefix.chars().all(|c| c.is_numeric())) + .unwrap_or_default() + || field.name == sym::f32 + || field.name == sym::f64) + { + err.span_suggestion_verbose( + field.span.shrink_to_lo(), + "If the number is meant to be a floating point number, consider adding a `0` after the period", + '0', + Applicability::MaybeIncorrect, + ); + } + err.emit(); } self.tcx().ty_error() diff --git a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed new file mode 100644 index 0000000000000..01d3769c1f3b7 --- /dev/null +++ b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +fn main() { + 2.0e1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0f64; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields +} diff --git a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs new file mode 100644 index 0000000000000..c2cbd5d518907 --- /dev/null +++ b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs @@ -0,0 +1,7 @@ +// run-rustfix + +fn main() { + 2.e1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.f64; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields +} diff --git a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr new file mode 100644 index 0000000000000..042f9c727cc72 --- /dev/null +++ b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr @@ -0,0 +1,36 @@ +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:4:7 + | +LL | 2.e1; + | ^^ + | +help: If the number is meant to be a floating point number, consider adding a `0` after the period + | +LL | 2.0e1; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:5:7 + | +LL | 2.f32; + | ^^^ + | +help: If the number is meant to be a floating point number, consider adding a `0` after the period + | +LL | 2.0f32; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:6:7 + | +LL | 2.f64; + | ^^^ + | +help: If the number is meant to be a floating point number, consider adding a `0` after the period + | +LL | 2.0f64; + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0610`. From e03cb7fb9a10bffbec3ccc0a0ca68c6c97112ea8 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 12 Jul 2022 13:59:51 +0900 Subject: [PATCH 2/2] implement a suggestion for a floating point number with a type suffix --- compiler/rustc_typeck/src/check/expr.rs | 42 +++++++++++---- ...g-missing-zero-to-floating-point-number.rs | 21 ++++++++ ...ssing-zero-to-floating-point-number.stderr | 51 +++++++++++++++++++ ...issing-zero-to-floating-point-number.fixed | 4 ++ ...g-missing-zero-to-floating-point-number.rs | 4 ++ ...ssing-zero-to-floating-point-number.stderr | 48 ++++++++++++++++- 6 files changed, 159 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.rs create mode 100644 src/test/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.stderr diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index a79257f0f5ebe..c3fc9776835d1 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -48,7 +48,7 @@ use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TypeVisitable}; use rustc_session::parse::feature_err; use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; -use rustc_span::source_map::Span; +use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Pos}; use rustc_target::spec::abi::Abi::RustIntrinsic; @@ -2170,14 +2170,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0610, "`{expr_t}` is a primitive type and therefore doesn't have fields", ); - if expr_t.is_integral() - && (field_name - .strip_prefix('e') - .or_else(|| field_name.strip_prefix('E')) - .map(|prefix| prefix.chars().all(|c| c.is_numeric())) - .unwrap_or_default() - || field.name == sym::f32 - || field.name == sym::f64) + let is_valid_suffix = |field: String| { + if field == "f32" || field == "f64" { + return true; + } + let mut chars = field.chars().peekable(); + match chars.peek() { + Some('e') | Some('E') => { + chars.next(); + if let Some(c) = chars.peek() + && !c.is_numeric() && *c != '-' && *c != '+' + { + return false; + } + while let Some(c) = chars.peek() { + if !c.is_numeric() { + break; + } + chars.next(); + } + } + _ => (), + } + let suffix = chars.collect::(); + suffix.is_empty() || suffix == "f32" || suffix == "f64" + }; + if let ty::Infer(ty::IntVar(_)) = expr_t.kind() + && let ExprKind::Lit(Spanned { + node: ast::LitKind::Int(_, ast::LitIntType::Unsuffixed), + .. + }) = base.kind + && !base.span.from_expansion() + && is_valid_suffix(field_name) { err.span_suggestion_verbose( field.span.shrink_to_lo(), diff --git a/src/test/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.rs b/src/test/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.rs new file mode 100644 index 0000000000000..501f4b6ef9ebc --- /dev/null +++ b/src/test/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.rs @@ -0,0 +1,21 @@ +macro_rules! num { () => { 1 } } + +fn main() { + let x = 1i32; + x.e10; //~ERROR `i32` is a primitive type and therefore doesn't have fields + + let y = 1; + y.e10; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + + 2u32.e10; //~ERROR `u32` is a primitive type and therefore doesn't have fields + + num!().e10; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + + 2.e10foo; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + + 42._; + //~^ERROR expected identifier, found reserved identifier `_` + //~|ERROR `{integer}` is a primitive type and therefore doesn't have fields + + 42.a; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields +} diff --git a/src/test/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.stderr b/src/test/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.stderr new file mode 100644 index 0000000000000..1ef1d4c28e479 --- /dev/null +++ b/src/test/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.stderr @@ -0,0 +1,51 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:16:8 + | +LL | 42._; + | ^ expected identifier, found reserved identifier + +error[E0610]: `i32` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:5:7 + | +LL | x.e10; + | ^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:8:7 + | +LL | y.e10; + | ^^^ + +error[E0610]: `u32` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:10:10 + | +LL | 2u32.e10; + | ^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:12:12 + | +LL | num!().e10; + | ^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:14:7 + | +LL | 2.e10foo; + | ^^^^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:16:8 + | +LL | 42._; + | ^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:20:8 + | +LL | 42.a; + | ^ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0610`. diff --git a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed index 01d3769c1f3b7..ba83e79005b33 100644 --- a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed +++ b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed @@ -2,6 +2,10 @@ fn main() { 2.0e1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0E1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields 2.0f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields 2.0f64; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0e+12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0e-12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0e1f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields } diff --git a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs index c2cbd5d518907..c102447f60288 100644 --- a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs +++ b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs @@ -2,6 +2,10 @@ fn main() { 2.e1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.E1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields 2.f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields 2.f64; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.e+12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.e-12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.e1f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields } diff --git a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr index 042f9c727cc72..e8e069708a864 100644 --- a/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr +++ b/src/test/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr @@ -12,6 +12,17 @@ LL | 2.0e1; error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:5:7 | +LL | 2.E1; + | ^^ + | +help: If the number is meant to be a floating point number, consider adding a `0` after the period + | +LL | 2.0E1; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:6:7 + | LL | 2.f32; | ^^^ | @@ -21,7 +32,7 @@ LL | 2.0f32; | + error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields - --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:6:7 + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:7:7 | LL | 2.f64; | ^^^ @@ -31,6 +42,39 @@ help: If the number is meant to be a floating point number, consider adding a `0 LL | 2.0f64; | + -error: aborting due to 3 previous errors +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:8:7 + | +LL | 2.e+12; + | ^ + | +help: If the number is meant to be a floating point number, consider adding a `0` after the period + | +LL | 2.0e+12; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:9:7 + | +LL | 2.e-12; + | ^ + | +help: If the number is meant to be a floating point number, consider adding a `0` after the period + | +LL | 2.0e-12; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:10:7 + | +LL | 2.e1f32; + | ^^^^^ + | +help: If the number is meant to be a floating point number, consider adding a `0` after the period + | +LL | 2.0e1f32; + | + + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0610`.