Skip to content

Commit 78cc331

Browse files
committed
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 <[email protected]>
1 parent de3e8ca commit 78cc331

File tree

3 files changed

+92
-58
lines changed

3 files changed

+92
-58
lines changed

compiler/rustc_error_messages/locales/en-US/typeck.ftl

+22
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,25 @@ typeck-explicit-generic-args-with-impl-trait =
100100
.label = explicit generic argument not allowed
101101
.note = see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
102102
.help = add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
103+
104+
typeck-missing-type-params =
105+
the type {$parameterCount ->
106+
[one] parameter
107+
*[other] parameters
108+
} {$parameters} must be explicitly specified
109+
.label = type {$parameterCount ->
110+
[one] parameter
111+
*[other] parameters
112+
} {$parameters} must be specified for this
113+
.suggestion = set the type {$parameterCount ->
114+
[one] parameter
115+
*[other] parameters
116+
} to the desired {$parameterCount ->
117+
[one] type
118+
*[other] types
119+
}
120+
.no-suggestion-label = missing {$parameterCount ->
121+
[one] reference
122+
*[other] references
123+
} to {$parameters}
124+
.note = because of the default `Self` reference, type parameters must be specified on object types

compiler/rustc_typeck/src/astconv/errors.rs

+6-57
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::astconv::AstConv;
2+
use crate::errors::MissingTypeParams;
23
use rustc_data_structures::fx::FxHashMap;
34
use rustc_errors::{pluralize, struct_span_err, Applicability, ErrorGuaranteed};
45
use rustc_hir as hir;
@@ -24,65 +25,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2425
if missing_type_params.is_empty() {
2526
return;
2627
}
27-
let display =
28-
missing_type_params.iter().map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
29-
let mut err = struct_span_err!(
30-
self.tcx().sess,
28+
29+
self.tcx().sess.emit_err(MissingTypeParams {
3130
span,
32-
E0393,
33-
"the type parameter{} {} must be explicitly specified",
34-
pluralize!(missing_type_params.len()),
35-
display,
36-
);
37-
err.span_label(
38-
self.tcx().def_span(def_id),
39-
&format!(
40-
"type parameter{} {} must be specified for this",
41-
pluralize!(missing_type_params.len()),
42-
display,
43-
),
44-
);
45-
let mut suggested = false;
46-
if let (Ok(snippet), true) = (
47-
self.tcx().sess.source_map().span_to_snippet(span),
48-
// Don't suggest setting the type params if there are some already: the order is
49-
// tricky to get right and the user will already know what the syntax is.
31+
def_span: self.tcx().def_span(def_id),
32+
missing_type_params,
5033
empty_generic_args,
51-
) {
52-
if snippet.ends_with('>') {
53-
// The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
54-
// we would have to preserve the right order. For now, as clearly the user is
55-
// aware of the syntax, we do nothing.
56-
} else {
57-
// The user wrote `Iterator`, so we don't have a type we can suggest, but at
58-
// least we can clue them to the correct syntax `Iterator<Type>`.
59-
err.span_suggestion(
60-
span,
61-
&format!(
62-
"set the type parameter{plural} to the desired type{plural}",
63-
plural = pluralize!(missing_type_params.len()),
64-
),
65-
format!("{}<{}>", snippet, missing_type_params.join(", ")),
66-
Applicability::HasPlaceholders,
67-
);
68-
suggested = true;
69-
}
70-
}
71-
if !suggested {
72-
err.span_label(
73-
span,
74-
format!(
75-
"missing reference{} to {}",
76-
pluralize!(missing_type_params.len()),
77-
display,
78-
),
79-
);
80-
}
81-
err.note(
82-
"because of the default `Self` reference, type parameters must be \
83-
specified on object types",
84-
);
85-
err.emit();
34+
});
8635
}
8736

8837
/// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit

compiler/rustc_typeck/src/errors.rs

+64-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
//! Errors emitted by typeck.
2-
use rustc_errors::Applicability;
2+
use rustc_errors::{
3+
error_code, Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
4+
};
35
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
46
use rustc_middle::ty::Ty;
7+
use rustc_session::{parse::ParseSess, SessionDiagnostic};
58
use rustc_span::{symbol::Ident, Span, Symbol};
69

710
#[derive(SessionDiagnostic)]
@@ -250,3 +253,63 @@ pub struct ExplicitGenericArgsWithImplTrait {
250253
#[help]
251254
pub is_nightly_build: Option<()>,
252255
}
256+
257+
pub struct MissingTypeParams {
258+
pub span: Span,
259+
pub def_span: Span,
260+
pub missing_type_params: Vec<String>,
261+
pub empty_generic_args: bool,
262+
}
263+
264+
// Manual implementation of `SessionDiagnostic` to be able to call `span_to_snippet`.
265+
impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
266+
fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
267+
static SLUG: &'static str = "typeck-missing-type-params";
268+
let mut err = sess.span_diagnostic.struct_span_err_with_code(
269+
self.span,
270+
DiagnosticMessage::fluent(SLUG),
271+
error_code!(E0393),
272+
);
273+
err.set_arg("parameterCount", self.missing_type_params.len());
274+
err.set_arg(
275+
"parameters",
276+
self.missing_type_params
277+
.iter()
278+
.map(|n| format!("`{}`", n))
279+
.collect::<Vec<_>>()
280+
.join(", "),
281+
);
282+
283+
err.span_label(self.def_span, DiagnosticMessage::fluent_attr(SLUG, "label"));
284+
285+
let mut suggested = false;
286+
if let (Ok(snippet), true) = (
287+
sess.source_map().span_to_snippet(self.span),
288+
// Don't suggest setting the type params if there are some already: the order is
289+
// tricky to get right and the user will already know what the syntax is.
290+
self.empty_generic_args,
291+
) {
292+
if snippet.ends_with('>') {
293+
// The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
294+
// we would have to preserve the right order. For now, as clearly the user is
295+
// aware of the syntax, we do nothing.
296+
} else {
297+
// The user wrote `Iterator`, so we don't have a type we can suggest, but at
298+
// least we can clue them to the correct syntax `Iterator<Type>`.
299+
err.span_suggestion(
300+
self.span,
301+
DiagnosticMessage::fluent_attr(SLUG, "suggestion"),
302+
format!("{}<{}>", snippet, self.missing_type_params.join(", ")),
303+
Applicability::HasPlaceholders,
304+
);
305+
suggested = true;
306+
}
307+
}
308+
if !suggested {
309+
err.span_label(self.span, DiagnosticMessage::fluent_attr(SLUG, "no-suggestion-label"));
310+
}
311+
312+
err.note(DiagnosticMessage::fluent_attr(SLUG, "note"));
313+
err
314+
}
315+
}

0 commit comments

Comments
 (0)