Skip to content

Commit 832690d

Browse files
committed
Auto merge of #53074 - varkor:blobfish-extinction, r=<try>
[Do not merge] Allow generic parameters to be specified in expressions without `::` Since chained comparison operators are invalid, it's plausible that the `::` disambiguation for generic parameters in expressions is no longer necessary. With the current parser infrastructure this is still a little awkward, requiring backtracking. However, it'd be nice to know just how bad backtracking is, because it _might_ turn out only to be much worse in niche edge cases, in which case the usability benefit could be worthwhile. This PR is intended solely to test the performance of these parser changes. @rust-lang/infra: would it be possible to get a perf run for this change?
2 parents 94c3c34 + 23aac5c commit 832690d

File tree

10 files changed

+72
-75
lines changed

10 files changed

+72
-75
lines changed

src/libsyntax/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#![feature(slice_sort_by_cached_key)]
2828
#![feature(str_escape)]
2929
#![feature(unicode_internals)]
30+
#![feature(catch_expr)]
3031

3132
#![recursion_limit="256"]
3233

src/libsyntax/parse/parser.rs

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,11 +1714,10 @@ impl<'a> Parser<'a> {
17141714
} else if self.eat_keyword(keywords::Const) {
17151715
Mutability::Immutable
17161716
} else {
1717-
let span = self.prev_span;
1718-
self.span_err(span,
1719-
"expected mut or const in raw pointer type (use \
1720-
`*mut T` or `*const T` as appropriate)");
1721-
Mutability::Immutable
1717+
let mut err = self.fatal("expected mut or const in raw pointer type (use \
1718+
`*mut T` or `*const T` as appropriate)");
1719+
err.span_label(self.prev_span, "expected mut or const");
1720+
return Err(err);
17221721
};
17231722
let t = self.parse_ty_no_plus()?;
17241723
Ok(MutTy { ty: t, mutbl: mutbl })
@@ -1984,20 +1983,26 @@ impl<'a> Parser<'a> {
19841983
-> PResult<'a, PathSegment> {
19851984
let ident = self.parse_path_segment_ident()?;
19861985

1987-
let is_args_start = |token: &token::Token| match *token {
1988-
token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true,
1986+
let is_args_start = |token: &token::Token, include_paren: bool| match *token {
1987+
token::Lt | token::BinOp(token::Shl) => true,
1988+
token::OpenDelim(token::Paren) => include_paren,
19891989
_ => false,
19901990
};
1991-
let check_args_start = |this: &mut Self| {
1992-
this.expected_tokens.extend_from_slice(
1993-
&[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))]
1994-
);
1995-
is_args_start(&this.token)
1991+
let check_args_start = |this: &mut Self, include_paren: bool| {
1992+
this.expected_tokens.push(TokenType::Token(token::Lt));
1993+
if include_paren {
1994+
this.expected_tokens.push(TokenType::Token(token::OpenDelim(token::Paren)));
1995+
}
1996+
is_args_start(&this.token, include_paren)
19961997
};
19971998

1998-
Ok(if style == PathStyle::Type && check_args_start(self) ||
1999+
let expr_without_disambig = style == PathStyle::Expr && check_args_start(self, false);
2000+
let parser_snapshot_before_generics = self.clone();
2001+
2002+
Ok(if style == PathStyle::Type && check_args_start(self, true) ||
19992003
style != PathStyle::Mod && self.check(&token::ModSep)
2000-
&& self.look_ahead(1, |t| is_args_start(t)) {
2004+
&& self.look_ahead(1, |t| is_args_start(t, true))
2005+
|| expr_without_disambig {
20012006
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
20022007
let lo = self.span;
20032008
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
@@ -2007,10 +2012,26 @@ impl<'a> Parser<'a> {
20072012

20082013
let args = if self.eat_lt() {
20092014
// `<'a, T, A = U>`
2010-
let (args, bindings) = self.parse_generic_args()?;
2011-
self.expect_gt()?;
2012-
let span = lo.to(self.prev_span);
2013-
AngleBracketedArgs { args, bindings, span }.into()
2015+
let args: PResult<_> = do catch {
2016+
let (args, bindings) = self.parse_generic_args()?;
2017+
self.expect_gt()?;
2018+
let span = lo.to(self.prev_span);
2019+
AngleBracketedArgs { args, bindings, span }
2020+
};
2021+
2022+
match args {
2023+
Err(mut err) => {
2024+
if expr_without_disambig {
2025+
err.cancel();
2026+
mem::replace(self, parser_snapshot_before_generics);
2027+
return Ok(PathSegment::from_ident(ident));
2028+
}
2029+
return Err(err);
2030+
}
2031+
_ => {
2032+
args?.into()
2033+
}
2034+
}
20142035
} else {
20152036
// `(T, U) -> R`
20162037
self.bump(); // `(`

src/libsyntax/parse/token.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ pub enum Token {
167167
Comma,
168168
Semi,
169169
Colon,
170-
ModSep,
170+
ModSep, // `::`
171171
RArrow,
172172
LArrow,
173173
FatArrow,

src/test/parse-fail/pat-ranges-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
// Parsing of range patterns
1212

1313
fn main() {
14-
let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!`
14+
let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, `<`, or `=`, found `!`
1515
}

src/test/parse-fail/require-parens-for-chained-comparison.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,4 @@ fn main() {
1818

1919
false == 0 < 2;
2020
//~^ ERROR: chained comparison operators require parentheses
21-
22-
f<X>();
23-
//~^ ERROR: chained comparison operators require parentheses
24-
//~| HELP: use `::<...>` instead of `<...>`
25-
//~| HELP: or use `(...)`
2621
}

src/test/ui/did_you_mean/issue-40396.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
// except according to those terms.
1010

1111
fn foo() {
12-
println!("{:?}", (0..13).collect<Vec<i32>>()); //~ ERROR chained comparison
12+
println!("{:?}", (0..13).collect<Vec<i32>>()); // ok
1313
}
1414

1515
fn bar() {
16-
println!("{:?}", Vec<i32>::new()); //~ ERROR chained comparison
16+
println!("{:?}", Vec<i32>::new()); // ok
1717
}
1818

1919
fn qux() {
20-
println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
21-
//~^ ERROR chained comparison
20+
println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR expected function, found struct `Vec`
21+
//~^ ERROR attempted to take value of method `collect`
2222
}
2323

2424
fn main() {}
Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,18 @@
1-
error: chained comparison operators require parentheses
2-
--> $DIR/issue-40396.rs:12:37
1+
error[E0423]: expected function, found struct `Vec`
2+
--> $DIR/issue-40396.rs:20:38
33
|
4-
LL | println!("{:?}", (0..13).collect<Vec<i32>>()); //~ ERROR chained comparison
5-
| ^^^^^^^^
6-
|
7-
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
8-
= help: or use `(...)` if you meant to specify fn arguments
9-
10-
error: chained comparison operators require parentheses
11-
--> $DIR/issue-40396.rs:16:25
12-
|
13-
LL | println!("{:?}", Vec<i32>::new()); //~ ERROR chained comparison
14-
| ^^^^^^^
15-
|
16-
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
17-
= help: or use `(...)` if you meant to specify fn arguments
18-
19-
error: chained comparison operators require parentheses
20-
--> $DIR/issue-40396.rs:20:37
21-
|
22-
LL | println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
23-
| ^^^^^^^^
24-
|
25-
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
26-
= help: or use `(...)` if you meant to specify fn arguments
4+
LL | println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR expected function, found struct `Vec`
5+
| ^^^^^^^^ did you mean `Vec { /* fields */ }`?
276

28-
error: chained comparison operators require parentheses
29-
--> $DIR/issue-40396.rs:20:41
7+
error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>`
8+
--> $DIR/issue-40396.rs:20:30
309
|
31-
LL | println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
32-
| ^^^^^^
10+
LL | println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR expected function, found struct `Vec`
11+
| ^^^^^^^
3312
|
34-
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
35-
= help: or use `(...)` if you meant to specify fn arguments
13+
= help: maybe a `()` to call it is missing?
3614

37-
error: aborting due to 4 previous errors
15+
error: aborting due to 2 previous errors
3816

17+
Some errors occurred: E0423, E0615.
18+
For more information about an error, try `rustc --explain E0423`.

src/test/ui/issue-6596-2.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ LL | { $inp $nonexistent }
77
LL | g!(foo);
88
| -------- in this macro invocation
99

10-
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `nonexistent`
10+
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `nonexistent`
1111
--> $DIR/issue-6596-2.rs:15:16
1212
|
1313
LL | { $inp $nonexistent }
14-
| ^^^^^^^^^^^^ expected one of 8 possible tokens here
14+
| ^^^^^^^^^^^^ expected one of 9 possible tokens here
1515
...
1616
LL | g!(foo);
1717
| -------- in this macro invocation

src/test/ui/macro_backtrace/main.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
1+
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error`
22
--> $DIR/main.rs:19:20
33
|
44
LL | / macro_rules! pong {
55
LL | | () => { syntax error };
6-
| | ^^^^^ expected one of 8 possible tokens here
6+
| | ^^^^^ expected one of 9 possible tokens here
77
LL | | }
88
| |_- in this expansion of `pong!`
99
...
1010
LL | pong!();
1111
| -------- in this macro invocation
1212

13-
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
13+
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error`
1414
--> $DIR/main.rs:19:20
1515
|
1616
LL | / macro_rules! pong {
1717
LL | | () => { syntax error };
18-
| | ^^^^^ expected one of 8 possible tokens here
18+
| | ^^^^^ expected one of 9 possible tokens here
1919
LL | | }
2020
| |_- in this expansion of `pong!`
2121
...
@@ -30,12 +30,12 @@ LL | ( ) => { pong ! ( ) ; }
3030
| | in this macro invocation
3131
| in this expansion of `ping!`
3232

33-
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
33+
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error`
3434
--> $DIR/main.rs:19:20
3535
|
3636
LL | / macro_rules! pong {
3737
LL | | () => { syntax error };
38-
| | ^^^^^ expected one of 8 possible tokens here
38+
| | ^^^^^ expected one of 9 possible tokens here
3939
LL | | }
4040
| |_- in this expansion of `pong!` (#5)
4141
...
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true`
1+
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `true`
22
--> $DIR/raw-literal-keywords.rs:16:10
33
|
44
LL | r#if true { } //~ ERROR found `true`
5-
| ^^^^ expected one of 8 possible tokens here
5+
| ^^^^ expected one of 9 possible tokens here
66

7-
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
7+
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `Test`
88
--> $DIR/raw-literal-keywords.rs:20:14
99
|
1010
LL | r#struct Test; //~ ERROR found `Test`
11-
| ^^^^ expected one of 8 possible tokens here
11+
| ^^^^ expected one of 9 possible tokens here
1212

13-
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
13+
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `Test`
1414
--> $DIR/raw-literal-keywords.rs:24:13
1515
|
1616
LL | r#union Test; //~ ERROR found `Test`
17-
| ^^^^ expected one of 8 possible tokens here
17+
| ^^^^ expected one of 9 possible tokens here
1818

1919
error: aborting due to 3 previous errors
2020

0 commit comments

Comments
 (0)