Skip to content

Commit 2f7a226

Browse files
authored
Rollup merge of rust-lang#57540 - estebank:eval-more, r=petrochenkov
Modify some parser diagnostics to continue evaluating beyond the parser Continue evaluating further errors after parser errors on: - trailing type argument attribute - lifetime in incorrect location - incorrect binary literal - missing `for` in `impl Trait for Foo` - type argument in `where` clause - incorrect float literal - incorrect `..` in pattern - associated types - incorrect discriminator value variant error and others. All of these were found by making `continue-parse-after-error` `true` by default to identify errors that would need few changes. There are now only a handful of errors that have any change with `continue-parse-after-error` enabled. These changes make it so `rust` _won't_ stop evaluation after finishing parsing, enabling type checking errors to be displayed on the existing code without having to fix the parse errors. Each commit has an individual diagnostic change with their corresponding tests. CC rust-lang#48724.
2 parents 816e31b + 28ea03e commit 2f7a226

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+344
-141
lines changed

src/libsyntax/parse/lexer/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl<'a> StringReader<'a> {
299299

300300
/// Report a lexical error with a given span.
301301
fn err_span(&self, sp: Span, m: &str) {
302-
self.sess.span_diagnostic.span_err(sp, m)
302+
self.sess.span_diagnostic.struct_span_err(sp, m).emit();
303303
}
304304

305305

src/libsyntax/parse/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ fn filtered_float_lit(data: Symbol, suffix: Option<Symbol>, diag: Option<(Span,
520520
} else {
521521
let msg = format!("invalid suffix `{}` for float literal", suf);
522522
diag.struct_span_err(span, &msg)
523+
.span_label(span, format!("invalid suffix `{}`", suf))
523524
.help("valid suffixes are `f32` and `f64`")
524525
.emit();
525526
}
@@ -673,7 +674,11 @@ fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
673674
_ => None,
674675
};
675676
if let Some(err) = err {
676-
err!(diag, |span, diag| diag.span_err(span, err));
677+
err!(diag, |span, diag| {
678+
diag.struct_span_err(span, err)
679+
.span_label(span, "not supported")
680+
.emit();
681+
});
677682
}
678683
return filtered_float_lit(Symbol::intern(s), Some(suf), diag)
679684
}
@@ -712,6 +717,7 @@ fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
712717
} else {
713718
let msg = format!("invalid suffix `{}` for numeric literal", suf);
714719
diag.struct_span_err(span, &msg)
720+
.span_label(span, format!("invalid suffix `{}`", suf))
715721
.help("the suffix must be one of the integral types \
716722
(`u32`, `isize`, etc)")
717723
.emit();

src/libsyntax/parse/parser.rs

+114-29
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,10 @@ impl<'a> Parser<'a> {
10121012
if text.is_empty() {
10131013
self.span_bug(sp, "found empty literal suffix in Some")
10141014
}
1015-
self.span_err(sp, &format!("{} with a suffix is invalid", kind));
1015+
let msg = format!("{} with a suffix is invalid", kind);
1016+
self.struct_span_err(sp, &msg)
1017+
.span_label(sp, msg)
1018+
.emit();
10161019
}
10171020
}
10181021
}
@@ -1768,9 +1771,11 @@ impl<'a> Parser<'a> {
17681771
Mutability::Immutable
17691772
} else {
17701773
let span = self.prev_span;
1771-
self.span_err(span,
1772-
"expected mut or const in raw pointer type (use \
1773-
`*mut T` or `*const T` as appropriate)");
1774+
let msg = "expected mut or const in raw pointer type";
1775+
self.struct_span_err(span, msg)
1776+
.span_label(span, msg)
1777+
.help("use `*mut T` or `*const T` as appropriate")
1778+
.emit();
17741779
Mutability::Immutable
17751780
};
17761781
let t = self.parse_ty_no_plus()?;
@@ -3815,8 +3820,12 @@ impl<'a> Parser<'a> {
38153820
ddpos = Some(fields.len());
38163821
} else {
38173822
// Emit a friendly error, ignore `..` and continue parsing
3818-
self.span_err(self.prev_span,
3819-
"`..` can only be used once per tuple or tuple struct pattern");
3823+
self.struct_span_err(
3824+
self.prev_span,
3825+
"`..` can only be used once per tuple or tuple struct pattern",
3826+
)
3827+
.span_label(self.prev_span, "can only be used once per pattern")
3828+
.emit();
38203829
}
38213830
} else if !self.check(&token::CloseDelim(token::Paren)) {
38223831
fields.push(self.parse_pat(None)?);
@@ -3832,7 +3841,10 @@ impl<'a> Parser<'a> {
38323841

38333842
if ddpos == Some(fields.len()) && trailing_comma {
38343843
// `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
3835-
self.span_err(self.prev_span, "trailing comma is not permitted after `..`");
3844+
let msg = "trailing comma is not permitted after `..`";
3845+
self.struct_span_err(self.prev_span, msg)
3846+
.span_label(self.prev_span, msg)
3847+
.emit();
38363848
}
38373849

38383850
Ok((fields, ddpos, trailing_comma))
@@ -5256,8 +5268,12 @@ impl<'a> Parser<'a> {
52565268
// Check for trailing attributes and stop parsing.
52575269
if !attrs.is_empty() {
52585270
let param_kind = if seen_ty_param.is_some() { "type" } else { "lifetime" };
5259-
self.span_err(attrs[0].span,
5260-
&format!("trailing attribute after {} parameters", param_kind));
5271+
self.struct_span_err(
5272+
attrs[0].span,
5273+
&format!("trailing attribute after {} parameters", param_kind),
5274+
)
5275+
.span_label(attrs[0].span, "attributes must go before parameters")
5276+
.emit();
52615277
}
52625278
break
52635279
}
@@ -5315,39 +5331,62 @@ impl<'a> Parser<'a> {
53155331

53165332
/// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
53175333
/// possibly including trailing comma.
5318-
fn parse_generic_args(&mut self)
5319-
-> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
5334+
fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
53205335
let mut args = Vec::new();
53215336
let mut bindings = Vec::new();
53225337
let mut seen_type = false;
53235338
let mut seen_binding = false;
5339+
let mut first_type_or_binding_span: Option<Span> = None;
5340+
let mut bad_lifetime_pos = vec![];
5341+
let mut last_comma_span = None;
5342+
let mut suggestions = vec![];
53245343
loop {
53255344
if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
53265345
// Parse lifetime argument.
53275346
args.push(GenericArg::Lifetime(self.expect_lifetime()));
53285347
if seen_type || seen_binding {
5329-
self.span_err(self.prev_span,
5330-
"lifetime parameters must be declared prior to type parameters");
5348+
let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span);
5349+
bad_lifetime_pos.push(self.prev_span);
5350+
if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) {
5351+
suggestions.push((remove_sp, String::new()));
5352+
suggestions.push((
5353+
first_type_or_binding_span.unwrap().shrink_to_lo(),
5354+
format!("{}, ", snippet)));
5355+
}
53315356
}
53325357
} else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) {
53335358
// Parse associated type binding.
53345359
let lo = self.span;
53355360
let ident = self.parse_ident()?;
53365361
self.bump();
53375362
let ty = self.parse_ty()?;
5363+
let span = lo.to(self.prev_span);
53385364
bindings.push(TypeBinding {
53395365
id: ast::DUMMY_NODE_ID,
53405366
ident,
53415367
ty,
5342-
span: lo.to(self.prev_span),
5368+
span,
53435369
});
53445370
seen_binding = true;
5371+
if first_type_or_binding_span.is_none() {
5372+
first_type_or_binding_span = Some(span);
5373+
}
53455374
} else if self.check_type() {
53465375
// Parse type argument.
53475376
let ty_param = self.parse_ty()?;
53485377
if seen_binding {
5349-
self.span_err(ty_param.span,
5350-
"type parameters must be declared prior to associated type bindings");
5378+
self.struct_span_err(
5379+
ty_param.span,
5380+
"type parameters must be declared prior to associated type bindings"
5381+
)
5382+
.span_label(
5383+
ty_param.span,
5384+
"must be declared prior to associated type bindings",
5385+
)
5386+
.emit();
5387+
}
5388+
if first_type_or_binding_span.is_none() {
5389+
first_type_or_binding_span = Some(ty_param.span);
53515390
}
53525391
args.push(GenericArg::Type(ty_param));
53535392
seen_type = true;
@@ -5357,7 +5396,29 @@ impl<'a> Parser<'a> {
53575396

53585397
if !self.eat(&token::Comma) {
53595398
break
5399+
} else {
5400+
last_comma_span = Some(self.prev_span);
5401+
}
5402+
}
5403+
if !bad_lifetime_pos.is_empty() {
5404+
let mut err = self.struct_span_err(
5405+
bad_lifetime_pos.clone(),
5406+
"lifetime parameters must be declared prior to type parameters"
5407+
);
5408+
for sp in &bad_lifetime_pos {
5409+
err.span_label(*sp, "must be declared prior to type parameters");
5410+
}
5411+
if !suggestions.is_empty() {
5412+
err.multipart_suggestion_with_applicability(
5413+
&format!(
5414+
"move the lifetime parameter{} prior to the first type parameter",
5415+
if bad_lifetime_pos.len() > 1 { "s" } else { "" },
5416+
),
5417+
suggestions,
5418+
Applicability::MachineApplicable,
5419+
);
53605420
}
5421+
err.emit();
53615422
}
53625423
Ok((args, bindings))
53635424
}
@@ -5386,8 +5447,12 @@ impl<'a> Parser<'a> {
53865447
// change we parse those generics now, but report an error.
53875448
if self.choose_generics_over_qpath() {
53885449
let generics = self.parse_generics()?;
5389-
self.span_err(generics.span,
5390-
"generic parameters on `where` clauses are reserved for future use");
5450+
self.struct_span_err(
5451+
generics.span,
5452+
"generic parameters on `where` clauses are reserved for future use",
5453+
)
5454+
.span_label(generics.span, "currently unsupported")
5455+
.emit();
53915456
}
53925457

53935458
loop {
@@ -5587,15 +5652,20 @@ impl<'a> Parser<'a> {
55875652
// *mut self
55885653
// *not_self
55895654
// Emit special error for `self` cases.
5655+
let msg = "cannot pass `self` by raw pointer";
55905656
(if isolated_self(self, 1) {
55915657
self.bump();
5592-
self.span_err(self.span, "cannot pass `self` by raw pointer");
5658+
self.struct_span_err(self.span, msg)
5659+
.span_label(self.span, msg)
5660+
.emit();
55935661
SelfKind::Value(Mutability::Immutable)
55945662
} else if self.look_ahead(1, |t| t.is_mutability()) &&
55955663
isolated_self(self, 2) {
55965664
self.bump();
55975665
self.bump();
5598-
self.span_err(self.span, "cannot pass `self` by raw pointer");
5666+
self.struct_span_err(self.span, msg)
5667+
.span_label(self.span, msg)
5668+
.emit();
55995669
SelfKind::Value(Mutability::Immutable)
56005670
} else {
56015671
return Ok(None);
@@ -5932,7 +6002,10 @@ impl<'a> Parser<'a> {
59326002
tps.where_clause = self.parse_where_clause()?;
59336003
self.expect(&token::Semi)?;
59346004
if unsafety != Unsafety::Normal {
5935-
self.span_err(self.prev_span, "trait aliases cannot be unsafe");
6005+
let msg = "trait aliases cannot be unsafe";
6006+
self.struct_span_err(self.prev_span, msg)
6007+
.span_label(self.prev_span, msg)
6008+
.emit();
59366009
}
59376010
Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
59386011
} else {
@@ -6048,7 +6121,13 @@ impl<'a> Parser<'a> {
60486121
Some(ty_second) => {
60496122
// impl Trait for Type
60506123
if !has_for {
6051-
self.span_err(missing_for_span, "missing `for` in a trait impl");
6124+
self.struct_span_err(missing_for_span, "missing `for` in a trait impl")
6125+
.span_suggestion_short_with_applicability(
6126+
missing_for_span,
6127+
"add `for` here",
6128+
" for ".to_string(),
6129+
Applicability::MachineApplicable,
6130+
).emit();
60526131
}
60536132

60546133
let ty_first = ty_first.into_inner();
@@ -6939,7 +7018,7 @@ impl<'a> Parser<'a> {
69397018
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
69407019
let mut variants = Vec::new();
69417020
let mut all_nullary = true;
6942-
let mut any_disr = None;
7021+
let mut any_disr = vec![];
69437022
while self.token != token::CloseDelim(token::Brace) {
69447023
let variant_attrs = self.parse_outer_attributes()?;
69457024
let vlo = self.span;
@@ -6961,7 +7040,9 @@ impl<'a> Parser<'a> {
69617040
id: ast::DUMMY_NODE_ID,
69627041
value: self.parse_expr()?,
69637042
});
6964-
any_disr = disr_expr.as_ref().map(|c| c.value.span);
7043+
if let Some(sp) = disr_expr.as_ref().map(|c| c.value.span) {
7044+
any_disr.push(sp);
7045+
}
69657046
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
69667047
} else {
69677048
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
@@ -6978,11 +7059,15 @@ impl<'a> Parser<'a> {
69787059
if !self.eat(&token::Comma) { break; }
69797060
}
69807061
self.expect(&token::CloseDelim(token::Brace))?;
6981-
match any_disr {
6982-
Some(disr_span) if !all_nullary =>
6983-
self.span_err(disr_span,
6984-
"discriminator values can only be used with a field-less enum"),
6985-
_ => ()
7062+
if !any_disr.is_empty() && !all_nullary {
7063+
let mut err =self.struct_span_err(
7064+
any_disr.clone(),
7065+
"discriminator values can only be used with a field-less enum",
7066+
);
7067+
for sp in any_disr {
7068+
err.span_label(sp, "only valid in field-less enums");
7069+
}
7070+
err.emit();
69867071
}
69877072

69887073
Ok(ast::EnumDef { variants })

src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: trailing attribute after lifetime parameters
22
--> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25
33
|
44
LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
5-
| ^^^^^^^
5+
| ^^^^^^^ attributes must go before parameters
66

77
error: aborting due to previous error
88

src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: trailing attribute after type parameters
22
--> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35
33
|
44
LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
5-
| ^^^^^^^
5+
| ^^^^^^^ attributes must go before parameters
66

77
error: aborting due to previous error
88

src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,8 @@
55
struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
66

77
fn hof_lt<Q>(_: Q)
8-
where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
8+
where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
99
//~^ ERROR trailing attribute after lifetime parameters
10-
{
10+
{}
1111

12-
}
13-
14-
fn main() {
15-
16-
}
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: trailing attribute after lifetime parameters
2-
--> $DIR/attrs-with-no-formal-in-generics-3.rs:8:38
2+
--> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44
33
|
4-
LL | where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
5-
| ^^^^^^^
4+
LL | where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
5+
| ^^^^^^^ attributes must go before parameters
66

77
error: aborting due to previous error
88

src/test/ui/old-suffixes-are-really-forbidden.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ error: invalid suffix `is` for numeric literal
22
--> $DIR/old-suffixes-are-really-forbidden.rs:2:13
33
|
44
LL | let a = 1_is; //~ ERROR invalid suffix
5-
| ^^^^
5+
| ^^^^ invalid suffix `is`
66
|
77
= help: the suffix must be one of the integral types (`u32`, `isize`, etc)
88

99
error: invalid suffix `us` for numeric literal
1010
--> $DIR/old-suffixes-are-really-forbidden.rs:3:13
1111
|
1212
LL | let b = 2_us; //~ ERROR invalid suffix
13-
| ^^^^
13+
| ^^^^ invalid suffix `us`
1414
|
1515
= help: the suffix must be one of the integral types (`u32`, `isize`, etc)
1616

0 commit comments

Comments
 (0)