better suggestion for duplicated where
This commit is contained in:
parent
1ea4851715
commit
f35d43cdf0
@ -4,7 +4,7 @@
|
||||
use rustc_ast::{
|
||||
self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
|
||||
};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_span::symbol::kw;
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
@ -256,7 +256,21 @@ pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
|
||||
break;
|
||||
}
|
||||
|
||||
if !self.eat(&token::Comma) {
|
||||
let prev_token = self.prev_token.span;
|
||||
let ate_comma = self.eat(&token::Comma);
|
||||
|
||||
if self.eat_keyword_noexpect(kw::Where) {
|
||||
let msg = &format!("cannot define duplicate `where` clauses on an item");
|
||||
let mut err = self.struct_span_err(self.token.span, msg);
|
||||
err.span_label(lo, "previous `where` clause starts here");
|
||||
err.span_suggestion_verbose(
|
||||
prev_token.shrink_to_hi().to(self.prev_token.span),
|
||||
"consider joining the two `where` clauses into one",
|
||||
",".to_owned(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.emit();
|
||||
} else if !ate_comma {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1221,7 +1221,7 @@ fn parse_enum_variant(&mut self) -> PResult<'a, Option<Variant>> {
|
||||
|
||||
let struct_def = if this.check(&token::OpenDelim(token::Brace)) {
|
||||
// Parse a struct variant.
|
||||
let (fields, recovered) = this.parse_record_struct_body("struct")?;
|
||||
let (fields, recovered) = this.parse_record_struct_body("struct", false)?;
|
||||
VariantData::Struct(fields, recovered)
|
||||
} else if this.check(&token::OpenDelim(token::Paren)) {
|
||||
VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID)
|
||||
@ -1275,7 +1275,8 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
|
||||
VariantData::Unit(DUMMY_NODE_ID)
|
||||
} else {
|
||||
// If we see: `struct Foo<T> where T: Copy { ... }`
|
||||
let (fields, recovered) = self.parse_record_struct_body("struct")?;
|
||||
let (fields, recovered) =
|
||||
self.parse_record_struct_body("struct", generics.where_clause.has_where_token)?;
|
||||
VariantData::Struct(fields, recovered)
|
||||
}
|
||||
// No `where` so: `struct Foo<T>;`
|
||||
@ -1283,7 +1284,8 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
|
||||
VariantData::Unit(DUMMY_NODE_ID)
|
||||
// Record-style struct definition
|
||||
} else if self.token == token::OpenDelim(token::Brace) {
|
||||
let (fields, recovered) = self.parse_record_struct_body("struct")?;
|
||||
let (fields, recovered) =
|
||||
self.parse_record_struct_body("struct", generics.where_clause.has_where_token)?;
|
||||
VariantData::Struct(fields, recovered)
|
||||
// Tuple-style struct definition with optional where-clause.
|
||||
} else if self.token == token::OpenDelim(token::Paren) {
|
||||
@ -1313,10 +1315,12 @@ fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
|
||||
|
||||
let vdata = if self.token.is_keyword(kw::Where) {
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
let (fields, recovered) = self.parse_record_struct_body("union")?;
|
||||
let (fields, recovered) =
|
||||
self.parse_record_struct_body("union", generics.where_clause.has_where_token)?;
|
||||
VariantData::Struct(fields, recovered)
|
||||
} else if self.token == token::OpenDelim(token::Brace) {
|
||||
let (fields, recovered) = self.parse_record_struct_body("union")?;
|
||||
let (fields, recovered) =
|
||||
self.parse_record_struct_body("union", generics.where_clause.has_where_token)?;
|
||||
VariantData::Struct(fields, recovered)
|
||||
} else {
|
||||
let token_str = super::token_descr(&self.token);
|
||||
@ -1332,6 +1336,7 @@ fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
|
||||
fn parse_record_struct_body(
|
||||
&mut self,
|
||||
adt_ty: &str,
|
||||
parsed_where: bool,
|
||||
) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
|
||||
let mut fields = Vec::new();
|
||||
let mut recovered = false;
|
||||
@ -1353,9 +1358,19 @@ fn parse_record_struct_body(
|
||||
self.eat(&token::CloseDelim(token::Brace));
|
||||
} else {
|
||||
let token_str = super::token_descr(&self.token);
|
||||
let msg = &format!("expected `where`, or `{{` after struct name, found {}", token_str);
|
||||
let msg = &format!(
|
||||
"expected {}`{{` after struct name, found {}",
|
||||
if parsed_where { "" } else { "`where`, or " },
|
||||
token_str
|
||||
);
|
||||
let mut err = self.struct_span_err(self.token.span, msg);
|
||||
err.span_label(self.token.span, "expected `where`, or `{` after struct name");
|
||||
err.span_label(
|
||||
self.token.span,
|
||||
format!(
|
||||
"expected {}`{{` after struct name",
|
||||
if parsed_where { "" } else { "`where`, or " }
|
||||
),
|
||||
);
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
|
2
src/test/ui/parser/bad-struct-following-where.rs
Normal file
2
src/test/ui/parser/bad-struct-following-where.rs
Normal file
@ -0,0 +1,2 @@
|
||||
struct A where T: Sized !
|
||||
//~^ ERROR expected `{` after struct name, found
|
8
src/test/ui/parser/bad-struct-following-where.stderr
Normal file
8
src/test/ui/parser/bad-struct-following-where.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: expected `{` after struct name, found `!`
|
||||
--> $DIR/bad-struct-following-where.rs:1:25
|
||||
|
|
||||
LL | struct A where T: Sized !
|
||||
| ^ expected `{` after struct name
|
||||
|
||||
error: aborting due to previous error
|
||||
|
19
src/test/ui/parser/duplicate-where-clauses.rs
Normal file
19
src/test/ui/parser/duplicate-where-clauses.rs
Normal file
@ -0,0 +1,19 @@
|
||||
struct A where (): Sized where (): Sized {}
|
||||
//~^ ERROR cannot define duplicate `where` clauses on an item
|
||||
|
||||
fn b() where (): Sized where (): Sized {}
|
||||
//~^ ERROR cannot define duplicate `where` clauses on an item
|
||||
|
||||
enum C where (): Sized where (): Sized {}
|
||||
//~^ ERROR cannot define duplicate `where` clauses on an item
|
||||
|
||||
struct D where (): Sized, where (): Sized {}
|
||||
//~^ ERROR cannot define duplicate `where` clauses on an item
|
||||
|
||||
fn e() where (): Sized, where (): Sized {}
|
||||
//~^ ERROR cannot define duplicate `where` clauses on an item
|
||||
|
||||
enum F where (): Sized, where (): Sized {}
|
||||
//~^ ERROR cannot define duplicate `where` clauses on an item
|
||||
|
||||
fn main() {}
|
80
src/test/ui/parser/duplicate-where-clauses.stderr
Normal file
80
src/test/ui/parser/duplicate-where-clauses.stderr
Normal file
@ -0,0 +1,80 @@
|
||||
error: cannot define duplicate `where` clauses on an item
|
||||
--> $DIR/duplicate-where-clauses.rs:1:32
|
||||
|
|
||||
LL | struct A where (): Sized where (): Sized {}
|
||||
| - ^
|
||||
| |
|
||||
| previous `where` clause starts here
|
||||
|
|
||||
help: consider joining the two `where` clauses into one
|
||||
|
|
||||
LL | struct A where (): Sized, (): Sized {}
|
||||
| ~
|
||||
|
||||
error: cannot define duplicate `where` clauses on an item
|
||||
--> $DIR/duplicate-where-clauses.rs:4:30
|
||||
|
|
||||
LL | fn b() where (): Sized where (): Sized {}
|
||||
| - ^
|
||||
| |
|
||||
| previous `where` clause starts here
|
||||
|
|
||||
help: consider joining the two `where` clauses into one
|
||||
|
|
||||
LL | fn b() where (): Sized, (): Sized {}
|
||||
| ~
|
||||
|
||||
error: cannot define duplicate `where` clauses on an item
|
||||
--> $DIR/duplicate-where-clauses.rs:7:30
|
||||
|
|
||||
LL | enum C where (): Sized where (): Sized {}
|
||||
| - ^
|
||||
| |
|
||||
| previous `where` clause starts here
|
||||
|
|
||||
help: consider joining the two `where` clauses into one
|
||||
|
|
||||
LL | enum C where (): Sized, (): Sized {}
|
||||
| ~
|
||||
|
||||
error: cannot define duplicate `where` clauses on an item
|
||||
--> $DIR/duplicate-where-clauses.rs:10:33
|
||||
|
|
||||
LL | struct D where (): Sized, where (): Sized {}
|
||||
| - ^
|
||||
| |
|
||||
| previous `where` clause starts here
|
||||
|
|
||||
help: consider joining the two `where` clauses into one
|
||||
|
|
||||
LL | struct D where (): Sized, (): Sized {}
|
||||
| ~
|
||||
|
||||
error: cannot define duplicate `where` clauses on an item
|
||||
--> $DIR/duplicate-where-clauses.rs:13:31
|
||||
|
|
||||
LL | fn e() where (): Sized, where (): Sized {}
|
||||
| - ^
|
||||
| |
|
||||
| previous `where` clause starts here
|
||||
|
|
||||
help: consider joining the two `where` clauses into one
|
||||
|
|
||||
LL | fn e() where (): Sized, (): Sized {}
|
||||
| ~
|
||||
|
||||
error: cannot define duplicate `where` clauses on an item
|
||||
--> $DIR/duplicate-where-clauses.rs:16:31
|
||||
|
|
||||
LL | enum F where (): Sized, where (): Sized {}
|
||||
| - ^
|
||||
| |
|
||||
| previous `where` clause starts here
|
||||
|
|
||||
help: consider joining the two `where` clauses into one
|
||||
|
|
||||
LL | enum F where (): Sized, (): Sized {}
|
||||
| ~
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user