about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl8
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs38
3 files changed, 56 insertions, 23 deletions
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 8eed5e6eef1..888bdeb2e5b 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -21,6 +21,14 @@ hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool`
     .help = compare with zero instead
     .label = unsupported cast
 
+hir_typeck_cast_unknown_pointer = cannot cast {$to ->
+    [true] to
+    *[false] from
+    } a pointer of an unknown kind
+    .label_to = needs more type information
+    .note = the type information given here is insufficient to check whether the pointer cast is valid
+    .label_from = the type information given here is insufficient to check whether the pointer cast is valid
+
 hir_typeck_const_select_must_be_const = this argument must be a `const fn`
     .help = consult the documentation on `const_eval_select` for more information
 
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 808d5ee8bc1..6e55e6c5a2c 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -33,9 +33,7 @@ use super::FnCtxt;
 use crate::errors;
 use crate::type_error_struct;
 use hir::ExprKind;
-use rustc_errors::{
-    struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-};
+use rustc_errors::{Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::mir::Mutability;
@@ -540,27 +538,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     CastError::UnknownExprPtrKind => false,
                     _ => bug!(),
                 };
-                let mut err = struct_span_err!(
-                    fcx.tcx.sess,
-                    if unknown_cast_to { self.cast_span } else { self.span },
-                    E0641,
-                    "cannot cast {} a pointer of an unknown kind",
-                    if unknown_cast_to { "to" } else { "from" }
-                );
-                if unknown_cast_to {
-                    err.span_label(self.cast_span, "needs more type information");
-                    err.note(
-                        "the type information given here is insufficient to check whether \
-                        the pointer cast is valid",
-                    );
+                let (span, sub) = if unknown_cast_to {
+                    (self.cast_span, errors::CastUnknownPointerSub::To(self.cast_span))
                 } else {
-                    err.span_label(
-                        self.span,
-                        "the type information given here is insufficient to check whether \
-                        the pointer cast is valid",
-                    );
-                }
-                err.emit();
+                    (self.cast_span, errors::CastUnknownPointerSub::From(self.span))
+                };
+                fcx.tcx.sess.emit_err(errors::CastUnknownPointer {
+                    span,
+                    to: unknown_cast_to,
+                    sub,
+                });
             }
             CastError::ForeignNonExhaustiveAdt => {
                 make_invalid_casting_error(
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index fd7bf050664..127a1574a7b 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -565,6 +565,44 @@ pub struct CannotCastToBool<'tcx> {
     pub help: CannotCastToBoolHelp,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_typeck_cast_unknown_pointer, code = "E0641")]
+pub struct CastUnknownPointer {
+    #[primary_span]
+    pub span: Span,
+    pub to: bool,
+    #[subdiagnostic]
+    pub sub: CastUnknownPointerSub,
+}
+
+pub enum CastUnknownPointerSub {
+    To(Span),
+    From(Span),
+}
+
+impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F)
+    where
+        F: Fn(
+            &mut Diagnostic,
+            rustc_errors::SubdiagnosticMessage,
+        ) -> rustc_errors::SubdiagnosticMessage,
+    {
+        match self {
+            CastUnknownPointerSub::To(span) => {
+                let msg = f(diag, crate::fluent_generated::hir_typeck_label_to.into());
+                diag.span_label(span, msg);
+                let msg = f(diag, crate::fluent_generated::hir_typeck_note.into());
+                diag.note(msg);
+            }
+            CastUnknownPointerSub::From(span) => {
+                let msg = f(diag, crate::fluent_generated::hir_typeck_label_from.into());
+                diag.span_label(span, msg);
+            }
+        }
+    }
+}
+
 #[derive(Subdiagnostic)]
 pub enum CannotCastToBoolHelp {
     #[suggestion(