Skip to content

Commit 5167ca8

Browse files
committed
migrate parser::ty to diagnostic structs
1 parent e4e17a3 commit 5167ca8

File tree

3 files changed

+176
-85
lines changed

3 files changed

+176
-85
lines changed

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

+35
Original file line numberDiff line numberDiff line change
@@ -525,3 +525,38 @@ parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...`
525525
.suggestion = to omit remaining fields, use one fewer `.`
526526
527527
parse_expected_comma_after_pattern_field = expected `,`
528+
529+
parse_return_types_use_thin_arrow = return types are denoted using `->`
530+
.suggestion = use `->` instead
531+
532+
parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
533+
534+
parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
535+
.suggestion = add `mut` or `const` here
536+
537+
parse_lifetime_after_mut = lifetime must precede `mut`
538+
.suggestion = place the lifetime before `mut`
539+
540+
parse_dyn_after_mut = `mut` must precede `dyn`
541+
.suggestion = place `mut` before `dyn`
542+
543+
parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
544+
.label = `const` because of this
545+
.suggestion = remove the `const` qualifier
546+
547+
parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
548+
.label = `async` because of this
549+
.suggestion = remove the `async` qualifier
550+
551+
parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
552+
553+
parse_invalid_dyn_keyword = invalid `dyn` keyword
554+
.help = `dyn` is only needed at the start of a trait `+`-separated list
555+
.suggestion = remove this keyword
556+
557+
parse_negative_bounds_not_supported = negative bounds are not supported
558+
.label = negative bounds are not supported
559+
.suggestion = {$num_bounds ->
560+
[one] remove the bound
561+
*[other] remove the bounds
562+
}

compiler/rustc_parse/src/errors.rs

+103
Original file line numberDiff line numberDiff line change
@@ -1770,3 +1770,106 @@ pub(crate) struct ExpectedCommaAfterPatternField {
17701770
#[primary_span]
17711771
pub span: Span,
17721772
}
1773+
1774+
#[derive(Diagnostic)]
1775+
#[diag(parse_return_types_use_thin_arrow)]
1776+
pub(crate) struct ReturnTypesUseThinArrow {
1777+
#[primary_span]
1778+
#[suggestion(style = "short", code = "->", applicability = "machine-applicable")]
1779+
pub span: Span,
1780+
}
1781+
1782+
#[derive(Diagnostic)]
1783+
#[diag(parse_need_plus_after_trait_object_lifetime)]
1784+
pub(crate) struct NeedPlusAfterTraitObjectLifetime {
1785+
#[primary_span]
1786+
pub span: Span,
1787+
}
1788+
1789+
#[derive(Diagnostic)]
1790+
#[diag(parse_expected_mut_or_const_in_raw_pointer_type)]
1791+
pub(crate) struct ExpectedMutOrConstInRawPointerType {
1792+
#[primary_span]
1793+
pub span: Span,
1794+
#[suggestion(code("mut ", "const "), applicability = "has-placeholders")]
1795+
pub after_asterisk: Span,
1796+
}
1797+
1798+
#[derive(Diagnostic)]
1799+
#[diag(parse_lifetime_after_mut)]
1800+
pub(crate) struct LifetimeAfterMut {
1801+
#[primary_span]
1802+
pub span: Span,
1803+
#[suggestion(code = "&{snippet} mut", applicability = "maybe-incorrect")]
1804+
pub suggest_lifetime: Option<Span>,
1805+
pub snippet: String,
1806+
}
1807+
1808+
#[derive(Diagnostic)]
1809+
#[diag(parse_dyn_after_mut)]
1810+
pub(crate) struct DynAfterMut {
1811+
#[primary_span]
1812+
#[suggestion(code = "&mut dyn", applicability = "machine-applicable")]
1813+
pub span: Span,
1814+
}
1815+
1816+
#[derive(Diagnostic)]
1817+
#[diag(parse_fn_pointer_cannot_be_const)]
1818+
pub(crate) struct FnPointerCannotBeConst {
1819+
#[primary_span]
1820+
pub span: Span,
1821+
#[suggestion(code = "", applicability = "maybe-incorrect")]
1822+
#[label]
1823+
pub qualifier: Span,
1824+
}
1825+
1826+
#[derive(Diagnostic)]
1827+
#[diag(parse_fn_pointer_cannot_be_async)]
1828+
pub(crate) struct FnPointerCannotBeAsync {
1829+
#[primary_span]
1830+
pub span: Span,
1831+
#[suggestion(code = "", applicability = "maybe-incorrect")]
1832+
#[label]
1833+
pub qualifier: Span,
1834+
}
1835+
1836+
#[derive(Diagnostic)]
1837+
#[diag(parse_nested_c_variadic_type, code = "E0743")]
1838+
pub(crate) struct NestedCVariadicType {
1839+
#[primary_span]
1840+
pub span: Span,
1841+
}
1842+
1843+
#[derive(Diagnostic)]
1844+
#[diag(parse_invalid_dyn_keyword)]
1845+
#[help]
1846+
pub(crate) struct InvalidDynKeyword {
1847+
#[primary_span]
1848+
#[suggestion(code = "", applicability = "machine-applicable")]
1849+
pub span: Span,
1850+
}
1851+
1852+
#[derive(Diagnostic)]
1853+
#[diag(parse_negative_bounds_not_supported)]
1854+
pub(crate) struct NegativeBoundsNotSupported {
1855+
#[primary_span]
1856+
pub negative_bounds: Vec<Span>,
1857+
#[label]
1858+
pub last_span: Span,
1859+
#[subdiagnostic]
1860+
pub sub: Option<NegativeBoundsNotSupportedSugg>,
1861+
}
1862+
1863+
#[derive(Subdiagnostic)]
1864+
#[suggestion(
1865+
suggestion,
1866+
style = "tool-only",
1867+
code = "{fixed}",
1868+
applicability = "machine-applicable"
1869+
)]
1870+
pub(crate) struct NegativeBoundsNotSupportedSugg {
1871+
#[primary_span]
1872+
pub bound_list: Span,
1873+
pub num_bounds: usize,
1874+
pub fixed: String,
1875+
}

compiler/rustc_parse/src/parser/ty.rs

+38-85
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
use super::{Parser, PathStyle, TokenType};
22

3-
use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg};
3+
use crate::errors::{
4+
DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
5+
FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
6+
InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
7+
NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType,
8+
ReturnTypesUseThinArrow,
9+
};
410
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
511

612
use ast::DUMMY_NODE_ID;
@@ -11,7 +17,7 @@ use rustc_ast::{
1117
self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
1218
MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
1319
};
14-
use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
20+
use rustc_errors::{Applicability, PResult};
1521
use rustc_span::source_map::Span;
1622
use rustc_span::symbol::{kw, sym, Ident};
1723
use rustc_span::Symbol;
@@ -217,14 +223,7 @@ impl<'a> Parser<'a> {
217223
// Don't `eat` to prevent `=>` from being added as an expected token which isn't
218224
// actually expected and could only confuse users
219225
self.bump();
220-
self.struct_span_err(self.prev_token.span, "return types are denoted using `->`")
221-
.span_suggestion_short(
222-
self.prev_token.span,
223-
"use `->` instead",
224-
"->",
225-
Applicability::MachineApplicable,
226-
)
227-
.emit();
226+
self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
228227
let ty = self.parse_ty_common(
229228
allow_plus,
230229
AllowCVariadic::No,
@@ -310,7 +309,7 @@ impl<'a> Parser<'a> {
310309
} else {
311310
// FIXME(Centril): Should we just allow `...` syntactically
312311
// anywhere in a type and use semantic restrictions instead?
313-
self.error_illegal_c_varadic_ty(lo);
312+
self.sess.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
314313
TyKind::Err
315314
}
316315
} else {
@@ -372,8 +371,7 @@ impl<'a> Parser<'a> {
372371
let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
373372
let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
374373
if lt_no_plus {
375-
self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`")
376-
.emit();
374+
self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
377375
}
378376
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
379377
}
@@ -407,14 +405,10 @@ impl<'a> Parser<'a> {
407405
fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
408406
let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
409407
let span = self.prev_token.span;
410-
self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
411-
.span_suggestions(
412-
span.shrink_to_hi(),
413-
"add `mut` or `const` here",
414-
["mut ".to_string(), "const ".to_string()],
415-
Applicability::HasPlaceholders,
416-
)
417-
.emit();
408+
self.sess.emit_err(ExpectedMutOrConstInRawPointerType {
409+
span,
410+
after_asterisk: span.shrink_to_hi(),
411+
});
418412
Mutability::Not
419413
});
420414
let ty = self.parse_ty_no_plus()?;
@@ -469,16 +463,13 @@ impl<'a> Parser<'a> {
469463
let lifetime_span = self.token.span;
470464
let span = and_span.to(lifetime_span);
471465

472-
let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
473-
if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
474-
err.span_suggestion(
475-
span,
476-
"place the lifetime before `mut`",
477-
format!("&{} mut", lifetime_src),
478-
Applicability::MaybeIncorrect,
479-
);
480-
}
481-
err.emit();
466+
let (suggest_lifetime, snippet) =
467+
if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
468+
(Some(span), lifetime_src)
469+
} else {
470+
(None, String::new())
471+
};
472+
self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
482473

