1
Fork 0

Adjust parser generic parameter errors

This commit is contained in:
varkor 2019-02-07 10:10:11 +01:00
parent 899d013fef
commit bbdcc4e7ce
18 changed files with 93 additions and 54 deletions

View file

@ -948,10 +948,6 @@ impl<'a> Parser<'a> {
} }
} }
fn check_const_param(&mut self) -> bool {
self.check_keyword(keywords::Const)
}
fn check_const_arg(&mut self) -> bool { fn check_const_arg(&mut self) -> bool {
if self.token.can_begin_const_arg() { if self.token.can_begin_const_arg() {
true true
@ -1046,7 +1042,8 @@ impl<'a> Parser<'a> {
} }
/// Attempt to consume a `<`. If `<<` is seen, replace it with a single /// Attempt to consume a `<`. If `<<` is seen, replace it with a single
/// `<` and continue. If a `<` is not seen, return false. /// `<` and continue. If `<-` is seen, replace it with a single `<`
/// and continue. If a `<` is not seen, return false.
/// ///
/// This is meant to be used when parsing generics on a path to get the /// This is meant to be used when parsing generics on a path to get the
/// starting token. /// starting token.
@ -1062,6 +1059,11 @@ impl<'a> Parser<'a> {
self.bump_with(token::Lt, span); self.bump_with(token::Lt, span);
true true
} }
token::LArrow => {
let span = self.span.with_lo(self.span.lo() + BytePos(1));
self.bump_with(token::BinOp(token::Minus), span);
true
}
_ => false, _ => false,
}; };
@ -5518,7 +5520,6 @@ impl<'a> Parser<'a> {
/// trailing comma and erroneous trailing attributes. /// trailing comma and erroneous trailing attributes.
crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> { crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
let mut params = Vec::new(); let mut params = Vec::new();
let mut prev_param: Option<ParamKindOrd> = None;
loop { loop {
let attrs = self.parse_outer_attributes()?; let attrs = self.parse_outer_attributes()?;
if self.check_lifetime() { if self.check_lifetime() {
@ -5536,30 +5537,22 @@ impl<'a> Parser<'a> {
bounds, bounds,
kind: ast::GenericParamKind::Lifetime, kind: ast::GenericParamKind::Lifetime,
}); });
prev_param = Some(ParamKindOrd::Lifetime); } else if self.check_keyword(keywords::Const) {
} else if self.check_const_param() {
// Parse const parameter. // Parse const parameter.
params.push(self.parse_const_param(attrs)?); params.push(self.parse_const_param(attrs)?);
prev_param = Some(ParamKindOrd::Const);
} else if self.check_ident() { } else if self.check_ident() {
// Parse type parameter. // Parse type parameter.
params.push(self.parse_ty_param(attrs)?); params.push(self.parse_ty_param(attrs)?);
prev_param = Some(ParamKindOrd::Type);
} else { } else {
// Check for trailing attributes and stop parsing. // Check for trailing attributes and stop parsing.
if !attrs.is_empty() { if !attrs.is_empty() && !params.is_empty() {
if let Some(prev_param) = prev_param {
self.struct_span_err( self.struct_span_err(
attrs[0].span, attrs[0].span,
&format!( &format!("trailing attribute after generic parameter"),
"trailing attribute after {} parameter",
prev_param,
),
) )
.span_label(attrs[0].span, "attributes must go before parameters") .span_label(attrs[0].span, "attributes must go before parameters")
.emit(); .emit();
} }
}
break break
} }
@ -5774,19 +5767,25 @@ impl<'a> Parser<'a> {
}); });
assoc_ty_bindings.push(span); assoc_ty_bindings.push(span);
} else if self.check_const_arg() { } else if self.check_const_arg() {
// FIXME(const_generics): to distinguish between idents for types and consts,
// we should introduce a GenericArg::Ident in the AST and distinguish when
// lowering to the HIR. For now, idents for const args are not permitted.
// Parse const argument. // Parse const argument.
let expr = if let token::OpenDelim(token::Brace) = self.token { let expr = if let token::OpenDelim(token::Brace) = self.token {
self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())? self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
} else if self.token.can_begin_literal_or_bool() { } else if self.token.is_ident() {
let lit = self.parse_lit()?;
self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
} else {
// FIXME(const_generics): to distinguish between idents for types and consts, // FIXME(const_generics): to distinguish between idents for types and consts,
// we should introduce a GenericArg::Ident in the AST and distinguish when // we should introduce a GenericArg::Ident in the AST and distinguish when
// lowering to the HIR. For now, idents for const args are not permitted. // lowering to the HIR. For now, idents for const args are not permitted.
return Err( return Err(
self.fatal("identifiers may currently not be used for const generics") self.fatal("identifiers may currently not be used for const generics")
); );
} else {
// FIXME(const_generics): this currently conflicts with emplacement syntax
// with negative integer literals.
let lit = self.parse_lit()?;
self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
}; };
let value = AnonConst { let value = AnonConst {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -6444,7 +6443,7 @@ impl<'a> Parser<'a> {
// `<` (LIFETIME|IDENT) `,` - first generic parameter in a list // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
// `<` (LIFETIME|IDENT) `:` - generic parameter with bounds // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
// `<` (LIFETIME|IDENT) `=` - generic parameter with a default // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
// `<` const IDENT - generic const parameter // `<` const - generic const parameter
// The only truly ambiguous case is // The only truly ambiguous case is
// `<` IDENT `>` `::` IDENT ... // `<` IDENT `>` `::` IDENT ...
// we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`) // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)

View file

@ -284,7 +284,6 @@ impl Token {
match self { match self {
OpenDelim(Brace) => true, OpenDelim(Brace) => true,
Interpolated(ref nt) => match nt.0 { Interpolated(ref nt) => match nt.0 {
NtExpr(..) => true,
NtBlock(..) => true, NtBlock(..) => true,
NtLiteral(..) => true, NtLiteral(..) => true,
_ => false, _ => false,

View file

@ -7,7 +7,7 @@
struct RefIntPair<'a, 'b>(&'a u32, &'b u32); struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> { impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
//~^ ERROR trailing attribute after lifetime parameter //~^ ERROR trailing attribute after generic parameter
} }
fn main() { fn main() {

View file

@ -1,4 +1,4 @@
error: trailing attribute after lifetime parameter error: trailing attribute after generic parameter
--> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25 --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25
| |
LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> { LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {

View file

@ -7,6 +7,6 @@
struct RefAny<'a, T>(&'a T); struct RefAny<'a, T>(&'a T);
impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {} impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
//~^ ERROR trailing attribute after type parameter //~^ ERROR trailing attribute after generic parameter
fn main() {} fn main() {}

View file

@ -1,4 +1,4 @@
error: trailing attribute after type parameter error: trailing attribute after generic parameter
--> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35 --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35
| |
LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {} LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}

View file

@ -6,7 +6,7 @@ struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
fn hof_lt<Q>(_: Q) fn hof_lt<Q>(_: Q)
where Q: for <#[allow(unused)] '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 parameter //~^ ERROR trailing attribute after generic parameter
{} {}
fn main() {} fn main() {}

View file

@ -1,4 +1,4 @@
error: trailing attribute after lifetime parameter error: trailing attribute after generic parameter
--> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44 --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44
| |
LL | where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 LL | where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32

View file

@ -0,0 +1,19 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
fn u32_identity<const X: u32>() -> u32 {
//~^ ERROR const generics in any position are currently unsupported
5
}
fn foo_a() {
u32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
}
fn foo_b() {
u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
}
fn main() {
u32_identity::<5>(); // ok
}

View file

@ -0,0 +1,26 @@
error: expected identifier, found `<-`
--> $DIR/const-expression-parameter.rs:10:19
|
LL | u32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
| ^^ expected identifier
error: expected one of `,` or `>`, found `+`
--> $DIR/const-expression-parameter.rs:14:22
|
LL | u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
| ^ expected one of `,` or `>` here
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/const-expression-parameter.rs:1:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
error: const generics in any position are currently unsupported
--> $DIR/const-expression-parameter.rs:4:23
|
LL | fn u32_identity<const X: u32>() -> u32 {
| ^
error: aborting due to 3 previous errors

View file

@ -1,5 +1,3 @@
// ignore-tidy-linelength
// We need all these 9 issue-20616-N.rs files // We need all these 9 issue-20616-N.rs files
// because we can only catch one parsing error at a time // because we can only catch one parsing error at a time
@ -12,7 +10,8 @@ type Type_1_<'a, T> = &'a T;
//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` //type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,` type Type_3<T> = Box<T,,>;
//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,` //type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`

View file

@ -1,7 +1,7 @@
error: expected one of `>`, const, identifier, lifetime, or type, found `,` error: expected one of `>`, const, identifier, lifetime, or type, found `,`
--> $DIR/issue-20616-3.rs:15:24 --> $DIR/issue-20616-3.rs:13:24
| |
LL | type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,` LL | type Type_3<T> = Box<T,,>;
| ^ expected one of `>`, const, identifier, lifetime, or type here | ^ expected one of `>`, const, identifier, lifetime, or type here
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,5 +1,3 @@
// ignore-tidy-linelength
// We need all these 9 issue-20616-N.rs files // We need all these 9 issue-20616-N.rs files
// because we can only catch one parsing error at a time // because we can only catch one parsing error at a time
@ -27,7 +25,8 @@ type Type_5_<'a> = Type_1_<'a, ()>;
//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
type Type_7 = Box<(),,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,` type Type_7 = Box<(),,>;
//~^ error: expected one of `>`, const, identifier, lifetime, or type, found `,`
//type Type_8<'a,,> = &'a (); // error: expected ident, found `,` //type Type_8<'a,,> = &'a (); // error: expected ident, found `,`

View file

@ -1,7 +1,7 @@
error: expected one of `>`, const, identifier, lifetime, or type, found `,` error: expected one of `>`, const, identifier, lifetime, or type, found `,`
--> $DIR/issue-20616-7.rs:30:22 --> $DIR/issue-20616-7.rs:28:22
| |
LL | type Type_7 = Box<(),,>; //~ error: expected one of `>`, const, identifier, lifetime, or type, found `,` LL | type Type_7 = Box<(),,>;
| ^ expected one of `>`, const, identifier, lifetime, or type here | ^ expected one of `>`, const, identifier, lifetime, or type here
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,5 +1,3 @@
// ignore-tidy-linelength
// We need all these 9 issue-20616-N.rs files // We need all these 9 issue-20616-N.rs files
// because we can only catch one parsing error at a time // because we can only catch one parsing error at a time
@ -30,7 +28,8 @@ type Type_5_<'a> = Type_1_<'a, ()>;
//type Type_7 = Box<(),,>; // error: expected type, found `,` //type Type_7 = Box<(),,>; // error: expected type, found `,`
type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,` type Type_8<'a,,> = &'a ();
//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
//type Type_9<T,,> = Box<T>; // error: expected identifier, found `,` //type Type_9<T,,> = Box<T>; // error: expected identifier, found `,`

View file

@ -1,7 +1,7 @@
error: expected one of `>`, `const`, identifier, or lifetime, found `,` error: expected one of `>`, `const`, identifier, or lifetime, found `,`
--> $DIR/issue-20616-8.rs:33:16 --> $DIR/issue-20616-8.rs:31:16
| |
LL | type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,` LL | type Type_8<'a,,> = &'a ();
| ^ expected one of `>`, `const`, identifier, or lifetime here | ^ expected one of `>`, `const`, identifier, or lifetime here
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,5 +1,3 @@
// ignore-tidy-linelength
// We need all these 9 issue-20616-N.rs files // We need all these 9 issue-20616-N.rs files
// because we can only catch one parsing error at a time // because we can only catch one parsing error at a time
@ -33,4 +31,5 @@ type Type_5_<'a> = Type_1_<'a, ()>;
//type Type_8<'a,,> = &'a (); // error: expected identifier, found `,` //type Type_8<'a,,> = &'a (); // error: expected identifier, found `,`
type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,` type Type_9<T,,> = Box<T>;
//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`

View file

@ -1,7 +1,7 @@
error: expected one of `>`, `const`, identifier, or lifetime, found `,` error: expected one of `>`, `const`, identifier, or lifetime, found `,`
--> $DIR/issue-20616-9.rs:36:15 --> $DIR/issue-20616-9.rs:34:15
| |
LL | type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, `const`, identifier, or lifetime, found `,` LL | type Type_9<T,,> = Box<T>;
| ^ expected one of `>`, `const`, identifier, or lifetime here | ^ expected one of `>`, `const`, identifier, or lifetime here
error: aborting due to previous error error: aborting due to previous error