about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_error_messages/locales/en-US/typeck.ftl22
-rw-r--r--compiler/rustc_typeck/src/astconv/errors.rs63
-rw-r--r--compiler/rustc_typeck/src/errors.rs65
3 files changed, 92 insertions, 58 deletions
diff --git a/compiler/rustc_error_messages/locales/en-US/typeck.ftl b/compiler/rustc_error_messages/locales/en-US/typeck.ftl
index be1a45fd872..a6b2b1dbd6a 100644
--- a/compiler/rustc_error_messages/locales/en-US/typeck.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/typeck.ftl
@@ -100,3 +100,25 @@ typeck-explicit-generic-args-with-impl-trait =
     .label = explicit generic argument not allowed
     .note = see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
     .help = add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
+
+typeck-missing-type-params =
+    the type {$parameterCount ->
+        [one] parameter
+        *[other] parameters
+    } {$parameters} must be explicitly specified
+    .label = type {$parameterCount ->
+        [one] parameter
+        *[other] parameters
+    } {$parameters} must be specified for this
+    .suggestion = set the type {$parameterCount ->
+        [one] parameter
+        *[other] parameters
+    } to the desired {$parameterCount ->
+        [one] type
+        *[other] types
+    }
+    .no-suggestion-label = missing {$parameterCount ->
+        [one] reference
+        *[other] references
+    } to {$parameters}
+    .note = because of the default `Self` reference, type parameters must be specified on object types
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs
index 38cc74a5e37..5cfed81017f 100644
--- a/compiler/rustc_typeck/src/astconv/errors.rs
+++ b/compiler/rustc_typeck/src/astconv/errors.rs
@@ -1,4 +1,5 @@
 use crate::astconv::AstConv;
+use crate::errors::MissingTypeParams;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -24,65 +25,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         if missing_type_params.is_empty() {
             return;
         }
-        let display =
-            missing_type_params.iter().map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
-        let mut err = struct_span_err!(
-            self.tcx().sess,
+
+        self.tcx().sess.emit_err(MissingTypeParams {
             span,
-            E0393,
-            "the type parameter{} {} must be explicitly specified",
-            pluralize!(missing_type_params.len()),
-            display,
-        );
-        err.span_label(
-            self.tcx().def_span(def_id),
-            &format!(
-                "type parameter{} {} must be specified for this",
-                pluralize!(missing_type_params.len()),
-                display,
-            ),
-        );
-        let mut suggested = false;
-        if let (Ok(snippet), true) = (
-            self.tcx().sess.source_map().span_to_snippet(span),
-            // Don't suggest setting the type params if there are some already: the order is
-            // tricky to get right and the user will already know what the syntax is.
+            def_span: self.tcx().def_span(def_id),
+            missing_type_params,
             empty_generic_args,
-        ) {
-            if snippet.ends_with('>') {
-                // The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
-                // we would have to preserve the right order. For now, as clearly the user is
-                // aware of the syntax, we do nothing.
-            } else {
-                // The user wrote `Iterator`, so we don't have a type we can suggest, but at
-                // least we can clue them to the correct syntax `Iterator<Type>`.
-                err.span_suggestion(
-                    span,
-                    &format!(
-                        "set the type parameter{plural} to the desired type{plural}",
-                        plural = pluralize!(missing_type_params.len()),
-                    ),
-                    format!("{}<{}>", snippet, missing_type_params.join(", ")),
-                    Applicability::HasPlaceholders,
-                );
-                suggested = true;
-            }
-        }
-        if !suggested {
-            err.span_label(
-                span,
-                format!(
-                    "missing reference{} to {}",
-                    pluralize!(missing_type_params.len()),
-                    display,
-                ),
-            );
-        }
-        err.note(
-            "because of the default `Self` reference, type parameters must be \
-                  specified on object types",
-        );
-        err.emit();
+        });
     }
 
     /// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs
index 540fd63e137..93900ae24bb 100644
--- a/compiler/rustc_typeck/src/errors.rs
+++ b/compiler/rustc_typeck/src/errors.rs
@@ -1,7 +1,10 @@
 //! Errors emitted by typeck.
-use rustc_errors::Applicability;
+use rustc_errors::{
+    error_code, Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
+};
 use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
 use rustc_middle::ty::Ty;
+use rustc_session::{parse::ParseSess, SessionDiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(SessionDiagnostic)]
@@ -250,3 +253,63 @@ pub struct ExplicitGenericArgsWithImplTrait {
     #[help]
     pub is_nightly_build: Option<()>,
 }
+
+pub struct MissingTypeParams {
+    pub span: Span,
+    pub def_span: Span,
+    pub missing_type_params: Vec<String>,
+    pub empty_generic_args: bool,
+}
+
+// Manual implementation of `SessionDiagnostic` to be able to call `span_to_snippet`.
+impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
+    fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+        static SLUG: &'static str = "typeck-missing-type-params";
+        let mut err = sess.span_diagnostic.struct_span_err_with_code(
+            self.span,
+            DiagnosticMessage::fluent(SLUG),
+            error_code!(E0393),
+        );
+        err.set_arg("parameterCount", self.missing_type_params.len());
+        err.set_arg(
+            "parameters",
+            self.missing_type_params
+                .iter()
+                .map(|n| format!("`{}`", n))
+                .collect::<Vec<_>>()
+                .join(", "),
+        );
+
+        err.span_label(self.def_span, DiagnosticMessage::fluent_attr(SLUG, "label"));
+
+        let mut suggested = false;
+        if let (Ok(snippet), true) = (
+            sess.source_map().span_to_snippet(self.span),
+            // Don't suggest setting the type params if there are some already: the order is
+            // tricky to get right and the user will already know what the syntax is.
+            self.empty_generic_args,
+        ) {
+            if snippet.ends_with('>') {
+                // The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
+                // we would have to preserve the right order. For now, as clearly the user is
+                // aware of the syntax, we do nothing.
+            } else {
+                // The user wrote `Iterator`, so we don't have a type we can suggest, but at
+                // least we can clue them to the correct syntax `Iterator<Type>`.
+                err.span_suggestion(
+                    self.span,
+                    DiagnosticMessage::fluent_attr(SLUG, "suggestion"),
+                    format!("{}<{}>", snippet, self.missing_type_params.join(", ")),
+                    Applicability::HasPlaceholders,
+                );
+                suggested = true;
+            }
+        }
+        if !suggested {
+            err.span_label(self.span, DiagnosticMessage::fluent_attr(SLUG, "no-suggestion-label"));
+        }
+
+        err.note(DiagnosticMessage::fluent_attr(SLUG, "note"));
+        err
+    }
+}