Skip to content

Commit bbdcc4e

Browse files
committed
Adjust parser generic parameter errors
1 parent 899d013 commit bbdcc4e

18 files changed

+93
-54
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -948,10 +948,6 @@ impl<'a> Parser<'a> {
948948
}
949949
}
950950

951-
fn check_const_param(&mut self) -> bool {
952-
self.check_keyword(keywords::Const)
953-
}
954-
955951
fn check_const_arg(&mut self) -> bool {
956952
if self.token.can_begin_const_arg() {
957953
true
@@ -1046,7 +1042,8 @@ impl<'a> Parser<'a> {
10461042
}
10471043

10481044
/// Attempt to consume a `<`. If `<<` is seen, replace it with a single
1049-
/// `<` and continue. If a `<` is not seen, return false.
1045+
/// `<` and continue. If `<-` is seen, replace it with a single `<`
1046+
/// and continue. If a `<` is not seen, return false.
10501047
///
10511048
/// This is meant to be used when parsing generics on a path to get the
10521049
/// starting token.
@@ -1062,6 +1059,11 @@ impl<'a> Parser<'a> {
10621059
self.bump_with(token::Lt, span);
10631060
true
10641061
}
1062+
token::LArrow => {
1063+
let span = self.span.with_lo(self.span.lo() + BytePos(1));
1064+
self.bump_with(token::BinOp(token::Minus), span);
1065+
true
1066+
}
10651067
_ => false,
10661068
};
10671069

@@ -5518,7 +5520,6 @@ impl<'a> Parser<'a> {
55185520
/// trailing comma and erroneous trailing attributes.
55195521
crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
55205522
let mut params = Vec::new();
5521-
let mut prev_param: Option<ParamKindOrd> = None;
55225523
loop {
55235524
let attrs = self.parse_outer_attributes()?;
55245525
if self.check_lifetime() {
@@ -5536,29 +5537,21 @@ impl<'a> Parser<'a> {
55365537
bounds,
55375538
kind: ast::GenericParamKind::Lifetime,
55385539
});
5539-
prev_param = Some(ParamKindOrd::Lifetime);
5540-
} else if self.check_const_param() {
5540+
} else if self.check_keyword(keywords::Const) {
55415541
// Parse const parameter.
55425542
params.push(self.parse_const_param(attrs)?);
5543-
prev_param = Some(ParamKindOrd::Const);
55445543
} else if self.check_ident() {
55455544
// Parse type parameter.
55465545
params.push(self.parse_ty_param(attrs)?);
5547-
prev_param = Some(ParamKindOrd::Type);
55485546
} else {
55495547
// Check for trailing attributes and stop parsing.
5550-
if !attrs.is_empty() {
5551-
if let Some(prev_param) = prev_param {
5552-
self.struct_span_err(
5553-
attrs[0].span,
5554-
&format!(
5555-
"trailing attribute after {} parameter",
5556-
prev_param,
5557-
),
5558-
)
5559-
.span_label(attrs[0].span, "attributes must go before parameters")
5560-
.emit();
5561-
}
5548+
if !attrs.is_empty() && !params.is_empty() {
5549+
self.struct_span_err(
5550+
attrs[0].span,
5551+
&format!("trailing attribute after generic parameter"),
5552+
)
5553+
.span_label(attrs[0].span, "attributes must go before parameters")
5554+
.emit();
55625555
}
55635556
break
55645557
}
@@ -5774,19 +5767,25 @@ impl<'a> Parser<'a> {
57745767
});
57755768
assoc_ty_bindings.push(span);
57765769
} else if self.check_const_arg() {
5770+
// FIXME(const_generics): to distinguish between idents for types and consts,
5771+
// we should introduce a GenericArg::Ident in the AST and distinguish when
5772+
// lowering to the HIR. For now, idents for const args are not permitted.
5773+
57775774
// Parse const argument.
57785775
let expr = if let token::OpenDelim(token::Brace) = self.token {
57795776
self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
5780-
} else if self.token.can_begin_literal_or_bool() {
5781-
let lit = self.parse_lit()?;
5782-
self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
5783-
} else {
5777+
} else if self.token.is_ident() {
57845778
// FIXME(const_generics): to distinguish between idents for types and consts,
57855779
// we should introduce a GenericArg::Ident in the AST and distinguish when
57865780
// lowering to the HIR. For now, idents for const args are not permitted.
57875781
return Err(
57885782
self.fatal("identifiers may currently not be used for const generics")
57895783
);
5784+
} else {
5785+
// FIXME(const_generics): this currently conflicts with emplacement syntax
5786+
// with negative integer literals.
5787+
let lit = self.parse_lit()?;
5788+
self.mk_expr(lit.span, ExprKind::Lit(lit), ThinVec::new())
57905789
};
57915790
let value = AnonConst {
57925791
id: ast::DUMMY_NODE_ID,
@@ -6444,7 +6443,7 @@ impl<'a> Parser<'a> {
64446443
// `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
64456444
// `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
64466445
// `<` (LIFETIME|IDENT) `=` - generic parameter with a default
6447-
// `<` const IDENT - generic const parameter
6446+
// `<` const - generic const parameter
64486447
// The only truly ambiguous case is
64496448
// `<` IDENT `>` `::` IDENT ...
64506449
// we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)

src/libsyntax/parse/token.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,6 @@ impl Token {
284284
match self {
285285
OpenDelim(Brace) => true,
286286
Interpolated(ref nt) => match nt.0 {
287-
NtExpr(..) => true,
288287
NtBlock(..) => true,
289288
NtLiteral(..) => true,
290289
_ => false,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
88

99
impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
10-
//~^ ERROR trailing attribute after lifetime parameter
10+
//~^ ERROR trailing attribute after generic parameter
1111
}
1212

1313
fn main() {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: trailing attribute after lifetime parameter
1+
error: trailing attribute after generic parameter
22
--> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25
33
|
44
LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
struct RefAny<'a, T>(&'a T);
88

99
impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
10-
//~^ ERROR trailing attribute after type parameter
10+
//~^ ERROR trailing attribute after generic parameter
1111

1212
fn main() {}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: trailing attribute after type parameter
1+
error: trailing attribute after generic parameter
22
--> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35
33
|
44
LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
66

77
fn hof_lt<Q>(_: Q)
88
where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
9-
//~^ ERROR trailing attribute after lifetime parameter
9+
//~^ ERROR trailing attribute after generic parameter
1010
{}
1111

1212
fn main() {}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: trailing attribute after lifetime parameter
1+
error: trailing attribute after generic parameter
22
--> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44
33
|
44
LL | where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
fn u32_identity<const X: u32>() -> u32 {
5+
//~^ ERROR const generics in any position are currently unsupported
6+
5
7+
}
8+
9+
fn foo_a() {
10+
u32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
11+
}
12+
13+
fn foo_b() {
14+
u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
15+
}
16+
17+
fn main() {
18+
u32_identity::<5>(); // ok
19+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: expected identifier, found `<-`
2+
--> $DIR/const-expression-parameter.rs:10:19
3+
|
4+
LL | u32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
5+
| ^^ expected identifier
6+
7+
error: expected one of `,` or `>`, found `+`
8+
--> $DIR/const-expression-parameter.rs:14:22
9+
|
10+
LL | u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
11+
| ^ expected one of `,` or `>` here
12+
13+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
14+
--> $DIR/const-expression-parameter.rs:1:12
15+
|
16+
LL | #![feature(const_generics)]
17+
| ^^^^^^^^^^^^^^
18+
19+
error: const generics in any position are currently unsupported
20+
--> $DIR/const-expression-parameter.rs:4:23
21+
|
22+
LL | fn u32_identity<const X: u32>() -> u32 {
23+
| ^
24+
25+
error: aborting due to 3 previous errors
26+

0 commit comments

Comments
 (0)