From 7631b12e3e820f00780fff345019436d36158159 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Tue, 18 Oct 2022 18:03:12 +0200 Subject: [PATCH] migrate parser::ty to diagnostic structs --- .../locales/en-US/parse.ftl | 35 +++++ compiler/rustc_parse/src/errors.rs | 103 +++++++++++++++ compiler/rustc_parse/src/parser/ty.rs | 123 ++++++------------ 3 files changed, 176 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index 5e138a94758..91902081d90 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -539,3 +539,38 @@ parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...` .suggestion = to omit remaining fields, use one fewer `.` parse_expected_comma_after_pattern_field = expected `,` + +parse_return_types_use_thin_arrow = return types are denoted using `->` + .suggestion = use `->` instead + +parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+` + +parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type + .suggestion = add `mut` or `const` here + +parse_lifetime_after_mut = lifetime must precede `mut` + .suggestion = place the lifetime before `mut` + +parse_dyn_after_mut = `mut` must precede `dyn` + .suggestion = place `mut` before `dyn` + +parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const` + .label = `const` because of this + .suggestion = remove the `const` qualifier + +parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async` + .label = `async` because of this + .suggestion = remove the `async` qualifier + +parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type + +parse_invalid_dyn_keyword = invalid `dyn` keyword + .help = `dyn` is only needed at the start of a trait `+`-separated list + .suggestion = remove this keyword + +parse_negative_bounds_not_supported = negative bounds are not supported + .label = negative bounds are not supported + .suggestion = {$num_bounds -> + [one] remove the bound + *[other] remove the bounds + } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 4dfa25eccd5..1abd7577d92 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1845,3 +1845,106 @@ pub(crate) struct ExpectedCommaAfterPatternField { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(parse_return_types_use_thin_arrow)] +pub(crate) struct ReturnTypesUseThinArrow { + #[primary_span] + #[suggestion(style = "short", code = "->", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_need_plus_after_trait_object_lifetime)] +pub(crate) struct NeedPlusAfterTraitObjectLifetime { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_expected_mut_or_const_in_raw_pointer_type)] +pub(crate) struct ExpectedMutOrConstInRawPointerType { + #[primary_span] + pub span: Span, + #[suggestion(code("mut ", "const "), applicability = "has-placeholders")] + pub after_asterisk: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_lifetime_after_mut)] +pub(crate) struct LifetimeAfterMut { + #[primary_span] + pub span: Span, + #[suggestion(code = "&{snippet} mut", applicability = "maybe-incorrect")] + pub suggest_lifetime: Option, + pub snippet: String, +} + +#[derive(Diagnostic)] +#[diag(parse_dyn_after_mut)] +pub(crate) struct DynAfterMut { + #[primary_span] + #[suggestion(code = "&mut dyn", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_fn_pointer_cannot_be_const)] +pub(crate) struct FnPointerCannotBeConst { + #[primary_span] + pub span: Span, + #[suggestion(code = "", applicability = "maybe-incorrect")] + #[label] + pub qualifier: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_fn_pointer_cannot_be_async)] +pub(crate) struct FnPointerCannotBeAsync { + #[primary_span] + pub span: Span, + #[suggestion(code = "", applicability = "maybe-incorrect")] + #[label] + pub qualifier: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_nested_c_variadic_type, code = "E0743")] +pub(crate) struct NestedCVariadicType { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_invalid_dyn_keyword)] +#[help] +pub(crate) struct InvalidDynKeyword { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_negative_bounds_not_supported)] +pub(crate) struct NegativeBoundsNotSupported { + #[primary_span] + pub negative_bounds: Vec, + #[label] + pub last_span: Span, + #[subdiagnostic] + pub sub: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion( + suggestion, + style = "tool-only", + code = "{fixed}", + applicability = "machine-applicable" +)] +pub(crate) struct NegativeBoundsNotSupportedSugg { + #[primary_span] + pub bound_list: Span, + pub num_bounds: usize, + pub fixed: String, +} diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 8b4f0ab8feb..306cbcff149 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,6 +1,12 @@ use super::{Parser, PathStyle, TokenType}; -use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg}; +use crate::errors::{ + DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, + FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg, + InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, + NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType, + ReturnTypesUseThinArrow, +}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use ast::DUMMY_NODE_ID; @@ -12,7 +18,7 @@ use rustc_ast::{ MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind, }; use rustc_ast_pretty::pprust; -use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; @@ -233,14 +239,7 @@ impl<'a> Parser<'a> { // Don't `eat` to prevent `=>` from being added as an expected token which isn't // actually expected and could only confuse users self.bump(); - self.struct_span_err(self.prev_token.span, "return types are denoted using `->`") - .span_suggestion_short( - self.prev_token.span, - "use `->` instead", - "->", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span }); let ty = self.parse_ty_common( allow_plus, AllowCVariadic::No, @@ -328,7 +327,7 @@ impl<'a> Parser<'a> { AllowCVariadic::No => { // FIXME(Centril): Should we just allow `...` syntactically // anywhere in a type and use semantic restrictions instead? - self.error_illegal_c_varadic_ty(lo); + self.sess.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) }); TyKind::Err } } @@ -431,8 +430,7 @@ impl<'a> Parser<'a> { let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()); let bounds = self.parse_generic_bounds_common(allow_plus, None)?; if lt_no_plus { - self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`") - .emit(); + self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo }); } Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } @@ -466,14 +464,10 @@ impl<'a> Parser<'a> { fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> { let mutbl = self.parse_const_or_mut().unwrap_or_else(|| { let span = self.prev_token.span; - self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type") - .span_suggestions( - span.shrink_to_hi(), - "add `mut` or `const` here", - ["mut ".to_string(), "const ".to_string()], - Applicability::HasPlaceholders, - ) - .emit(); + self.sess.emit_err(ExpectedMutOrConstInRawPointerType { + span, + after_asterisk: span.shrink_to_hi(), + }); Mutability::Not }); let ty = self.parse_ty_no_plus()?; @@ -528,16 +522,13 @@ impl<'a> Parser<'a> { let lifetime_span = self.token.span; let span = and_span.to(lifetime_span); - let mut err = self.struct_span_err(span, "lifetime must precede `mut`"); - if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) { - err.span_suggestion( - span, - "place the lifetime before `mut`", - format!("&{} mut", lifetime_src), - Applicability::MaybeIncorrect, - ); - } - err.emit(); + let (suggest_lifetime, snippet) = + if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) { + (Some(span), lifetime_src) + } else { + (None, String::new()) + }; + self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet }); opt_lifetime = Some(self.expect_lifetime()); } @@ -547,14 +538,7 @@ impl<'a> Parser<'a> { { // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`. let span = and_span.to(self.look_ahead(1, |t| t.span)); - let mut err = self.struct_span_err(span, "`mut` must precede `dyn`"); - err.span_suggestion( - span, - "place `mut` before `dyn`", - "&mut dyn", - Applicability::MachineApplicable, - ); - err.emit(); + self.sess.emit_err(DynAfterMut { span }); // Recovery mutbl = Mutability::Mut; @@ -608,10 +592,10 @@ impl<'a> Parser<'a> { // If we ever start to allow `const fn()`, then update // feature gating for `#![feature(const_extern_fn)]` to // cover it. - self.error_fn_ptr_bad_qualifier(whole_span, span, "const"); + self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span }); } if let ast::Async::Yes { span, .. } = asyncness { - self.error_fn_ptr_bad_qualifier(whole_span, span, "async"); + self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span }); } let decl_span = span_start.to(self.token.span); Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span }))) @@ -659,19 +643,6 @@ impl<'a> Parser<'a> { Ok(()) } - /// Emit an error for the given bad function pointer qualifier. - fn error_fn_ptr_bad_qualifier(&self, span: Span, qual_span: Span, qual: &str) { - self.struct_span_err(span, &format!("an `fn` pointer type cannot be `{}`", qual)) - .span_label(qual_span, format!("`{}` because of this", qual)) - .span_suggestion_short( - qual_span, - &format!("remove the `{}` qualifier", qual), - "", - Applicability::MaybeIncorrect, - ) - .emit(); - } - /// Parses an `impl B0 + ... + Bn` type. fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { // Always parse bounds greedily for better error recovery. @@ -758,16 +729,6 @@ impl<'a> Parser<'a> { } } - fn error_illegal_c_varadic_ty(&self, lo: Span) { - struct_span_err!( - self.sess.span_diagnostic, - lo.to(self.prev_token.span), - E0743, - "C-variadic type `...` may not be nested inside another type", - ) - .emit(); - } - pub(super) fn parse_generic_bounds( &mut self, colon_span: Option, @@ -797,15 +758,7 @@ impl<'a> Parser<'a> { { if self.token.is_keyword(kw::Dyn) { // Account for `&dyn Trait + dyn Other`. - self.struct_span_err(self.token.span, "invalid `dyn` keyword") - .help("`dyn` is only needed at the start of a trait `+`-separated list") - .span_suggestion( - self.token.span, - "remove this keyword", - "", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(InvalidDynKeyword { span: self.token.span }); self.bump(); } match self.parse_generic_bound()? { @@ -842,11 +795,7 @@ impl<'a> Parser<'a> { bounds: &[GenericBound], negative_bounds: Vec, ) { - let negative_bounds_len = negative_bounds.len(); - let last_span = *negative_bounds.last().expect("no negative bounds, but still error?"); - let mut err = self.struct_span_err(negative_bounds, "negative bounds are not supported"); - err.span_label(last_span, "negative bounds are not supported"); - if let Some(bound_list) = colon_span { + let sub = if let Some(bound_list) = colon_span { let bound_list = bound_list.to(self.prev_token.span); let mut new_bound_list = String::new(); if !bounds.is_empty() { @@ -857,14 +806,18 @@ impl<'a> Parser<'a> { } new_bound_list = new_bound_list.replacen(" +", ":", 1); } - err.tool_only_span_suggestion( + + Some(NegativeBoundsNotSupportedSugg { bound_list, - &format!("remove the bound{}", pluralize!(negative_bounds_len)), - new_bound_list, - Applicability::MachineApplicable, - ); - } - err.emit(); + num_bounds: negative_bounds.len(), + fixed: new_bound_list, + }) + } else { + None + }; + + let last_span = *negative_bounds.last().expect("no negative bounds, but still error?"); + self.sess.emit_err(NegativeBoundsNotSupported { negative_bounds, last_span, sub }); } /// Parses a bound according to the grammar: