|
1 | 1 | //! Errors emitted by typeck.
|
2 |
| -use rustc_errors::Applicability; |
| 2 | +use rustc_errors::{ |
| 3 | + error_code, Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, |
| 4 | +}; |
3 | 5 | use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
|
4 | 6 | use rustc_middle::ty::Ty;
|
| 7 | +use rustc_session::{parse::ParseSess, SessionDiagnostic}; |
5 | 8 | use rustc_span::{symbol::Ident, Span, Symbol};
|
6 | 9 |
|
7 | 10 | #[derive(SessionDiagnostic)]
|
@@ -250,3 +253,63 @@ pub struct ExplicitGenericArgsWithImplTrait {
|
250 | 253 | #[help]
|
251 | 254 | pub is_nightly_build: Option<()>,
|
252 | 255 | }
|
| 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