483474
opt_lifetime = Some(self.expect_lifetime());
484475
}
@@ -488,14 +479,7 @@ impl<'a> Parser<'a> {
488479
{
489480
// We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
490481
let span = and_span.to(self.look_ahead(1, |t| t.span));
491-
let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
492-
err.span_suggestion(
493-
span,
494-
"place `mut` before `dyn`",
495-
"&mut dyn",
496-
Applicability::MachineApplicable,
497-
);
498-
err.emit();
482+
self.sess.emit_err(DynAfterMut { span });
499483

500484
// Recovery
501485
mutbl = Mutability::Mut;
@@ -549,10 +533,10 @@ impl<'a> Parser<'a> {
549533
// If we ever start to allow `const fn()`, then update
550534
// feature gating for `#![feature(const_extern_fn)]` to
551535
// cover it.
552-
self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
536+
self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
553537
}
554538
if let ast::Async::Yes { span, .. } = asyncness {
555-
self.error_fn_ptr_bad_qualifier(whole_span, span, "async");
539+
self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
556540
}
557541
let decl_span = span_start.to(self.token.span);
558542
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
@@ -600,19 +584,6 @@ impl<'a> Parser<'a> {
600584
Ok(())
601585
}
602586

603-
/// Emit an error for the given bad function pointer qualifier.
604-
fn error_fn_ptr_bad_qualifier(&self, span: Span, qual_span: Span, qual: &str) {
605-
self.struct_span_err(span, &format!("an `fn` pointer type cannot be `{}`", qual))
606-
.span_label(qual_span, format!("`{}` because of this", qual))
607-
.span_suggestion_short(
608-
qual_span,
609-
&format!("remove the `{}` qualifier", qual),
610-
"",
611-
Applicability::MaybeIncorrect,
612-
)
613-
.emit();
614-
}
615-
616587
/// Parses an `impl B0 + ... + Bn` type.
617588
fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
618589
// Always parse bounds greedily for better error recovery.
@@ -699,16 +670,6 @@ impl<'a> Parser<'a> {
699670
}
700671
}
701672

702-
fn error_illegal_c_varadic_ty(&self, lo: Span) {
703-
struct_span_err!(
704-
self.sess.span_diagnostic,
705-
lo.to(self.prev_token.span),
706-
E0743,
707-
"C-variadic type `...` may not be nested inside another type",
708-
)
709-
.emit();
710-
}
711-
712673
pub(super) fn parse_generic_bounds(
713674
&mut self,
714675
colon_span: Option<Span>,
@@ -736,15 +697,7 @@ impl<'a> Parser<'a> {
736697
{
737698
if self.token.is_keyword(kw::Dyn) {
738699
// Account for `&dyn Trait + dyn Other`.
739-
self.struct_span_err(self.token.span, "invalid `dyn` keyword")
740-
.help("`dyn` is only needed at the start of a trait `+`-separated list")
741-
.span_suggestion(
742-
self.token.span,
743-
"remove this keyword",
744-
"",
745-
Applicability::MachineApplicable,
746-
)
747-
.emit();
700+
self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
748701
self.bump();
749702
}
750703
match self.parse_generic_bound()? {
@@ -781,11 +734,7 @@ impl<'a> Parser<'a> {
781734
bounds: &[GenericBound],
782735
negative_bounds: Vec<Span>,
783736
) {
784-
let negative_bounds_len = negative_bounds.len();
785-
let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
786-
let mut err = self.struct_span_err(negative_bounds, "negative bounds are not supported");
787-
err.span_label(last_span, "negative bounds are not supported");
788-
if let Some(bound_list) = colon_span {
737+
let sub = if let Some(bound_list) = colon_span {
789738
let bound_list = bound_list.to(self.prev_token.span);
790739
let mut new_bound_list = String::new();
791740
if !bounds.is_empty() {
@@ -796,14 +745,18 @@ impl<'a> Parser<'a> {
796745
}
797746
new_bound_list = new_bound_list.replacen(" +", ":", 1);
798747
}
799-
err.tool_only_span_suggestion(
748+
749+
Some(NegativeBoundsNotSupportedSugg {
800750
bound_list,
801-
&format!("remove the bound{}", pluralize!(negative_bounds_len)),
802-
new_bound_list,
803-
Applicability::MachineApplicable,
804-
);
805-
}
806-
err.emit();
751+
num_bounds: negative_bounds.len(),
752+
fixed: new_bound_list,
753+
})
754+
} else {
755+
None
756+
};
757+
758+
let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
759+
self.sess.emit_err(NegativeBoundsNotSupported { negative_bounds, last_span, sub });
807760
}
808761

809762
/// Parses a bound according to the grammar:

0 commit comments

Comments
 (0)