typeck: port "missing type params"
Port the "the type parameter `T` must be explicitly specified" diagnostic to using a diagnostic struct. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
de3e8ca2f3
commit
78cc331bd7
@ -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
|
||||
|
@ -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 @@ pub(crate) fn complain_about_missing_type_params(
|
||||
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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user