Skip to content

Commit 9275f21

Browse files
committed
Allow generic parameters to be specified in expressions without ::
1 parent 2d6d3ac commit 9275f21

File tree

9 files changed

+71
-75
lines changed

9 files changed

+71
-75
lines changed

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 })
@@ -2022,20 +2021,26 @@ impl<'a> Parser<'a> {
20222021
-> PResult<'a, PathSegment> {
20232022
let ident = self.parse_path_segment_ident()?;
20242023

2025-
let is_args_start = |token: &token::Token| match *token {
2026-
token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true,
2024+
let is_args_start = |token: &token::Token, include_paren: bool| match *token {
2025+
token::Lt | token::BinOp(token::Shl) => true,
2026+
token::OpenDelim(token::Paren) => include_paren,
20272027
_ => false,
20282028
};
2029-
let check_args_start = |this: &mut Self| {
2030-
this.expected_tokens.extend_from_slice(
2031-
&[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))]
2032-
);
2033-
is_args_start(&this.token)
2029+
let check_args_start = |this: &mut Self, include_paren: bool| {
2030+
this.expected_tokens.push(TokenType::Token(token::Lt));
2031+
if include_paren {
2032+
this.expected_tokens.push(TokenType::Token(token::OpenDelim(token::Paren)));
2033+
}
2034+
is_args_start(&this.token, include_paren)
20342035
};
20352036

2036-
Ok(if style == PathStyle::Type && check_args_start(self) ||
2037+
let expr_without_disambig = style == PathStyle::Expr && check_args_start(self, false);
2038+
let parser_snapshot_before_generics = self.clone();
2039+
2040+
Ok(if style == PathStyle::Type && check_args_start(self, true) ||
20372041
style != PathStyle::Mod && self.check(&token::ModSep)
2038-
&& self.look_ahead(1, |t| is_args_start(t)) {
2042+
&& self.look_ahead(1, |t| is_args_start(t, true))
2043+
|| expr_without_disambig {
20392044
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
20402045
let lo = self.span;
20412046
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
@@ -2045,10 +2050,26 @@ impl<'a> Parser<'a> {
20452050

20462051
let args = if self.eat_lt() {
20472052
// `<'a, T, A = U>`
2048-
let (args, bindings) = self.parse_generic_args()?;
2049-
self.expect_gt()?;
2050-
let span = lo.to(self.prev_span);
2051-
AngleBracketedArgs { args, bindings, span }.into()
2053+
let args: PResult<_> = do catch {
2054+
let (args, bindings) = self.parse_generic_args()?;
2055+
self.expect_gt()?;
2056+
let span = lo.to(self.prev_span);
2057+
AngleBracketedArgs { args, bindings, span }
2058+
};
2059+
2060+
match args {
2061+
Err(mut err) => {
2062+
if expr_without_disambig {
2063+
err.cancel();
2064+
mem::replace(self, parser_snapshot_before_generics);
2065+
return Ok(PathSegment::from_ident(ident));
2066+
}
2067+
return Err(err);
2068+
}
2069+
_ => {
2070+
args?.into()
2071+
}
2072+
}
20522073
} else {
20532074
// `(T, U) -> R`
20542075
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/issues/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:14: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:18: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:22: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)