about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-04-10 21:03:34 +0200
committerGitHub <noreply@github.com>2022-04-10 21:03:34 +0200
commit54597ba11f73e642797a51f7cdd264613759e693 (patch)
tree4d1eee704eef9e9526117c1f101cb77806fd66fd
parentc0655dec7e5ca0b5ecbd843f47afadb57a657d08 (diff)
parent8412d5dc5c4f284390f89d0352adae56dbc650e9 (diff)
downloadrust-54597ba11f73e642797a51f7cdd264613759e693.tar.gz
rust-54597ba11f73e642797a51f7cdd264613759e693.zip
Rollup merge of #95784 - WaffleLapkin:typeof_cool_suggestion, r=compiler-errors
Suggest replacing `typeof(...)` with an actual type

This PR adds suggestion to replace `typeof(...)` with an actual type of `...`, for example in case of `typeof(1)` we suggest replacing it with `i32`.

If the expression
1. Is not const (`{ let a = 1; let _: typeof(a); }`)
2. Can't be found (`let _: typeof(this_variable_does_not_exist)`)
3. Or has non-suggestable type (closure, generator, error, etc)
we don't suggest anything.

The 1 one is sad, but it's not clear how to support non-consts expressions for `typeof`.

_This PR is inspired by [this tweet]._

[this tweet]: https://twitter.com/compiler_errors/status/1511945354752638976
-rw-r--r--compiler/rustc_error_messages/locales/en-US/diagnostics.ftl1
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs12
-rw-r--r--compiler/rustc_typeck/src/errors.rs7
-rw-r--r--src/test/ui/error-codes/E0516.stderr5
-rw-r--r--src/test/ui/issues/issue-29184.stderr5
-rw-r--r--src/test/ui/typeof/type_mismatch.stderr5
6 files changed, 32 insertions, 3 deletions
diff --git a/compiler/rustc_error_messages/locales/en-US/diagnostics.ftl b/compiler/rustc_error_messages/locales/en-US/diagnostics.ftl
index 336e7a66857..2b1deb34304 100644
--- a/compiler/rustc_error_messages/locales/en-US/diagnostics.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/diagnostics.ftl
@@ -62,6 +62,7 @@ typeck-functional-record-update-on-non-struct =
 
 typeck-typeof-reserved-keyword-used =
     `typeof` is a reserved keyword but unimplemented
+    .suggestion = consider replacing `typeof(...)` with an actual type
     .label = reserved keyword
 
 typeck-return-stmt-outside-of-fn-body =
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index e58617b985d..6bae0f2eac9 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -2460,8 +2460,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 self.normalize_ty(ast_ty.span, array_ty)
             }
             hir::TyKind::Typeof(ref e) => {
-                tcx.sess.emit_err(TypeofReservedKeywordUsed { span: ast_ty.span });
-                tcx.type_of(tcx.hir().local_def_id(e.hir_id))
+                let ty = tcx.type_of(tcx.hir().local_def_id(e.hir_id));
+                let span = ast_ty.span;
+                tcx.sess.emit_err(TypeofReservedKeywordUsed {
+                    span,
+                    ty,
+                    opt_sugg: Some((span, Applicability::MachineApplicable))
+                        .filter(|_| ty.is_suggestable()),
+                });
+
+                ty
             }
             hir::TyKind::Infer => {
                 // Infer also appears as the type of arguments or return
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs
index 0b78aea9f05..1088be5f566 100644
--- a/compiler/rustc_typeck/src/errors.rs
+++ b/compiler/rustc_typeck/src/errors.rs
@@ -1,5 +1,7 @@
 //! Errors emitted by typeck.
+use rustc_errors::Applicability;
 use rustc_macros::SessionDiagnostic;
+use rustc_middle::ty::Ty;
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(SessionDiagnostic)]
@@ -127,10 +129,13 @@ pub struct FunctionalRecordUpdateOnNonStruct {
 
 #[derive(SessionDiagnostic)]
 #[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")]
-pub struct TypeofReservedKeywordUsed {
+pub struct TypeofReservedKeywordUsed<'tcx> {
+    pub ty: Ty<'tcx>,
     #[primary_span]
     #[label]
     pub span: Span,
+    #[suggestion_verbose(message = "suggestion", code = "{ty}")]
+    pub opt_sugg: Option<(Span, Applicability)>,
 }
 
 #[derive(SessionDiagnostic)]
diff --git a/src/test/ui/error-codes/E0516.stderr b/src/test/ui/error-codes/E0516.stderr
index 2e6de5053d5..5243b7caf22 100644
--- a/src/test/ui/error-codes/E0516.stderr
+++ b/src/test/ui/error-codes/E0516.stderr
@@ -3,6 +3,11 @@ error[E0516]: `typeof` is a reserved keyword but unimplemented
    |
 LL |     let x: typeof(92) = 92;
    |            ^^^^^^^^^^ reserved keyword
+   |
+help: consider replacing `typeof(...)` with an actual type
+   |
+LL |     let x: i32 = 92;
+   |            ~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-29184.stderr b/src/test/ui/issues/issue-29184.stderr
index 87d3632ee42..75b6c64f2ce 100644
--- a/src/test/ui/issues/issue-29184.stderr
+++ b/src/test/ui/issues/issue-29184.stderr
@@ -3,6 +3,11 @@ error[E0516]: `typeof` is a reserved keyword but unimplemented
    |
 LL |     let x: typeof(92) = 92;
    |            ^^^^^^^^^^ reserved keyword
+   |
+help: consider replacing `typeof(...)` with an actual type
+   |
+LL |     let x: i32 = 92;
+   |            ~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeof/type_mismatch.stderr b/src/test/ui/typeof/type_mismatch.stderr
index e82b5e44973..e75214cd31a 100644
--- a/src/test/ui/typeof/type_mismatch.stderr
+++ b/src/test/ui/typeof/type_mismatch.stderr
@@ -3,6 +3,11 @@ error[E0516]: `typeof` is a reserved keyword but unimplemented
    |
 LL |     let b: typeof(a) = 1i8;
    |            ^^^^^^^^^ reserved keyword
+   |
+help: consider replacing `typeof(...)` with an actual type
+   |
+LL |     let b: u8 = 1i8;
+   |            ~~
 
 error[E0308]: mismatched types
   --> $DIR/type_mismatch.rs:5:24