Adjust parser generic parameter errors
This commit is contained in:
parent
899d013fef
commit
bbdcc4e7ce
18 changed files with 93 additions and 54 deletions
|
@ -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> { ... }`)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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> {}
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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
|
||||||
|
|
19
src/test/ui/const-generics/const-expression-parameter.rs
Normal file
19
src/test/ui/const-generics/const-expression-parameter.rs
Normal 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
|
||||||
|
}
|
26
src/test/ui/const-generics/const-expression-parameter.stderr
Normal file
26
src/test/ui/const-generics/const-expression-parameter.stderr
Normal 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
|
||||||
|
|
|
@ -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 `,`
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 `,`
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 `,`
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 `,`
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue