Skip to content

Commit 7631b12

Browse files
committed
migrate parser::ty to diagnostic structs
1 parent 9564a30 commit 7631b12

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
@@ -539,3 +539,38 @@ parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...`
539539
.suggestion = to omit remaining fields, use one fewer `.`
540540
541541
parse_expected_comma_after_pattern_field = expected `,`
542+
543+
parse_return_types_use_thin_arrow = return types are denoted using `->`
544+
.suggestion = use `->` instead
545+
546+
parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
547+
548+
parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
549+
.suggestion = add `mut` or `const` here
550+
551+
parse_lifetime_after_mut = lifetime must precede `mut`
552+
.suggestion = place the lifetime before `mut`
553+
554+
parse_dyn_after_mut = `mut` must precede `dyn`
555+
.suggestion = place `mut` before `dyn`
556+
557+
parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
558+
.label = `const` because of this
559+
.suggestion = remove the `const` qualifier
560+
561+
parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
562+
.label = `async` because of this
563+
.suggestion = remove the `async` qualifier
564+
565+
parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
566+
567+
parse_invalid_dyn_keyword = invalid `dyn` keyword
568+
.help = `dyn` is only needed at the start of a trait `+`-separated list
569+
.suggestion = remove this keyword
570+
571+
parse_negative_bounds_not_supported = negative bounds are not supported
572+
.label = negative bounds are not supported
573+
.suggestion = {$num_bounds ->
574+
[one] remove the bound
575+
*[other] remove the bounds
576+
}

compiler/rustc_parse/src/errors.rs

+103
Original file line numberDiff line numberDiff line change
@@ -1845,3 +1845,106 @@ pub(crate) struct ExpectedCommaAfterPatternField {
18451845
#[primary_span]
18461846
pub span: Span,
18471847
}
1848+
1849+
#[derive(Diagnostic)]
1850+
#[diag(parse_return_types_use_thin_arrow)]
1851+
pub(crate) struct ReturnTypesUseThinArrow {
1852+
#[primary_span]
1853+
#[suggestion(style = "short", code = "->", applicability = "machine-applicable")]
1854+
pub span: Span,
1855+
}
1856+
1857+
#[derive(Diagnostic)]
1858+
#[diag(parse_need_plus_after_trait_object_lifetime)]
1859+
pub(crate) struct NeedPlusAfterTraitObjectLifetime {
1860+
#[primary_span]
1861+
pub span: Span,
1862+
}
1863+
1864+
#[derive(Diagnostic)]
1865+
#[diag(parse_expected_mut_or_const_in_raw_pointer_type)]
1866+
pub(crate) struct ExpectedMutOrConstInRawPointerType {
1867+
#[primary_span]
1868+
pub span: Span,
1869+
#[suggestion(code("mut ", "const "), applicability = "has-placeholders")]
1870+
pub after_asterisk: Span,
1871+
}
1872+
1873+
#[derive(Diagnostic)]
1874+
#[diag(parse_lifetime_after_mut)]
1875+
pub(crate) struct LifetimeAfterMut {
1876+
#[primary_span]
1877+
pub span: Span,
1878+
#[suggestion(code = "&{snippet} mut", applicability = "maybe-incorrect")]
1879+
pub suggest_lifetime: Option<Span>,
1880+
pub snippet: String,
1881+
}
1882+
1883+
#[derive(Diagnostic)]
1884+
#[diag(parse_dyn_after_mut)]
1885+
pub(crate) struct DynAfterMut {
1886+
#[primary_span]
1887+
#[suggestion(code = "&mut dyn", applicability = "machine-applicable")]
1888+
pub span: Span,
1889+
}
1890+
1891+
#[derive(Diagnostic)]
1892+
#[diag(parse_fn_pointer_cannot_be_const)]
1893+
pub(crate) struct FnPointerCannotBeConst {
1894+
#[primary_span]
1895+
pub span: Span,
1896+
#[suggestion(code = "", applicability = "maybe-incorrect")]
1897+
#[label]
1898+
pub qualifier: Span,
1899+
}
1900+
1901+
#[derive(Diagnostic)]
1902+
#[diag(parse_fn_pointer_cannot_be_async)]
1903+
pub(crate) struct FnPointerCannotBeAsync {
1904+
#[primary_span]
1905+
pub span: Span,
1906+
#[suggestion(code = "", applicability = "maybe-incorrect")]
1907+
#[label]
1908+
pub qualifier: Span,
1909+
}
1910+
1911+
#[derive(Diagnostic)]
1912+
#[diag(parse_nested_c_variadic_type, code = "E0743")]
1913+
pub(crate) struct NestedCVariadicType {
1914+
#[primary_span]
1915+
pub span: Span,
1916+
}
1917+
1918+
#[derive(Diagnostic)]
1919+
#[diag(parse_invalid_dyn_keyword)]
1920+
#[help]
1921+
pub(crate) struct InvalidDynKeyword {
1922+
#[primary_span]
1923+
#[suggestion(code = "", applicability = "machine-applicable")]
1924+
pub span: Span,
1925+
}
1926+
1927+
#[derive(Diagnostic)]
1928+
#[diag(parse_negative_bounds_not_supported)]
1929+
pub(crate) struct NegativeBoundsNotSupported {
1930+
#[primary_span]
1931+
pub negative_bounds: Vec<Span>,
1932+
#[label]
1933+
pub last_span: Span,
1934+
#[subdiagnostic]
1935+
pub sub: Option<NegativeBoundsNotSupportedSugg>,
1936+
}
1937+
1938+
#[derive(Subdiagnostic)]
1939+
#[suggestion(
1940+
suggestion,
1941+
style = "tool-only",
1942+
code = "{fixed}",
1943+
applicability = "machine-applicable"
1944+
)]
1945+
pub(crate) struct NegativeBoundsNotSupportedSugg {
1946+
#[primary_span]
1947+
pub bound_list: Span,
1948+
pub num_bounds: usize,
1949+
pub fixed: String,
1950+
}

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;
@@ -12,7 +18,7 @@ use rustc_ast::{
1218
MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
1319
};
1420
use rustc_ast_pretty::pprust;
15-
use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
21+
use rustc_errors::{Applicability, PResult};
1622
use rustc_span::source_map::Span;
1723
use rustc_span::symbol::{kw, sym, Ident};
1824
use rustc_span::Symbol;
@@ -233,14 +239,7 @@ impl<'a> Parser<'a> {
233239
// Don't `eat` to prevent `=>` from being added as an expected token which isn't
234240
// actually expected and could only confuse users
235241
self.bump();
236-
self.struct_span_err(self.prev_token.span, "return types are denoted using `->`")
237-
.span_suggestion_short(
238-
self.prev_token.span,
239-
"use `->` instead",
240-
"->",
241-
Applicability::MachineApplicable,
242-
)
243-
.emit();
242+
self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
244243
let ty = self.parse_ty_common(
245244
allow_plus,
246245
AllowCVariadic::No,
@@ -328,7 +327,7 @@ impl<'a> Parser<'a> {
328327
AllowCVariadic::No => {
329328
// FIXME(Centril): Should we just allow `...` syntactically
330329
// anywhere in a type and use semantic restrictions instead?
331-
self.error_illegal_c_varadic_ty(lo);
330+
self.sess.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
332331
TyKind::Err
333332
}
334333
}
@@ -431,8 +430,7 @@ impl<'a> Parser<'a> {
431430
let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
432431
let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
433432
if lt_no_plus {
434-
self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`")
435-
.emit();
433+
self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
436434
}
437435
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
438436
}
@@ -466,14 +464,10 @@ impl<'a> Parser<'a> {
466464
fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
467465
let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
468466
let span = self.prev_token.span;
469-
self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
470-
.span_suggestions(
471-
span.shrink_to_hi(),
472-
"add `mut` or `const` here",
473-
["mut ".to_string(), "const ".to_string()],
474-
Applicability::HasPlaceholders,
475-
)
476-
.emit();
467+
self.sess.emit_err(ExpectedMutOrConstInRawPointerType {
468+
span,
469+
after_asterisk: span.shrink_to_hi(),
470+
});
477471
Mutability::Not
478472
});
479473
let ty = self.parse_ty_no_plus()?;
@@ -528,16 +522,13 @@ impl<'a> Parser<'a> {
528522
let lifetime_span = self.token.span;
529523
let span = and_span.to(lifetime_span);
530524

531-
let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
532-
if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
533-
err.span_suggestion(
534-
span,
535-
"place the lifetime before `mut`",
536-
format!("&{} mut", lifetime_src),
537-
Applicability::MaybeIncorrect,
538-
);
539-
}
540-
err.emit();
525+
let (suggest_lifetime, snippet) =
526+
if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
527+
(Some(span), lifetime_src)
528+
} else {
529+
(None, String::new())
530+
};
531+
self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
541532

542533
opt_lifetime = Some(self.expect_lifetime());
543534
}
@@ -547,14 +538,7 @@ impl<'a> Parser<'a> {
547538
{
548539
// We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
549540
let span = and_span.to(self.look_ahead(1, |t| t.span));
550-
let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
551-
err.span_suggestion(
552-
span,
553-
"place `mut` before `dyn`",
554-
"&mut dyn",
555-
Applicability::MachineApplicable,
556-
);
557-
err.emit();
541+
self.sess.emit_err(DynAfterMut { span });
558542

559543
// Recovery
560544
mutbl = Mutability::Mut;
@@ -608,10 +592,10 @@ impl<'a> Parser<'a> {
608592
// If we ever start to allow `const fn()`, then update
609593
// feature gating for `#![feature(const_extern_fn)]` to
610594
// cover it.
611-
self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
595+
self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
612596
}
613597
if let ast::Async::Yes { span, .. } = asyncness {
614-
self.error_fn_ptr_bad_qualifier(whole_span, span, "async");
598+
self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
615599
}
616600
let decl_span = span_start.to(self.token.span);
617601
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
@@ -659,19 +643,6 @@ impl<'a> Parser<'a> {
659643
Ok(())
660644
}
661645

662-
/// Emit an error for the given bad function pointer qualifier.
663-
fn error_fn_ptr_bad_qualifier(&self, span: Span, qual_span: Span, qual: &str) {
664-
self.struct_span_err(span, &format!("an `fn` pointer type cannot be `{}`", qual))
665-
.span_label(qual_span, format!("`{}` because of this", qual))
666-
.span_suggestion_short(
667-
qual_span,
668-
&format!("remove the `{}` qualifier", qual),
669-
"",
670-
Applicability::MaybeIncorrect,
671-
)
672-
.emit();
673-
}
674-
675646
/// Parses an `impl B0 + ... + Bn` type.
676647
fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
677648
// Always parse bounds greedily for better error recovery.
@@ -758,16 +729,6 @@ impl<'a> Parser<'a> {
758729
}
759730
}
760731

761-
fn error_illegal_c_varadic_ty(&self, lo: Span) {
762-
struct_span_err!(
763-
self.sess.span_diagnostic,
764-
lo.to(self.prev_token.span),
765-
E0743,
766-
"C-variadic type `...` may not be nested inside another type",
767-
)
768-
.emit();
769-
}
770-
771732
pub(super) fn parse_generic_bounds(
772733
&mut self,
773734
colon_span: Option<Span>,
@@ -797,15 +758,7 @@ impl<'a> Parser<'a> {
797758
{
798759
if self.token.is_keyword(kw::Dyn) {
799760
// Account for `&dyn Trait + dyn Other`.
800-
self.struct_span_err(self.token.span, "invalid `dyn` keyword")
801-
.help("`dyn` is only needed at the start of a trait `+`-separated list")
802-
.span_suggestion(
803-
self.token.span,
804-
"remove this keyword",
805-
"",
806-
Applicability::MachineApplicable,
807-
)
808-
.emit();
761+
self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
809762
self.bump();
810763
}
811764
match self.parse_generic_bound()? {
@@ -842,11 +795,7 @@ impl<'a> Parser<'a> {
842795
bounds: &[GenericBound],
843796
negative_bounds: Vec<Span>,
844797
) {
845-
let negative_bounds_len = negative_bounds.len();
846-
let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
847-
let mut err = self.struct_span_err(negative_bounds, "negative bounds are not supported");
848-
err.span_label(last_span, "negative bounds are not supported");
849-
if let Some(bound_list) = colon_span {
798+
let sub = if let Some(bound_list) = colon_span {
850799
let bound_list = bound_list.to(self.prev_token.span);
851800
let mut new_bound_list = String::new();
852801
if !bounds.is_empty() {
@@ -857,14 +806,18 @@ impl<'a> Parser<'a> {
857806
}
858807
new_bound_list = new_bound_list.replacen(" +", ":", 1);
859808
}
860-
err.tool_only_span_suggestion(
809+
810+
Some(NegativeBoundsNotSupportedSugg {
861811
bound_list,
862-
&format!("remove the bound{}", pluralize!(negative_bounds_len)),
863-
new_bound_list,
864-
Applicability::MachineApplicable,
865-
);
866-
}
867-
err.emit();
812+
num_bounds: negative_bounds.len(),
813+
fixed: new_bound_list,
814+
})
815+
} else {
816+
None
817+
};
818+
819+
let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
820+
self.sess.emit_err(NegativeBoundsNotSupported { negative_bounds, last_span, sub });
868821
}
869822

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

0 commit comments

Comments
 (0)