about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-12-17 23:20:16 +0000
committerMichael Goulet <michael@errs.io>2022-12-27 17:14:45 +0000
commit3cf22de90fcc23100bbecae3925896409d36aaa9 (patch)
tree45d8d893bbc3e5bed389f6ffc403073b427f5b78
parentb38a6d373cb254697411147c0e49cd2e84864258 (diff)
downloadrust-3cf22de90fcc23100bbecae3925896409d36aaa9.tar.gz
rust-3cf22de90fcc23100bbecae3925896409d36aaa9.zip
Suggest rewriting a malformed hex literal if we expect a float
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs26
-rw-r--r--src/test/ui/suggestions/bad-hex-float-lit.rs13
-rw-r--r--src/test/ui/suggestions/bad-hex-float-lit.stderr48
3 files changed, 87 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 9a7d753e66b..e38d1bccc10 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -19,6 +19,7 @@ use rustc_middle::ty::{
     TypeVisitable,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
@@ -1259,6 +1260,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
                 true
             }
+            ExprKind::Lit(Spanned {
+                node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed),
+                span,
+            }) => {
+                let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; };
+                if !(snippet.starts_with("0x") || snippet.starts_with("0X")) {
+                    return false;
+                }
+                if snippet.len() <= 5 || !snippet.is_char_boundary(snippet.len() - 3) {
+                    return false;
+                }
+                let (_, suffix) = snippet.split_at(snippet.len() - 3);
+                let value = match suffix {
+                    "f32" => (lit - 0xf32) / (16 * 16 * 16),
+                    "f64" => (lit - 0xf64) / (16 * 16 * 16),
+                    _ => return false,
+                };
+                err.span_suggestions(
+                    expr.span,
+                    "rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float",
+                    [format!("0x{value:X} as {suffix}"), format!("{value}_{suffix}")],
+                    Applicability::MaybeIncorrect,
+                );
+                true
+            }
             _ => false,
         }
     }
diff --git a/src/test/ui/suggestions/bad-hex-float-lit.rs b/src/test/ui/suggestions/bad-hex-float-lit.rs
new file mode 100644
index 00000000000..cd6fdbde96c
--- /dev/null
+++ b/src/test/ui/suggestions/bad-hex-float-lit.rs
@@ -0,0 +1,13 @@
+fn main() {
+    let _f: f32 = 0xAAf32;
+    //~^ ERROR mismatched types
+    //~| HELP rewrite this
+
+    let _f: f32 = 0xAB_f32;
+    //~^ ERROR mismatched types
+    //~| HELP rewrite this
+
+    let _f: f64 = 0xFF_f64;
+    //~^ ERROR mismatched types
+    //~| HELP rewrite this
+}
diff --git a/src/test/ui/suggestions/bad-hex-float-lit.stderr b/src/test/ui/suggestions/bad-hex-float-lit.stderr
new file mode 100644
index 00000000000..bc09abb1a56
--- /dev/null
+++ b/src/test/ui/suggestions/bad-hex-float-lit.stderr
@@ -0,0 +1,48 @@
+error[E0308]: mismatched types
+  --> $DIR/bad-hex-float-lit.rs:2:19
+   |
+LL |     let _f: f32 = 0xAAf32;
+   |             ---   ^^^^^^^ expected `f32`, found integer
+   |             |
+   |             expected due to this
+   |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+   |
+LL |     let _f: f32 = 0xAA as f32;
+   |                   ~~~~~~~~~~~
+LL |     let _f: f32 = 170_f32;
+   |                   ~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/bad-hex-float-lit.rs:6:19
+   |
+LL |     let _f: f32 = 0xAB_f32;
+   |             ---   ^^^^^^^^ expected `f32`, found integer
+   |             |
+   |             expected due to this
+   |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+   |
+LL |     let _f: f32 = 0xAB as f32;
+   |                   ~~~~~~~~~~~
+LL |     let _f: f32 = 171_f32;
+   |                   ~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/bad-hex-float-lit.rs:10:19
+   |
+LL |     let _f: f64 = 0xFF_f64;
+   |             ---   ^^^^^^^^ expected `f64`, found integer
+   |             |
+   |             expected due to this
+   |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+   |
+LL |     let _f: f64 = 0xFF as f64;
+   |                   ~~~~~~~~~~~
+LL |     let _f: f64 = 255_f64;
+   |                   ~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.