From 5c67ba615c299d47aef592f62f1c7540e824e87f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 19:31:45 -0800 Subject: [PATCH 01/15] Continue parser after trailing type argument attribute --- src/libsyntax/parse/parser.rs | 8 ++++++-- .../attrs-with-no-formal-in-generics-1.stderr | 2 +- .../attrs-with-no-formal-in-generics-2.stderr | 2 +- .../attrs-with-no-formal-in-generics-3.rs | 3 +-- .../attrs-with-no-formal-in-generics-3.stderr | 13 +++++++++++-- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1e4a26b353759..ae0296f839c76 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5255,8 +5255,12 @@ impl<'a> Parser<'a> { // Check for trailing attributes and stop parsing. if !attrs.is_empty() { let param_kind = if seen_ty_param.is_some() { "type" } else { "lifetime" }; - self.span_err(attrs[0].span, - &format!("trailing attribute after {} parameters", param_kind)); + self.struct_span_err( + attrs[0].span, + &format!("trailing attribute after {} parameters", param_kind), + ) + .span_label(attrs[0].span, "attributes must go before parameters") + .emit(); } break } diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr index 75c0d91ee1791..c4c0cee5ccc31 100644 --- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr +++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr @@ -2,7 +2,7 @@ error: trailing attribute after lifetime parameters --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25 | LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> { - | ^^^^^^^ + | ^^^^^^^ attributes must go before parameters error: aborting due to previous error diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr index 7585c6dd738a2..9099d74ce1be9 100644 --- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr +++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr @@ -2,7 +2,7 @@ error: trailing attribute after type parameters --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35 | LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {} - | ^^^^^^^ + | ^^^^^^^ attributes must go before parameters error: aborting due to previous error diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs index 343a2d7a563d1..84e242f322cb5 100644 --- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs +++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs @@ -7,10 +7,9 @@ struct RefIntPair<'a, 'b>(&'a u32, &'b u32); fn hof_lt(_: Q) where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 //~^ ERROR trailing attribute after lifetime parameters + //~| ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for { - } fn main() { - } diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr index 91960510de4db..a918a5a8d9989 100644 --- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr +++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr @@ -2,7 +2,16 @@ error: trailing attribute after lifetime parameters --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:38 | LL | where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 - | ^^^^^^^ + | ^^^^^^^ attributes must go before parameters -error: aborting due to previous error +error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) + --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:19 + | +LL | where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 + | ^^^^^^^^^^ + | + = help: add #![feature(rustc_attrs)] to the crate attributes to enable + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0658`. From fc4b54157fd1732e03689bca12b81f0a496c7913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 19:41:43 -0800 Subject: [PATCH 02/15] Continue parsing after lifetime in incorrect location --- src/libsyntax/parse/parser.rs | 8 +++-- src/test/ui/parser/issue-14303-fncall.rs | 2 ++ src/test/ui/parser/issue-14303-fncall.stderr | 17 +++++++++-- src/test/ui/parser/issue-14303-path.rs | 3 ++ src/test/ui/parser/issue-14303-path.stderr | 30 +++++++++++++++++-- .../ui/traits/trait-object-vs-lifetime.stderr | 2 +- 6 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ae0296f839c76..f5a4e2779aaca 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5329,8 +5329,12 @@ impl<'a> Parser<'a> { // Parse lifetime argument. args.push(GenericArg::Lifetime(self.expect_lifetime())); if seen_type || seen_binding { - self.span_err(self.prev_span, - "lifetime parameters must be declared prior to type parameters"); + self.struct_span_err( + self.prev_span, + "lifetime parameters must be declared prior to type parameters" + ) + .span_label(self.prev_span, "must be declared prior to type parameters") + .emit(); } } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) { // Parse associated type binding. diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issue-14303-fncall.rs index f5894349e1576..aa39fe52819d7 100644 --- a/src/test/ui/parser/issue-14303-fncall.rs +++ b/src/test/ui/parser/issue-14303-fncall.rs @@ -3,4 +3,6 @@ fn main() { .map(|x| x * 2) .collect::>() //~^ ERROR lifetime parameters must be declared prior to type parameters + //~| ERRROR use of undeclared lifetime name + //~| ERRROR use of undeclared lifetime name } diff --git a/src/test/ui/parser/issue-14303-fncall.stderr b/src/test/ui/parser/issue-14303-fncall.stderr index 1cc82f523c4ba..fa2deafb67396 100644 --- a/src/test/ui/parser/issue-14303-fncall.stderr +++ b/src/test/ui/parser/issue-14303-fncall.stderr @@ -2,7 +2,20 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-14303-fncall.rs:4:31 | LL | .collect::>() - | ^^ + | ^^ must be declared prior to type parameters -error: aborting due to previous error +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-14303-fncall.rs:4:20 + | +LL | .collect::>() + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/issue-14303-fncall.rs:4:31 + | +LL | .collect::>() + | ^^ undeclared lifetime + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issue-14303-path.rs index f61cb6b8dd6eb..67102249f63f1 100644 --- a/src/test/ui/parser/issue-14303-path.rs +++ b/src/test/ui/parser/issue-14303-path.rs @@ -1,4 +1,7 @@ fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} //~^ ERROR lifetime parameters must be declared prior to type parameters +//~| ERROR failed to resolve: use of undeclared type or module `mymodule` +//~| ERROR use of undeclared lifetime name `'b` +//~| ERROR use of undeclared lifetime name `'c` fn main() {} diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issue-14303-path.stderr index 3de8a169c6922..4c968fceb9d12 100644 --- a/src/test/ui/parser/issue-14303-path.stderr +++ b/src/test/ui/parser/issue-14303-path.stderr @@ -2,7 +2,33 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-14303-path.rs:1:37 | LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} - | ^^ + | ^^ must be declared prior to type parameters -error: aborting due to previous error +error: lifetime parameters must be declared prior to type parameters + --> $DIR/issue-14303-path.rs:1:41 + | +LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} + | ^^ must be declared prior to type parameters + +error[E0433]: failed to resolve: use of undeclared type or module `mymodule` + --> $DIR/issue-14303-path.rs:1:18 + | +LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} + | ^^^^^^^^ use of undeclared type or module `mymodule` + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/issue-14303-path.rs:1:37 + | +LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'c` + --> $DIR/issue-14303-path.rs:1:41 + | +LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} + | ^^ undeclared lifetime + +error: aborting due to 5 previous errors +Some errors occurred: E0261, E0433. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr index 20218c19e452b..00f8164caa429 100644 --- a/src/test/ui/traits/trait-object-vs-lifetime.stderr +++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr @@ -2,7 +2,7 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/trait-object-vs-lifetime.rs:16:25 | LL | let _: S<'static +, 'static>; - | ^^^^^^^ + | ^^^^^^^ must be declared prior to type parameters error[E0224]: at least one non-builtin trait is required for an object type --> $DIR/trait-object-vs-lifetime.rs:11:23 From d8610b31ecfba9bd9430d0acd97baa2bbc481100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 19:56:41 -0800 Subject: [PATCH 03/15] Continue evaluating after parsing incorrect binary literal --- src/libsyntax/parse/lexer/mod.rs | 2 +- src/test/ui/parser/issue-1802-1.rs | 5 ++++- src/test/ui/parser/issue-1802-1.stderr | 2 +- src/test/ui/parser/issue-1802-2.rs | 5 ++++- src/test/ui/parser/issue-1802-2.stderr | 11 +++++++++-- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index ecb34e43c590c..0e1c3b4b61f3a 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -299,7 +299,7 @@ impl<'a> StringReader<'a> { /// Report a lexical error with a given span. fn err_span(&self, sp: Span, m: &str) { - self.sess.span_diagnostic.span_err(sp, m) + self.sess.span_diagnostic.struct_span_err(sp, m).emit(); } diff --git a/src/test/ui/parser/issue-1802-1.rs b/src/test/ui/parser/issue-1802-1.rs index 050e9a258d1ed..3c34b0d8febbc 100644 --- a/src/test/ui/parser/issue-1802-1.rs +++ b/src/test/ui/parser/issue-1802-1.rs @@ -1,4 +1,7 @@ -// error-pattern:no valid digits found for number +fn log(a: i32, b: i32) {} + fn main() { + let error = 42; log(error, 0b); + //~^ ERROR no valid digits found for number } diff --git a/src/test/ui/parser/issue-1802-1.stderr b/src/test/ui/parser/issue-1802-1.stderr index 5cd6a4f7c6860..b7d003df56b71 100644 --- a/src/test/ui/parser/issue-1802-1.stderr +++ b/src/test/ui/parser/issue-1802-1.stderr @@ -1,5 +1,5 @@ error: no valid digits found for number - --> $DIR/issue-1802-1.rs:3:16 + --> $DIR/issue-1802-1.rs:5:16 | LL | log(error, 0b); | ^^ diff --git a/src/test/ui/parser/issue-1802-2.rs b/src/test/ui/parser/issue-1802-2.rs index 796db66d22e9a..c5fe7d506d937 100644 --- a/src/test/ui/parser/issue-1802-2.rs +++ b/src/test/ui/parser/issue-1802-2.rs @@ -1,4 +1,7 @@ -// error-pattern:no valid digits found for number +fn log(a: i32, b: i32) {} + fn main() { + let error = 42; log(error, 0b_usize); + //~^ ERROR no valid digits found for number } diff --git a/src/test/ui/parser/issue-1802-2.stderr b/src/test/ui/parser/issue-1802-2.stderr index c6c04279666a0..92fce75f8c37c 100644 --- a/src/test/ui/parser/issue-1802-2.stderr +++ b/src/test/ui/parser/issue-1802-2.stderr @@ -1,8 +1,15 @@ error: no valid digits found for number - --> $DIR/issue-1802-2.rs:3:16 + --> $DIR/issue-1802-2.rs:5:16 | LL | log(error, 0b_usize); | ^^^ -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-1802-2.rs:5:16 + | +LL | log(error, 0b_usize); + | ^^^^^^^^ expected i32, found usize + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. From 5d2f31cddc4003c5c291641355191090f505c49a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 20:05:31 -0800 Subject: [PATCH 04/15] Continue evaluating after missing `for` in `impl Trait for Foo` --- src/libsyntax/parse/parser.rs | 8 +++++++- src/test/ui/parser/impl-parsing.stderr | 4 ++-- src/test/ui/parser/issue-27255.rs | 9 ++++++++- src/test/ui/parser/issue-27255.stderr | 22 ++++++++++++++++++---- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f5a4e2779aaca..da910aefdc096 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6055,7 +6055,13 @@ impl<'a> Parser<'a> { Some(ty_second) => { // impl Trait for Type if !has_for { - self.span_err(missing_for_span, "missing `for` in a trait impl"); + self.struct_span_err(missing_for_span, "missing `for` in a trait impl") + .span_suggestion_short_with_applicability( + missing_for_span, + "add `for` here", + " for ".to_string(), + Applicability::MachineApplicable, + ).emit(); } let ty_first = ty_first.into_inner(); diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr index 308f14c60c765..353f5e21ee641 100644 --- a/src/test/ui/parser/impl-parsing.stderr +++ b/src/test/ui/parser/impl-parsing.stderr @@ -2,13 +2,13 @@ error: missing `for` in a trait impl --> $DIR/impl-parsing.rs:6:11 | LL | impl Trait Type {} //~ ERROR missing `for` in a trait impl - | ^ + | ^ help: add `for` here error: missing `for` in a trait impl --> $DIR/impl-parsing.rs:7:11 | LL | impl Trait .. {} //~ ERROR missing `for` in a trait impl - | ^ + | ^ help: add `for` here error: expected a trait, found type --> $DIR/impl-parsing.rs:8:6 diff --git a/src/test/ui/parser/issue-27255.rs b/src/test/ui/parser/issue-27255.rs index c0ff331b8bae0..d619688e10183 100644 --- a/src/test/ui/parser/issue-27255.rs +++ b/src/test/ui/parser/issue-27255.rs @@ -1,3 +1,10 @@ -impl A .. {} //~ ERROR +trait A {} + +impl A .. {} +//~^ ERROR missing `for` in a trait impl +//~| ERROR `impl Trait for .. {}` is an obsolete syntax + +impl A usize {} +//~^ ERROR missing `for` in a trait impl fn main() {} diff --git a/src/test/ui/parser/issue-27255.stderr b/src/test/ui/parser/issue-27255.stderr index 6d09d82e34f33..391a23556c4e0 100644 --- a/src/test/ui/parser/issue-27255.stderr +++ b/src/test/ui/parser/issue-27255.stderr @@ -1,8 +1,22 @@ error: missing `for` in a trait impl - --> $DIR/issue-27255.rs:1:7 + --> $DIR/issue-27255.rs:3:7 | -LL | impl A .. {} //~ ERROR - | ^ +LL | impl A .. {} + | ^ help: add `for` here -error: aborting due to previous error +error: missing `for` in a trait impl + --> $DIR/issue-27255.rs:7:7 + | +LL | impl A usize {} + | ^^^^^^ help: add `for` here + +error: `impl Trait for .. {}` is an obsolete syntax + --> $DIR/issue-27255.rs:3:1 + | +LL | impl A .. {} + | ^^^^^^^^^^^^ + | + = help: use `auto trait Trait {}` instead + +error: aborting due to 3 previous errors From 57f17e91d08b038a76e175bf2bbd36147d889eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 21:05:18 -0800 Subject: [PATCH 05/15] Continue evaluating after type argument in where clause --- src/libsyntax/parse/parser.rs | 8 ++++++-- src/test/ui/parser/where_with_bound.rs | 1 + src/test/ui/parser/where_with_bound.stderr | 11 +++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index da910aefdc096..ce9db4d04683f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5393,8 +5393,12 @@ impl<'a> Parser<'a> { // change we parse those generics now, but report an error. if self.choose_generics_over_qpath() { let generics = self.parse_generics()?; - self.span_err(generics.span, - "generic parameters on `where` clauses are reserved for future use"); + self.struct_span_err( + generics.span, + "generic parameters on `where` clauses are reserved for future use", + ) + .span_label(generics.span, "currently unsupported") + .emit(); } loop { diff --git a/src/test/ui/parser/where_with_bound.rs b/src/test/ui/parser/where_with_bound.rs index 3a1edb9ffc911..3ca45f1889c9c 100644 --- a/src/test/ui/parser/where_with_bound.rs +++ b/src/test/ui/parser/where_with_bound.rs @@ -1,4 +1,5 @@ fn foo() where ::Item: ToString, T: Iterator { } //~^ ERROR generic parameters on `where` clauses are reserved for future use +//~| ERROR cannot find type `Item` in the crate root fn main() {} diff --git a/src/test/ui/parser/where_with_bound.stderr b/src/test/ui/parser/where_with_bound.stderr index e68f744555809..ff98b3f5fed61 100644 --- a/src/test/ui/parser/where_with_bound.stderr +++ b/src/test/ui/parser/where_with_bound.stderr @@ -2,7 +2,14 @@ error: generic parameters on `where` clauses are reserved for future use --> $DIR/where_with_bound.rs:1:19 | LL | fn foo() where ::Item: ToString, T: Iterator { } - | ^^^ + | ^^^ currently unsupported -error: aborting due to previous error +error[E0412]: cannot find type `Item` in the crate root + --> $DIR/where_with_bound.rs:1:24 + | +LL | fn foo() where ::Item: ToString, T: Iterator { } + | ^^^^ not found in the crate root + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0412`. From 65a8d7b1d8e5acb494c0313829f173657fd0d5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 21:07:46 -0800 Subject: [PATCH 06/15] fix tests --- src/test/ui/parser/issue-14303-fncall.rs | 4 ++-- src/test/ui/parser/issue-14303-path.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issue-14303-fncall.rs index aa39fe52819d7..f08b847ac3288 100644 --- a/src/test/ui/parser/issue-14303-fncall.rs +++ b/src/test/ui/parser/issue-14303-fncall.rs @@ -3,6 +3,6 @@ fn main() { .map(|x| x * 2) .collect::>() //~^ ERROR lifetime parameters must be declared prior to type parameters - //~| ERRROR use of undeclared lifetime name - //~| ERRROR use of undeclared lifetime name + //~| ERROR use of undeclared lifetime name + //~| ERROR use of undeclared lifetime name } diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issue-14303-path.rs index 67102249f63f1..a407ed5fee9f1 100644 --- a/src/test/ui/parser/issue-14303-path.rs +++ b/src/test/ui/parser/issue-14303-path.rs @@ -1,5 +1,6 @@ fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} //~^ ERROR lifetime parameters must be declared prior to type parameters +//~| ERROR lifetime parameters must be declared prior to type parameters //~| ERROR failed to resolve: use of undeclared type or module `mymodule` //~| ERROR use of undeclared lifetime name `'b` //~| ERROR use of undeclared lifetime name `'c` From 8bede50f23d1b53cd34356a4d3b57bb775304b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 21:19:44 -0800 Subject: [PATCH 07/15] Continue evaluating after incorrect float literal --- src/libsyntax/parse/mod.rs | 6 ++++- .../ui/parser/lex-bad-numeric-literals.stderr | 6 ++--- src/test/ui/parser/no-binary-float-literal.rs | 5 ++-- .../ui/parser/no-binary-float-literal.stderr | 18 +++++++++++-- src/test/ui/parser/no-hex-float-literal.rs | 6 +++-- .../ui/parser/no-hex-float-literal.stderr | 25 +++++++++++++++++-- 6 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ba5676a65d7eb..48184f6d918b2 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -673,7 +673,11 @@ fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) _ => None, }; if let Some(err) = err { - err!(diag, |span, diag| diag.span_err(span, err)); + err!(diag, |span, diag| { + diag.struct_span_err(span, err) + .span_label(span, "not supported") + .emit(); + }); } return filtered_float_lit(Symbol::intern(s), Some(suf), diag) } diff --git a/src/test/ui/parser/lex-bad-numeric-literals.stderr b/src/test/ui/parser/lex-bad-numeric-literals.stderr index b1a91705533a0..1fa23b8b73c9e 100644 --- a/src/test/ui/parser/lex-bad-numeric-literals.stderr +++ b/src/test/ui/parser/lex-bad-numeric-literals.stderr @@ -110,7 +110,7 @@ error: octal float literal is not supported --> $DIR/lex-bad-numeric-literals.rs:5:5 | LL | 0o2f32; //~ ERROR: octal float literal is not supported - | ^^^^^^ + | ^^^^^^ not supported error: int literal is too large --> $DIR/lex-bad-numeric-literals.rs:16:5 @@ -128,13 +128,13 @@ error: octal float literal is not supported --> $DIR/lex-bad-numeric-literals.rs:23:5 | LL | 0o123f64; //~ ERROR: octal float literal is not supported - | ^^^^^^^^ + | ^^^^^^^^ not supported error: binary float literal is not supported --> $DIR/lex-bad-numeric-literals.rs:25:5 | LL | 0b101f64; //~ ERROR: binary float literal is not supported - | ^^^^^^^^ + | ^^^^^^^^ not supported error: aborting due to 23 previous errors diff --git a/src/test/ui/parser/no-binary-float-literal.rs b/src/test/ui/parser/no-binary-float-literal.rs index c078bf5f63ef9..a42d2cbc442f0 100644 --- a/src/test/ui/parser/no-binary-float-literal.rs +++ b/src/test/ui/parser/no-binary-float-literal.rs @@ -1,7 +1,8 @@ -// error-pattern:binary float literal is not supported - fn main() { 0b101010f64; + //~^ ERROR binary float literal is not supported 0b101.010; + //~^ ERROR binary float literal is not supported 0b101p4f64; + //~^ ERROR invalid suffix `p4f64` for numeric literal } diff --git a/src/test/ui/parser/no-binary-float-literal.stderr b/src/test/ui/parser/no-binary-float-literal.stderr index 7ff3e28ccb688..90f4171f88da5 100644 --- a/src/test/ui/parser/no-binary-float-literal.stderr +++ b/src/test/ui/parser/no-binary-float-literal.stderr @@ -1,8 +1,22 @@ error: binary float literal is not supported - --> $DIR/no-binary-float-literal.rs:5:5 + --> $DIR/no-binary-float-literal.rs:4:5 | LL | 0b101.010; | ^^^^^^^^^ -error: aborting due to previous error +error: binary float literal is not supported + --> $DIR/no-binary-float-literal.rs:2:5 + | +LL | 0b101010f64; + | ^^^^^^^^^^^ not supported + +error: invalid suffix `p4f64` for numeric literal + --> $DIR/no-binary-float-literal.rs:6:5 + | +LL | 0b101p4f64; + | ^^^^^^^^^^ + | + = help: the suffix must be one of the integral types (`u32`, `isize`, etc) + +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/no-hex-float-literal.rs b/src/test/ui/parser/no-hex-float-literal.rs index d830c96fc2f98..bf11dee08338e 100644 --- a/src/test/ui/parser/no-hex-float-literal.rs +++ b/src/test/ui/parser/no-hex-float-literal.rs @@ -1,7 +1,9 @@ -// error-pattern:hexadecimal float literal is not supported - fn main() { 0xABC.Df; + //~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields 0x567.89; + //~^ ERROR hexadecimal float literal is not supported 0xDEAD.BEEFp-2f; + //~^ ERROR invalid suffix `f` for float literal + //~| ERROR `{integer}` is a primitive type and therefore doesn't have fields } diff --git a/src/test/ui/parser/no-hex-float-literal.stderr b/src/test/ui/parser/no-hex-float-literal.stderr index 1668cfe5a33ed..11e911f5ecb60 100644 --- a/src/test/ui/parser/no-hex-float-literal.stderr +++ b/src/test/ui/parser/no-hex-float-literal.stderr @@ -1,8 +1,29 @@ error: hexadecimal float literal is not supported - --> $DIR/no-hex-float-literal.rs:5:5 + --> $DIR/no-hex-float-literal.rs:4:5 | LL | 0x567.89; | ^^^^^^^^ -error: aborting due to previous error +error: invalid suffix `f` for float literal + --> $DIR/no-hex-float-literal.rs:6:18 + | +LL | 0xDEAD.BEEFp-2f; + | ^^ + | + = help: valid suffixes are `f32` and `f64` + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/no-hex-float-literal.rs:2:11 + | +LL | 0xABC.Df; + | ^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/no-hex-float-literal.rs:6:12 + | +LL | 0xDEAD.BEEFp-2f; + | ^^^^^ + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0610`. From 975f8b5e32cfcd368a245169dd3d3cc536b0cc28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 21:21:30 -0800 Subject: [PATCH 08/15] fix test --- src/test/ui/parser/issue-1802-2.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/parser/issue-1802-2.rs b/src/test/ui/parser/issue-1802-2.rs index c5fe7d506d937..2fca41a83d4ca 100644 --- a/src/test/ui/parser/issue-1802-2.rs +++ b/src/test/ui/parser/issue-1802-2.rs @@ -4,4 +4,5 @@ fn main() { let error = 42; log(error, 0b_usize); //~^ ERROR no valid digits found for number + //~| ERROR mismatched types } From 8119017746959f7ecb3ba93c6c32a7d6d9dafc40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 21:33:57 -0800 Subject: [PATCH 09/15] Continue evaluating after finding incorrect .. in pattern --- src/libsyntax/parse/parser.rs | 13 ++++++++++--- src/test/ui/parser/pat-tuple-2.rs | 4 +++- src/test/ui/parser/pat-tuple-2.stderr | 16 +++++++++++++--- src/test/ui/parser/pat-tuple-3.rs | 4 +++- src/test/ui/parser/pat-tuple-3.stderr | 16 +++++++++++++--- 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ce9db4d04683f..6228598ab61da 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3814,8 +3814,12 @@ impl<'a> Parser<'a> { ddpos = Some(fields.len()); } else { // Emit a friendly error, ignore `..` and continue parsing - self.span_err(self.prev_span, - "`..` can only be used once per tuple or tuple struct pattern"); + self.struct_span_err( + self.prev_span, + "`..` can only be used once per tuple or tuple struct pattern", + ) + .span_label(self.prev_span, "can only be used once per pattern") + .emit(); } } else if !self.check(&token::CloseDelim(token::Paren)) { fields.push(self.parse_pat(None)?); @@ -3831,7 +3835,10 @@ impl<'a> Parser<'a> { if ddpos == Some(fields.len()) && trailing_comma { // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed. - self.span_err(self.prev_span, "trailing comma is not permitted after `..`"); + let msg = "trailing comma is not permitted after `..`"; + self.struct_span_err(self.prev_span, msg) + .span_label(self.prev_span, msg) + .emit(); } Ok((fields, ddpos, trailing_comma)) diff --git a/src/test/ui/parser/pat-tuple-2.rs b/src/test/ui/parser/pat-tuple-2.rs index 108278fa58e94..574cb6045dc9a 100644 --- a/src/test/ui/parser/pat-tuple-2.rs +++ b/src/test/ui/parser/pat-tuple-2.rs @@ -1,5 +1,7 @@ fn main() { match 0 { - (pat, ..,) => {} //~ ERROR trailing comma is not permitted after `..` + (pat, ..,) => {} + //~^ ERROR trailing comma is not permitted after `..` + //~| ERROR mismatched types } } diff --git a/src/test/ui/parser/pat-tuple-2.stderr b/src/test/ui/parser/pat-tuple-2.stderr index ec12336356619..178be83d9bf73 100644 --- a/src/test/ui/parser/pat-tuple-2.stderr +++ b/src/test/ui/parser/pat-tuple-2.stderr @@ -1,8 +1,18 @@ error: trailing comma is not permitted after `..` --> $DIR/pat-tuple-2.rs:3:17 | -LL | (pat, ..,) => {} //~ ERROR trailing comma is not permitted after `..` - | ^ +LL | (pat, ..,) => {} + | ^ trailing comma is not permitted after `..` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/pat-tuple-2.rs:3:9 + | +LL | (pat, ..,) => {} + | ^^^^^^^^^^ expected integer, found tuple + | + = note: expected type `{integer}` + found type `(_,)` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-tuple-3.rs b/src/test/ui/parser/pat-tuple-3.rs index 63dcde45bfb5e..33edb0007e7c1 100644 --- a/src/test/ui/parser/pat-tuple-3.rs +++ b/src/test/ui/parser/pat-tuple-3.rs @@ -1,5 +1,7 @@ fn main() { match 0 { - (.., pat, ..) => {} //~ ERROR `..` can only be used once per tuple or tuple struct pattern + (.., pat, ..) => {} + //~^ ERROR `..` can only be used once per tuple or tuple struct pattern + //~| ERROR mismatched types } } diff --git a/src/test/ui/parser/pat-tuple-3.stderr b/src/test/ui/parser/pat-tuple-3.stderr index 90940eb1723b8..fcb657393b8f2 100644 --- a/src/test/ui/parser/pat-tuple-3.stderr +++ b/src/test/ui/parser/pat-tuple-3.stderr @@ -1,8 +1,18 @@ error: `..` can only be used once per tuple or tuple struct pattern --> $DIR/pat-tuple-3.rs:3:19 | -LL | (.., pat, ..) => {} //~ ERROR `..` can only be used once per tuple or tuple struct pattern - | ^^ +LL | (.., pat, ..) => {} + | ^^ can only be used once per pattern -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/pat-tuple-3.rs:3:9 + | +LL | (.., pat, ..) => {} + | ^^^^^^^^^^^^^ expected integer, found tuple + | + = note: expected type `{integer}` + found type `(_,)` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. From de3c4be099993517dba7bb764628ff28e86f9320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 21:45:24 -0800 Subject: [PATCH 10/15] Tweak type argument after assoc type error --- src/libsyntax/parse/parser.rs | 11 +++++++++-- src/test/ui/parser/issue-32214.stderr | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6228598ab61da..a5ef403888502 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5360,8 +5360,15 @@ impl<'a> Parser<'a> { // Parse type argument. let ty_param = self.parse_ty()?; if seen_binding { - self.span_err(ty_param.span, - "type parameters must be declared prior to associated type bindings"); + self.struct_span_err( + ty_param.span, + "type parameters must be declared prior to associated type bindings" + ) + .span_label( + ty_param.span, + "must be declared prior to associated type bindings", + ) + .emit(); } args.push(GenericArg::Type(ty_param)); seen_type = true; diff --git a/src/test/ui/parser/issue-32214.stderr b/src/test/ui/parser/issue-32214.stderr index a01517d016d07..a889513eaee52 100644 --- a/src/test/ui/parser/issue-32214.stderr +++ b/src/test/ui/parser/issue-32214.stderr @@ -2,7 +2,7 @@ error: type parameters must be declared prior to associated type bindings --> $DIR/issue-32214.rs:5:34 | LL | pub fn test >() {} - | ^ + | ^ must be declared prior to associated type bindings error: aborting due to previous error From 7feb802d8982fe69d7d6acef532a87ada8aae9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 22:04:54 -0800 Subject: [PATCH 11/15] Small tweaks to parser errors --- src/libsyntax/parse/parser.rs | 27 ++++++++++++++++------ src/test/ui/parser/bad-lit-suffixes.stderr | 16 ++++++------- src/test/ui/parser/bad-pointer-type.rs | 2 +- src/test/ui/parser/bad-pointer-type.stderr | 6 +++-- src/test/ui/parser/no-unsafe-self.stderr | 12 +++++----- 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a5ef403888502..ee93696c602dc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1012,7 +1012,10 @@ impl<'a> Parser<'a> { if text.is_empty() { self.span_bug(sp, "found empty literal suffix in Some") } - self.span_err(sp, &format!("{} with a suffix is invalid", kind)); + let msg = format!("{} with a suffix is invalid", kind); + self.struct_span_err(sp, &msg) + .span_label(sp, msg) + .emit(); } } } @@ -1768,9 +1771,11 @@ impl<'a> Parser<'a> { Mutability::Immutable } else { let span = self.prev_span; - self.span_err(span, - "expected mut or const in raw pointer type (use \ - `*mut T` or `*const T` as appropriate)"); + let msg = "expected mut or const in raw pointer type"; + self.struct_span_err(span, msg) + .span_label(span, msg) + .help("use `*mut T` or `*const T` as appropriate") + .emit(); Mutability::Immutable }; let t = self.parse_ty_no_plus()?; @@ -5612,15 +5617,20 @@ impl<'a> Parser<'a> { // *mut self // *not_self // Emit special error for `self` cases. + let msg = "cannot pass `self` by raw pointer"; (if isolated_self(self, 1) { self.bump(); - self.span_err(self.span, "cannot pass `self` by raw pointer"); + self.struct_span_err(self.span, msg) + .span_label(self.span, msg) + .emit(); SelfKind::Value(Mutability::Immutable) } else if self.look_ahead(1, |t| t.is_mutability()) && isolated_self(self, 2) { self.bump(); self.bump(); - self.span_err(self.span, "cannot pass `self` by raw pointer"); + self.struct_span_err(self.span, msg) + .span_label(self.span, msg) + .emit(); SelfKind::Value(Mutability::Immutable) } else { return Ok(None); @@ -5957,7 +5967,10 @@ impl<'a> Parser<'a> { tps.where_clause = self.parse_where_clause()?; self.expect(&token::Semi)?; if unsafety != Unsafety::Normal { - self.span_err(self.prev_span, "trait aliases cannot be unsafe"); + let msg = "trait aliases cannot be unsafe"; + self.struct_span_err(self.prev_span, msg) + .span_label(self.prev_span, msg) + .emit(); } Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) } else { diff --git a/src/test/ui/parser/bad-lit-suffixes.stderr b/src/test/ui/parser/bad-lit-suffixes.stderr index 4fd2ab8177bd4..0dc291ebda01a 100644 --- a/src/test/ui/parser/bad-lit-suffixes.stderr +++ b/src/test/ui/parser/bad-lit-suffixes.stderr @@ -2,49 +2,49 @@ error: ABI spec with a suffix is invalid --> $DIR/bad-lit-suffixes.rs:5:5 | LL | "C"suffix //~ ERROR ABI spec with a suffix is invalid - | ^^^^^^^^^ + | ^^^^^^^^^ ABI spec with a suffix is invalid error: ABI spec with a suffix is invalid --> $DIR/bad-lit-suffixes.rs:9:5 | LL | "C"suffix //~ ERROR ABI spec with a suffix is invalid - | ^^^^^^^^^ + | ^^^^^^^^^ ABI spec with a suffix is invalid error: string literal with a suffix is invalid --> $DIR/bad-lit-suffixes.rs:13:5 | LL | ""suffix; //~ ERROR string literal with a suffix is invalid - | ^^^^^^^^ + | ^^^^^^^^ string literal with a suffix is invalid error: byte string literal with a suffix is invalid --> $DIR/bad-lit-suffixes.rs:14:5 | LL | b""suffix; //~ ERROR byte string literal with a suffix is invalid - | ^^^^^^^^^ + | ^^^^^^^^^ byte string literal with a suffix is invalid error: string literal with a suffix is invalid --> $DIR/bad-lit-suffixes.rs:15:5 | LL | r#""#suffix; //~ ERROR string literal with a suffix is invalid - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ string literal with a suffix is invalid error: byte string literal with a suffix is invalid --> $DIR/bad-lit-suffixes.rs:16:5 | LL | br#""#suffix; //~ ERROR byte string literal with a suffix is invalid - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ byte string literal with a suffix is invalid error: char literal with a suffix is invalid --> $DIR/bad-lit-suffixes.rs:17:5 | LL | 'a'suffix; //~ ERROR char literal with a suffix is invalid - | ^^^^^^^^^ + | ^^^^^^^^^ char literal with a suffix is invalid error: byte literal with a suffix is invalid --> $DIR/bad-lit-suffixes.rs:18:5 | LL | b'a'suffix; //~ ERROR byte literal with a suffix is invalid - | ^^^^^^^^^^ + | ^^^^^^^^^^ byte literal with a suffix is invalid error: invalid width `1024` for integer literal --> $DIR/bad-lit-suffixes.rs:20:5 diff --git a/src/test/ui/parser/bad-pointer-type.rs b/src/test/ui/parser/bad-pointer-type.rs index 0e5a01103dc5f..59e5e0c5d31db 100644 --- a/src/test/ui/parser/bad-pointer-type.rs +++ b/src/test/ui/parser/bad-pointer-type.rs @@ -1,5 +1,5 @@ fn foo(_: *()) { - //~^ expected mut or const in raw pointer type (use `*mut T` or `*const T` as appropriate) + //~^ ERROR expected mut or const in raw pointer type } fn main() {} diff --git a/src/test/ui/parser/bad-pointer-type.stderr b/src/test/ui/parser/bad-pointer-type.stderr index 860f9f96bb8f5..e18c220affe6e 100644 --- a/src/test/ui/parser/bad-pointer-type.stderr +++ b/src/test/ui/parser/bad-pointer-type.stderr @@ -1,8 +1,10 @@ -error: expected mut or const in raw pointer type (use `*mut T` or `*const T` as appropriate) +error: expected mut or const in raw pointer type --> $DIR/bad-pointer-type.rs:1:11 | LL | fn foo(_: *()) { - | ^ + | ^ expected mut or const in raw pointer type + | + = help: use `*mut T` or `*const T` as appropriate error: aborting due to previous error diff --git a/src/test/ui/parser/no-unsafe-self.stderr b/src/test/ui/parser/no-unsafe-self.stderr index 364c22a962226..84779b09dc7c6 100644 --- a/src/test/ui/parser/no-unsafe-self.stderr +++ b/src/test/ui/parser/no-unsafe-self.stderr @@ -2,37 +2,37 @@ error: cannot pass `self` by raw pointer --> $DIR/no-unsafe-self.rs:4:17 | LL | fn foo(*mut self); //~ ERROR cannot pass `self` by raw pointer - | ^^^^ + | ^^^^ cannot pass `self` by raw pointer error: cannot pass `self` by raw pointer --> $DIR/no-unsafe-self.rs:5:19 | LL | fn baz(*const self); //~ ERROR cannot pass `self` by raw pointer - | ^^^^ + | ^^^^ cannot pass `self` by raw pointer error: cannot pass `self` by raw pointer --> $DIR/no-unsafe-self.rs:6:13 | LL | fn bar(*self); //~ ERROR cannot pass `self` by raw pointer - | ^^^^ + | ^^^^ cannot pass `self` by raw pointer error: cannot pass `self` by raw pointer --> $DIR/no-unsafe-self.rs:11:17 | LL | fn foo(*mut self) { } //~ ERROR cannot pass `self` by raw pointer - | ^^^^ + | ^^^^ cannot pass `self` by raw pointer error: cannot pass `self` by raw pointer --> $DIR/no-unsafe-self.rs:12:19 | LL | fn baz(*const self) { } //~ ERROR cannot pass `self` by raw pointer - | ^^^^ + | ^^^^ cannot pass `self` by raw pointer error: cannot pass `self` by raw pointer --> $DIR/no-unsafe-self.rs:13:13 | LL | fn bar(*self) { } //~ ERROR cannot pass `self` by raw pointer - | ^^^^ + | ^^^^ cannot pass `self` by raw pointer error: aborting due to 6 previous errors From 3ead6de40d57ec78275ee398592baa814b5f0841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 23:12:29 -0800 Subject: [PATCH 12/15] Tweak incorrect discriminator value variant error --- src/libsyntax/parse/parser.rs | 20 ++++++++----- src/test/ui/parser/issue-17383.rs | 7 ++--- src/test/ui/parser/issue-17383.stderr | 6 ++-- .../ui/parser/tag-variant-disr-non-nullary.rs | 18 ++++++------ .../tag-variant-disr-non-nullary.stderr | 28 ++++++++++++++++--- 5 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ee93696c602dc..3f736c361115a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6983,7 +6983,7 @@ impl<'a> Parser<'a> { fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> { let mut variants = Vec::new(); let mut all_nullary = true; - let mut any_disr = None; + let mut any_disr = vec![]; while self.token != token::CloseDelim(token::Brace) { let variant_attrs = self.parse_outer_attributes()?; let vlo = self.span; @@ -7005,7 +7005,9 @@ impl<'a> Parser<'a> { id: ast::DUMMY_NODE_ID, value: self.parse_expr()?, }); - any_disr = disr_expr.as_ref().map(|c| c.value.span); + if let Some(sp) = disr_expr.as_ref().map(|c| c.value.span) { + any_disr.push(sp); + } struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); } else { struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); @@ -7022,11 +7024,15 @@ impl<'a> Parser<'a> { if !self.eat(&token::Comma) { break; } } self.expect(&token::CloseDelim(token::Brace))?; - match any_disr { - Some(disr_span) if !all_nullary => - self.span_err(disr_span, - "discriminator values can only be used with a field-less enum"), - _ => () + if !any_disr.is_empty() && !all_nullary { + let mut err =self.struct_span_err( + any_disr.clone(), + "discriminator values can only be used with a field-less enum", + ); + for sp in any_disr { + err.span_label(sp, "only valid in field-less enums"); + } + err.emit(); } Ok(ast::EnumDef { variants }) diff --git a/src/test/ui/parser/issue-17383.rs b/src/test/ui/parser/issue-17383.rs index 9c00289287cde..04cd43d0b1071 100644 --- a/src/test/ui/parser/issue-17383.rs +++ b/src/test/ui/parser/issue-17383.rs @@ -1,8 +1,7 @@ enum X { - A = - b'a' //~ ERROR discriminator values can only be used with a field-less enum - , - B(isize) + A = 3, + //~^ ERROR discriminator values can only be used with a field-less enum + B(usize) } fn main() {} diff --git a/src/test/ui/parser/issue-17383.stderr b/src/test/ui/parser/issue-17383.stderr index b225e11066dbc..57caa3372a629 100644 --- a/src/test/ui/parser/issue-17383.stderr +++ b/src/test/ui/parser/issue-17383.stderr @@ -1,8 +1,8 @@ error: discriminator values can only be used with a field-less enum - --> $DIR/issue-17383.rs:3:9 + --> $DIR/issue-17383.rs:2:9 | -LL | b'a' //~ ERROR discriminator values can only be used with a field-less enum - | ^^^^ +LL | A = 3, + | ^ only valid in field-less enums error: aborting due to previous error diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs index 35a36cbbf91c6..8f5453d06f37f 100644 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.rs +++ b/src/test/ui/parser/tag-variant-disr-non-nullary.rs @@ -1,12 +1,14 @@ -//error-pattern: discriminator values can only be used with a field-less enum -enum color { - red = 0xff0000, - green = 0x00ff00, - blue = 0x0000ff, - black = 0x000000, - white = 0xffffff, - other (str), +enum Color { + Red = 0xff0000, + //~^ ERROR discriminator values can only be used with a field-less enum + Green = 0x00ff00, + Blue = 0x0000ff, + Black = 0x000000, + White = 0xffffff, + Other (str), + //~^ ERROR the size for values of type + // the above is kept in order to verify that we get beyond parse errors } fn main() {} diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr index aa45ea4ac26e9..7088352f8033a 100644 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr +++ b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr @@ -1,8 +1,28 @@ error: discriminator values can only be used with a field-less enum - --> $DIR/tag-variant-disr-non-nullary.rs:8:13 + --> $DIR/tag-variant-disr-non-nullary.rs:3:11 | -LL | white = 0xffffff, - | ^^^^^^^^ +LL | Red = 0xff0000, + | ^^^^^^^^ only valid in field-less enums +LL | //~^ ERROR discriminator values can only be used with a field-less enum +LL | Green = 0x00ff00, + | ^^^^^^^^ only valid in field-less enums +LL | Blue = 0x0000ff, + | ^^^^^^^^ only valid in field-less enums +LL | Black = 0x000000, + | ^^^^^^^^ only valid in field-less enums +LL | White = 0xffffff, + | ^^^^^^^^ only valid in field-less enums -error: aborting due to previous error +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/tag-variant-disr-non-nullary.rs:9:12 + | +LL | Other (str), + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `str` + = note: to learn more, visit + = note: no field of an enum variant may have a dynamically sized type + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. From 1550787b13d3e863f06da7c0c9e17ec1dee341df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 11 Jan 2019 23:37:49 -0800 Subject: [PATCH 13/15] Add label for invalid literal suffix --- src/libsyntax/parse/mod.rs | 2 ++ src/test/ui/old-suffixes-are-really-forbidden.stderr | 4 ++-- src/test/ui/parser/bad-lit-suffixes.stderr | 8 ++++---- src/test/ui/parser/no-binary-float-literal.stderr | 2 +- src/test/ui/parser/no-hex-float-literal.stderr | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 48184f6d918b2..ea205530ca5cc 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -520,6 +520,7 @@ fn filtered_float_lit(data: Symbol, suffix: Option, diag: Option<(Span, } else { let msg = format!("invalid suffix `{}` for float literal", suf); diag.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) .help("valid suffixes are `f32` and `f64`") .emit(); } @@ -716,6 +717,7 @@ fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) } else { let msg = format!("invalid suffix `{}` for numeric literal", suf); diag.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) .help("the suffix must be one of the integral types \ (`u32`, `isize`, etc)") .emit(); diff --git a/src/test/ui/old-suffixes-are-really-forbidden.stderr b/src/test/ui/old-suffixes-are-really-forbidden.stderr index 557e7ef6794cd..c54b72a3585d1 100644 --- a/src/test/ui/old-suffixes-are-really-forbidden.stderr +++ b/src/test/ui/old-suffixes-are-really-forbidden.stderr @@ -2,7 +2,7 @@ error: invalid suffix `is` for numeric literal --> $DIR/old-suffixes-are-really-forbidden.rs:2:13 | LL | let a = 1_is; //~ ERROR invalid suffix - | ^^^^ + | ^^^^ invalid suffix `is` | = help: the suffix must be one of the integral types (`u32`, `isize`, etc) @@ -10,7 +10,7 @@ error: invalid suffix `us` for numeric literal --> $DIR/old-suffixes-are-really-forbidden.rs:3:13 | LL | let b = 2_us; //~ ERROR invalid suffix - | ^^^^ + | ^^^^ invalid suffix `us` | = help: the suffix must be one of the integral types (`u32`, `isize`, etc) diff --git a/src/test/ui/parser/bad-lit-suffixes.stderr b/src/test/ui/parser/bad-lit-suffixes.stderr index 0dc291ebda01a..608c5fda2482a 100644 --- a/src/test/ui/parser/bad-lit-suffixes.stderr +++ b/src/test/ui/parser/bad-lit-suffixes.stderr @@ -82,7 +82,7 @@ error: invalid suffix `suffix` for numeric literal --> $DIR/bad-lit-suffixes.rs:25:5 | LL | 1234suffix; //~ ERROR invalid suffix `suffix` for numeric literal - | ^^^^^^^^^^ + | ^^^^^^^^^^ invalid suffix `suffix` | = help: the suffix must be one of the integral types (`u32`, `isize`, etc) @@ -90,7 +90,7 @@ error: invalid suffix `suffix` for numeric literal --> $DIR/bad-lit-suffixes.rs:26:5 | LL | 0b101suffix; //~ ERROR invalid suffix `suffix` for numeric literal - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ invalid suffix `suffix` | = help: the suffix must be one of the integral types (`u32`, `isize`, etc) @@ -98,7 +98,7 @@ error: invalid suffix `suffix` for float literal --> $DIR/bad-lit-suffixes.rs:27:5 | LL | 1.0suffix; //~ ERROR invalid suffix `suffix` for float literal - | ^^^^^^^^^ + | ^^^^^^^^^ invalid suffix `suffix` | = help: valid suffixes are `f32` and `f64` @@ -106,7 +106,7 @@ error: invalid suffix `suffix` for float literal --> $DIR/bad-lit-suffixes.rs:28:5 | LL | 1.0e10suffix; //~ ERROR invalid suffix `suffix` for float literal - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ invalid suffix `suffix` | = help: valid suffixes are `f32` and `f64` diff --git a/src/test/ui/parser/no-binary-float-literal.stderr b/src/test/ui/parser/no-binary-float-literal.stderr index 90f4171f88da5..21f415bcfb000 100644 --- a/src/test/ui/parser/no-binary-float-literal.stderr +++ b/src/test/ui/parser/no-binary-float-literal.stderr @@ -14,7 +14,7 @@ error: invalid suffix `p4f64` for numeric literal --> $DIR/no-binary-float-literal.rs:6:5 | LL | 0b101p4f64; - | ^^^^^^^^^^ + | ^^^^^^^^^^ invalid suffix `p4f64` | = help: the suffix must be one of the integral types (`u32`, `isize`, etc) diff --git a/src/test/ui/parser/no-hex-float-literal.stderr b/src/test/ui/parser/no-hex-float-literal.stderr index 11e911f5ecb60..258ab06d5ee2f 100644 --- a/src/test/ui/parser/no-hex-float-literal.stderr +++ b/src/test/ui/parser/no-hex-float-literal.stderr @@ -8,7 +8,7 @@ error: invalid suffix `f` for float literal --> $DIR/no-hex-float-literal.rs:6:18 | LL | 0xDEAD.BEEFp-2f; - | ^^ + | ^^ invalid suffix `f` | = help: valid suffixes are `f32` and `f64` From db740313e023c76a2b354981e352ebcf6d7d57e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 12 Jan 2019 17:12:41 -0800 Subject: [PATCH 14/15] Remove unrelated errors from parse stderr tests --- .../attrs-with-no-formal-in-generics-3.rs | 9 ++--- .../attrs-with-no-formal-in-generics-3.stderr | 17 +++------- src/test/ui/parser/issue-14303-path.rs | 14 +++++--- src/test/ui/parser/issue-14303-path.stderr | 34 ++++--------------- src/test/ui/parser/issue-1802-2.rs | 3 +- src/test/ui/parser/issue-1802-2.stderr | 13 ++----- src/test/ui/parser/pat-tuple-2.rs | 3 +- src/test/ui/parser/pat-tuple-2.stderr | 12 +------ src/test/ui/parser/pat-tuple-3.rs | 3 +- src/test/ui/parser/pat-tuple-3.stderr | 12 +------ .../ui/parser/tag-variant-disr-non-nullary.rs | 5 +-- .../tag-variant-disr-non-nullary.stderr | 15 ++------ 12 files changed, 35 insertions(+), 105 deletions(-) diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs index 84e242f322cb5..e9f908d479f64 100644 --- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs +++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs @@ -5,11 +5,8 @@ struct RefIntPair<'a, 'b>(&'a u32, &'b u32); fn hof_lt(_: Q) - where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 + where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 //~^ ERROR trailing attribute after lifetime parameters - //~| ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for -{ -} +{} -fn main() { -} +fn main() {} diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr index a918a5a8d9989..452f0ea5e1753 100644 --- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr +++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr @@ -1,17 +1,8 @@ error: trailing attribute after lifetime parameters - --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:38 + --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44 | -LL | where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 - | ^^^^^^^ attributes must go before parameters +LL | where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 + | ^^^^^^^ attributes must go before parameters -error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) - --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:19 - | -LL | where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 - | ^^^^^^^^^^ - | - = help: add #![feature(rustc_attrs)] to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issue-14303-path.rs index a407ed5fee9f1..8749d46818f69 100644 --- a/src/test/ui/parser/issue-14303-path.rs +++ b/src/test/ui/parser/issue-14303-path.rs @@ -1,8 +1,14 @@ -fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} +mod foo { + pub struct X<'a, 'b, 'c, T> { + a: &'a str, + b: &'b str, + c: &'c str, + t: T, + } +} + +fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} //~^ ERROR lifetime parameters must be declared prior to type parameters //~| ERROR lifetime parameters must be declared prior to type parameters -//~| ERROR failed to resolve: use of undeclared type or module `mymodule` -//~| ERROR use of undeclared lifetime name `'b` -//~| ERROR use of undeclared lifetime name `'c` fn main() {} diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issue-14303-path.stderr index 4c968fceb9d12..07e4441b0de3a 100644 --- a/src/test/ui/parser/issue-14303-path.stderr +++ b/src/test/ui/parser/issue-14303-path.stderr @@ -1,34 +1,14 @@ error: lifetime parameters must be declared prior to type parameters - --> $DIR/issue-14303-path.rs:1:37 + --> $DIR/issue-14303-path.rs:10:40 | -LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} - | ^^ must be declared prior to type parameters +LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} + | ^^ must be declared prior to type parameters error: lifetime parameters must be declared prior to type parameters - --> $DIR/issue-14303-path.rs:1:41 + --> $DIR/issue-14303-path.rs:10:44 | -LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} - | ^^ must be declared prior to type parameters +LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} + | ^^ must be declared prior to type parameters -error[E0433]: failed to resolve: use of undeclared type or module `mymodule` - --> $DIR/issue-14303-path.rs:1:18 - | -LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} - | ^^^^^^^^ use of undeclared type or module `mymodule` - -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/issue-14303-path.rs:1:37 - | -LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} - | ^^ undeclared lifetime - -error[E0261]: use of undeclared lifetime name `'c` - --> $DIR/issue-14303-path.rs:1:41 - | -LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} - | ^^ undeclared lifetime - -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors occurred: E0261, E0433. -For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/parser/issue-1802-2.rs b/src/test/ui/parser/issue-1802-2.rs index 2fca41a83d4ca..3c34b0d8febbc 100644 --- a/src/test/ui/parser/issue-1802-2.rs +++ b/src/test/ui/parser/issue-1802-2.rs @@ -2,7 +2,6 @@ fn log(a: i32, b: i32) {} fn main() { let error = 42; - log(error, 0b_usize); + log(error, 0b); //~^ ERROR no valid digits found for number - //~| ERROR mismatched types } diff --git a/src/test/ui/parser/issue-1802-2.stderr b/src/test/ui/parser/issue-1802-2.stderr index 92fce75f8c37c..8491dd07cb788 100644 --- a/src/test/ui/parser/issue-1802-2.stderr +++ b/src/test/ui/parser/issue-1802-2.stderr @@ -1,15 +1,8 @@ error: no valid digits found for number --> $DIR/issue-1802-2.rs:5:16 | -LL | log(error, 0b_usize); - | ^^^ +LL | log(error, 0b); + | ^^ -error[E0308]: mismatched types - --> $DIR/issue-1802-2.rs:5:16 - | -LL | log(error, 0b_usize); - | ^^^^^^^^ expected i32, found usize - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-tuple-2.rs b/src/test/ui/parser/pat-tuple-2.rs index 574cb6045dc9a..fd25499381a28 100644 --- a/src/test/ui/parser/pat-tuple-2.rs +++ b/src/test/ui/parser/pat-tuple-2.rs @@ -1,7 +1,6 @@ fn main() { - match 0 { + match (0, 1, 2) { (pat, ..,) => {} //~^ ERROR trailing comma is not permitted after `..` - //~| ERROR mismatched types } } diff --git a/src/test/ui/parser/pat-tuple-2.stderr b/src/test/ui/parser/pat-tuple-2.stderr index 178be83d9bf73..c3a5c39a8e32a 100644 --- a/src/test/ui/parser/pat-tuple-2.stderr +++ b/src/test/ui/parser/pat-tuple-2.stderr @@ -4,15 +4,5 @@ error: trailing comma is not permitted after `..` LL | (pat, ..,) => {} | ^ trailing comma is not permitted after `..` -error[E0308]: mismatched types - --> $DIR/pat-tuple-2.rs:3:9 - | -LL | (pat, ..,) => {} - | ^^^^^^^^^^ expected integer, found tuple - | - = note: expected type `{integer}` - found type `(_,)` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-tuple-3.rs b/src/test/ui/parser/pat-tuple-3.rs index 33edb0007e7c1..e1e975d3c3ea0 100644 --- a/src/test/ui/parser/pat-tuple-3.rs +++ b/src/test/ui/parser/pat-tuple-3.rs @@ -1,7 +1,6 @@ fn main() { - match 0 { + match (0, 1, 2) { (.., pat, ..) => {} //~^ ERROR `..` can only be used once per tuple or tuple struct pattern - //~| ERROR mismatched types } } diff --git a/src/test/ui/parser/pat-tuple-3.stderr b/src/test/ui/parser/pat-tuple-3.stderr index fcb657393b8f2..0ad7d27b94e54 100644 --- a/src/test/ui/parser/pat-tuple-3.stderr +++ b/src/test/ui/parser/pat-tuple-3.stderr @@ -4,15 +4,5 @@ error: `..` can only be used once per tuple or tuple struct pattern LL | (.., pat, ..) => {} | ^^ can only be used once per pattern -error[E0308]: mismatched types - --> $DIR/pat-tuple-3.rs:3:9 - | -LL | (.., pat, ..) => {} - | ^^^^^^^^^^^^^ expected integer, found tuple - | - = note: expected type `{integer}` - found type `(_,)` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs index 8f5453d06f37f..83a3b727982b5 100644 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.rs +++ b/src/test/ui/parser/tag-variant-disr-non-nullary.rs @@ -1,4 +1,3 @@ - enum Color { Red = 0xff0000, //~^ ERROR discriminator values can only be used with a field-less enum @@ -6,9 +5,7 @@ enum Color { Blue = 0x0000ff, Black = 0x000000, White = 0xffffff, - Other (str), - //~^ ERROR the size for values of type - // the above is kept in order to verify that we get beyond parse errors + Other(usize), } fn main() {} diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr index 7088352f8033a..cc6312b454551 100644 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr +++ b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr @@ -1,5 +1,5 @@ error: discriminator values can only be used with a field-less enum - --> $DIR/tag-variant-disr-non-nullary.rs:3:11 + --> $DIR/tag-variant-disr-non-nullary.rs:2:11 | LL | Red = 0xff0000, | ^^^^^^^^ only valid in field-less enums @@ -13,16 +13,5 @@ LL | Black = 0x000000, LL | White = 0xffffff, | ^^^^^^^^ only valid in field-less enums -error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/tag-variant-disr-non-nullary.rs:9:12 - | -LL | Other (str), - | ^^^ doesn't have a size known at compile-time - | - = help: the trait `std::marker::Sized` is not implemented for `str` - = note: to learn more, visit - = note: no field of an enum variant may have a dynamically sized type - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. From 28ea03e11477032a29b30284487d6d73e181ecaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 12 Jan 2019 19:25:03 -0800 Subject: [PATCH 15/15] Suggest correct location for lifetime parameters in use --- src/libsyntax/parse/parser.rs | 52 +++++++++++++++---- src/test/ui/parser/issue-14303-fncall.rs | 23 +++++--- src/test/ui/parser/issue-14303-fncall.stderr | 23 +++----- src/test/ui/parser/issue-14303-path.rs | 1 - src/test/ui/parser/issue-14303-path.stderr | 14 ++--- .../ui/traits/trait-object-vs-lifetime.rs | 2 - .../ui/traits/trait-object-vs-lifetime.stderr | 14 +++-- 7 files changed, 82 insertions(+), 47 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3f736c361115a..4d0401097c46d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5330,23 +5330,28 @@ impl<'a> Parser<'a> { /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings, /// possibly including trailing comma. - fn parse_generic_args(&mut self) - -> PResult<'a, (Vec, Vec)> { + fn parse_generic_args(&mut self) -> PResult<'a, (Vec, Vec)> { let mut args = Vec::new(); let mut bindings = Vec::new(); let mut seen_type = false; let mut seen_binding = false; + let mut first_type_or_binding_span: Option = None; + let mut bad_lifetime_pos = vec![]; + let mut last_comma_span = None; + let mut suggestions = vec![]; loop { if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { // Parse lifetime argument. args.push(GenericArg::Lifetime(self.expect_lifetime())); if seen_type || seen_binding { - self.struct_span_err( - self.prev_span, - "lifetime parameters must be declared prior to type parameters" - ) - .span_label(self.prev_span, "must be declared prior to type parameters") - .emit(); + let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span); + bad_lifetime_pos.push(self.prev_span); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) { + suggestions.push((remove_sp, String::new())); + suggestions.push(( + first_type_or_binding_span.unwrap().shrink_to_lo(), + format!("{}, ", snippet))); + } } } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) { // Parse associated type binding. @@ -5354,13 +5359,17 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; self.bump(); let ty = self.parse_ty()?; + let span = lo.to(self.prev_span); bindings.push(TypeBinding { id: ast::DUMMY_NODE_ID, ident, ty, - span: lo.to(self.prev_span), + span, }); seen_binding = true; + if first_type_or_binding_span.is_none() { + first_type_or_binding_span = Some(span); + } } else if self.check_type() { // Parse type argument. let ty_param = self.parse_ty()?; @@ -5375,6 +5384,9 @@ impl<'a> Parser<'a> { ) .emit(); } + if first_type_or_binding_span.is_none() { + first_type_or_binding_span = Some(ty_param.span); + } args.push(GenericArg::Type(ty_param)); seen_type = true; } else { @@ -5383,8 +5395,30 @@ impl<'a> Parser<'a> { if !self.eat(&token::Comma) { break + } else { + last_comma_span = Some(self.prev_span); } } + if !bad_lifetime_pos.is_empty() { + let mut err = self.struct_span_err( + bad_lifetime_pos.clone(), + "lifetime parameters must be declared prior to type parameters" + ); + for sp in &bad_lifetime_pos { + err.span_label(*sp, "must be declared prior to type parameters"); + } + if !suggestions.is_empty() { + err.multipart_suggestion_with_applicability( + &format!( + "move the lifetime parameter{} prior to the first type parameter", + if bad_lifetime_pos.len() > 1 { "s" } else { "" }, + ), + suggestions, + Applicability::MachineApplicable, + ); + } + err.emit(); + } Ok((args, bindings)) } diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issue-14303-fncall.rs index f08b847ac3288..17b9b766b2181 100644 --- a/src/test/ui/parser/issue-14303-fncall.rs +++ b/src/test/ui/parser/issue-14303-fncall.rs @@ -1,8 +1,17 @@ -fn main() { - (0..4) - .map(|x| x * 2) - .collect::>() - //~^ ERROR lifetime parameters must be declared prior to type parameters - //~| ERROR use of undeclared lifetime name - //~| ERROR use of undeclared lifetime name +// can't run rustfix because it doesn't handle multipart suggestions correctly +// compile-flags: -Zborrowck=mir +// we need the above to avoid ast borrowck failure in recovered code + +struct S<'a, T> { + a: &'a T, + b: &'a T, } + +fn foo<'a, 'b>(start: &'a usize, end: &'a usize) { + let _x = (*start..*end) + .map(|x| S { a: start, b: end }) + .collect::>>(); + //~^ ERROR lifetime parameters must be declared prior to type parameters +} + +fn main() {} diff --git a/src/test/ui/parser/issue-14303-fncall.stderr b/src/test/ui/parser/issue-14303-fncall.stderr index fa2deafb67396..2a7364915949e 100644 --- a/src/test/ui/parser/issue-14303-fncall.stderr +++ b/src/test/ui/parser/issue-14303-fncall.stderr @@ -1,21 +1,12 @@ error: lifetime parameters must be declared prior to type parameters - --> $DIR/issue-14303-fncall.rs:4:31 + --> $DIR/issue-14303-fncall.rs:13:29 | -LL | .collect::>() - | ^^ must be declared prior to type parameters - -error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/issue-14303-fncall.rs:4:20 - | -LL | .collect::>() - | ^^ undeclared lifetime - -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/issue-14303-fncall.rs:4:31 +LL | .collect::>>(); + | ^^ must be declared prior to type parameters +help: move the lifetime parameter prior to the first type parameter | -LL | .collect::>() - | ^^ undeclared lifetime +LL | .collect::>>(); + | ^^^ -- -error: aborting due to 3 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issue-14303-path.rs index 8749d46818f69..a08c89f3437b4 100644 --- a/src/test/ui/parser/issue-14303-path.rs +++ b/src/test/ui/parser/issue-14303-path.rs @@ -9,6 +9,5 @@ mod foo { fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} //~^ ERROR lifetime parameters must be declared prior to type parameters -//~| ERROR lifetime parameters must be declared prior to type parameters fn main() {} diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issue-14303-path.stderr index 07e4441b0de3a..fb4fb32e11e50 100644 --- a/src/test/ui/parser/issue-14303-path.stderr +++ b/src/test/ui/parser/issue-14303-path.stderr @@ -2,13 +2,13 @@ error: lifetime parameters must be declared prior to type parameters --> $DIR/issue-14303-path.rs:10:40 | LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} - | ^^ must be declared prior to type parameters - -error: lifetime parameters must be declared prior to type parameters - --> $DIR/issue-14303-path.rs:10:44 + | ^^ ^^ must be declared prior to type parameters + | | + | must be declared prior to type parameters +help: move the lifetime parameters prior to the first type parameter | -LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} - | ^^ must be declared prior to type parameters +LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, 'b, 'c, T>) {} + | ^^^ ^^^ -- -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/traits/trait-object-vs-lifetime.rs b/src/test/ui/traits/trait-object-vs-lifetime.rs index 57d9b2df9f5d7..a12429c868ed0 100644 --- a/src/test/ui/traits/trait-object-vs-lifetime.rs +++ b/src/test/ui/traits/trait-object-vs-lifetime.rs @@ -1,8 +1,6 @@ // A few contrived examples where lifetime should (or should not) be parsed as an object type. // Lifetimes parsed as types are still rejected later by semantic checks. -// compile-flags: -Z continue-parse-after-error - struct S<'a, T>(&'a u8, T); fn main() { diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr index 00f8164caa429..4cc96bae5cd17 100644 --- a/src/test/ui/traits/trait-object-vs-lifetime.stderr +++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr @@ -1,29 +1,33 @@ error: lifetime parameters must be declared prior to type parameters - --> $DIR/trait-object-vs-lifetime.rs:16:25 + --> $DIR/trait-object-vs-lifetime.rs:14:25 | LL | let _: S<'static +, 'static>; | ^^^^^^^ must be declared prior to type parameters +help: move the lifetime parameter prior to the first type parameter + | +LL | let _: S<'static, 'static +>; + | ^^^^^^^^ -- error[E0224]: at least one non-builtin trait is required for an object type - --> $DIR/trait-object-vs-lifetime.rs:11:23 + --> $DIR/trait-object-vs-lifetime.rs:9:23 | LL | let _: S<'static, 'static +>; | ^^^^^^^^^ error[E0107]: wrong number of lifetime arguments: expected 1, found 2 - --> $DIR/trait-object-vs-lifetime.rs:13:23 + --> $DIR/trait-object-vs-lifetime.rs:11:23 | LL | let _: S<'static, 'static>; | ^^^^^^^ unexpected lifetime argument error[E0107]: wrong number of type arguments: expected 1, found 0 - --> $DIR/trait-object-vs-lifetime.rs:13:12 + --> $DIR/trait-object-vs-lifetime.rs:11:12 | LL | let _: S<'static, 'static>; | ^^^^^^^^^^^^^^^^^^^ expected 1 type argument error[E0224]: at least one non-builtin trait is required for an object type - --> $DIR/trait-object-vs-lifetime.rs:16:14 + --> $DIR/trait-object-vs-lifetime.rs:14:14 | LL | let _: S<'static +, 'static>; | ^^^^^^^^^