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
|
.label = explicit generic argument not allowed
|
||||||
.note = see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
|
.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
|
.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::astconv::AstConv;
|
||||||
|
use crate::errors::MissingTypeParams;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{pluralize, struct_span_err, Applicability, ErrorGuaranteed};
|
use rustc_errors::{pluralize, struct_span_err, Applicability, ErrorGuaranteed};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@ -24,65 +25,13 @@ pub(crate) fn complain_about_missing_type_params(
|
|||||||
if missing_type_params.is_empty() {
|
if missing_type_params.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let display =
|
|
||||||
missing_type_params.iter().map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
|
self.tcx().sess.emit_err(MissingTypeParams {
|
||||||
let mut err = struct_span_err!(
|
|
||||||
self.tcx().sess,
|
|
||||||
span,
|
span,
|
||||||
E0393,
|
def_span: self.tcx().def_span(def_id),
|
||||||
"the type parameter{} {} must be explicitly specified",
|
missing_type_params,
|
||||||
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.
|
|
||||||
empty_generic_args,
|
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
|
/// 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.
|
//! Errors emitted by typeck.
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::{
|
||||||
|
error_code, Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
|
||||||
|
};
|
||||||
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
|
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
|
use rustc_session::{parse::ParseSess, SessionDiagnostic};
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
@ -250,3 +253,63 @@ pub struct ExplicitGenericArgsWithImplTrait {
|
|||||||
#[help]
|
#[help]
|
||||||
pub is_nightly_build: Option<()>,
|
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