migrate parser::ty to diagnostic structs
This commit is contained in:
parent
9564a30c19
commit
7631b12e3e
3 changed files with 176 additions and 85 deletions
|
@ -539,3 +539,38 @@ parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...`
|
||||||
.suggestion = to omit remaining fields, use one fewer `.`
|
.suggestion = to omit remaining fields, use one fewer `.`
|
||||||
|
|
||||||
parse_expected_comma_after_pattern_field = expected `,`
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1845,3 +1845,106 @@ pub(crate) struct ExpectedCommaAfterPatternField {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: 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<Span>,
|
||||||
|
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<Span>,
|
||||||
|
#[label]
|
||||||
|
pub last_span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sub: Option<NegativeBoundsNotSupportedSugg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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,
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
use super::{Parser, PathStyle, TokenType};
|
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 crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
||||||
|
|
||||||
use ast::DUMMY_NODE_ID;
|
use ast::DUMMY_NODE_ID;
|
||||||
|
@ -12,7 +18,7 @@ use rustc_ast::{
|
||||||
MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
|
MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_ast_pretty::pprust;
|
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::source_map::Span;
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::Symbol;
|
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
|
// Don't `eat` to prevent `=>` from being added as an expected token which isn't
|
||||||
// actually expected and could only confuse users
|
// actually expected and could only confuse users
|
||||||
self.bump();
|
self.bump();
|
||||||
self.struct_span_err(self.prev_token.span, "return types are denoted using `->`")
|
self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
|
||||||
.span_suggestion_short(
|
|
||||||
self.prev_token.span,
|
|
||||||
"use `->` instead",
|
|
||||||
"->",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
let ty = self.parse_ty_common(
|
let ty = self.parse_ty_common(
|
||||||
allow_plus,
|
allow_plus,
|
||||||
AllowCVariadic::No,
|
AllowCVariadic::No,
|
||||||
|
@ -328,7 +327,7 @@ impl<'a> Parser<'a> {
|
||||||
AllowCVariadic::No => {
|
AllowCVariadic::No => {
|
||||||
// FIXME(Centril): Should we just allow `...` syntactically
|
// FIXME(Centril): Should we just allow `...` syntactically
|
||||||
// anywhere in a type and use semantic restrictions instead?
|
// 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
|
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 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)?;
|
let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
|
||||||
if lt_no_plus {
|
if lt_no_plus {
|
||||||
self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`")
|
self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
|
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
|
||||||
}
|
}
|
||||||
|
@ -466,14 +464,10 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
|
fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
|
||||||
let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
|
let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
|
||||||
let span = self.prev_token.span;
|
let span = self.prev_token.span;
|
||||||
self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
|
self.sess.emit_err(ExpectedMutOrConstInRawPointerType {
|
||||||
.span_suggestions(
|
span,
|
||||||
span.shrink_to_hi(),
|
after_asterisk: span.shrink_to_hi(),
|
||||||
"add `mut` or `const` here",
|
});
|
||||||
["mut ".to_string(), "const ".to_string()],
|
|
||||||
Applicability::HasPlaceholders,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
Mutability::Not
|
Mutability::Not
|
||||||
});
|
});
|
||||||
let ty = self.parse_ty_no_plus()?;
|
let ty = self.parse_ty_no_plus()?;
|
||||||
|
@ -528,16 +522,13 @@ impl<'a> Parser<'a> {
|
||||||
let lifetime_span = self.token.span;
|
let lifetime_span = self.token.span;
|
||||||
let span = and_span.to(lifetime_span);
|
let span = and_span.to(lifetime_span);
|
||||||
|
|
||||||
let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
|
let (suggest_lifetime, snippet) =
|
||||||
if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
|
if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
|
||||||
err.span_suggestion(
|
(Some(span), lifetime_src)
|
||||||
span,
|
} else {
|
||||||
"place the lifetime before `mut`",
|
(None, String::new())
|
||||||
format!("&{} mut", lifetime_src),
|
};
|
||||||
Applicability::MaybeIncorrect,
|
self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
|
||||||
);
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
|
|
||||||
opt_lifetime = Some(self.expect_lifetime());
|
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 ...`.
|
// 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 span = and_span.to(self.look_ahead(1, |t| t.span));
|
||||||
let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
|
self.sess.emit_err(DynAfterMut { span });
|
||||||
err.span_suggestion(
|
|
||||||
span,
|
|
||||||
"place `mut` before `dyn`",
|
|
||||||
"&mut dyn",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
err.emit();
|
|
||||||
|
|
||||||
// Recovery
|
// Recovery
|
||||||
mutbl = Mutability::Mut;
|
mutbl = Mutability::Mut;
|
||||||
|
@ -608,10 +592,10 @@ impl<'a> Parser<'a> {
|
||||||
// If we ever start to allow `const fn()`, then update
|
// If we ever start to allow `const fn()`, then update
|
||||||
// feature gating for `#![feature(const_extern_fn)]` to
|
// feature gating for `#![feature(const_extern_fn)]` to
|
||||||
// cover it.
|
// 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 {
|
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);
|
let decl_span = span_start.to(self.token.span);
|
||||||
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
|
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
|
||||||
|
@ -659,19 +643,6 @@ impl<'a> Parser<'a> {
|
||||||
Ok(())
|
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.
|
/// Parses an `impl B0 + ... + Bn` type.
|
||||||
fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
|
fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
|
||||||
// Always parse bounds greedily for better error recovery.
|
// 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(
|
pub(super) fn parse_generic_bounds(
|
||||||
&mut self,
|
&mut self,
|
||||||
colon_span: Option<Span>,
|
colon_span: Option<Span>,
|
||||||
|
@ -797,15 +758,7 @@ impl<'a> Parser<'a> {
|
||||||
{
|
{
|
||||||
if self.token.is_keyword(kw::Dyn) {
|
if self.token.is_keyword(kw::Dyn) {
|
||||||
// Account for `&dyn Trait + dyn Other`.
|
// Account for `&dyn Trait + dyn Other`.
|
||||||
self.struct_span_err(self.token.span, "invalid `dyn` keyword")
|
self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
|
||||||
.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.bump();
|
self.bump();
|
||||||
}
|
}
|
||||||
match self.parse_generic_bound()? {
|
match self.parse_generic_bound()? {
|
||||||
|
@ -842,11 +795,7 @@ impl<'a> Parser<'a> {
|
||||||
bounds: &[GenericBound],
|
bounds: &[GenericBound],
|
||||||
negative_bounds: Vec<Span>,
|
negative_bounds: Vec<Span>,
|
||||||
) {
|
) {
|
||||||
let negative_bounds_len = negative_bounds.len();
|
let sub = if let Some(bound_list) = colon_span {
|
||||||
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 bound_list = bound_list.to(self.prev_token.span);
|
let bound_list = bound_list.to(self.prev_token.span);
|
||||||
let mut new_bound_list = String::new();
|
let mut new_bound_list = String::new();
|
||||||
if !bounds.is_empty() {
|
if !bounds.is_empty() {
|
||||||
|
@ -857,14 +806,18 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
new_bound_list = new_bound_list.replacen(" +", ":", 1);
|
new_bound_list = new_bound_list.replacen(" +", ":", 1);
|
||||||
}
|
}
|
||||||
err.tool_only_span_suggestion(
|
|
||||||
|
Some(NegativeBoundsNotSupportedSugg {
|
||||||
bound_list,
|
bound_list,
|
||||||
&format!("remove the bound{}", pluralize!(negative_bounds_len)),
|
num_bounds: negative_bounds.len(),
|
||||||
new_bound_list,
|
fixed: new_bound_list,
|
||||||
Applicability::MachineApplicable,
|
})
|
||||||
);
|
} else {
|
||||||
}
|
None
|
||||||
err.emit();
|
};
|
||||||
|
|
||||||
|
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:
|
/// Parses a bound according to the grammar:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue