Skip to content

Commit 8959c99

Browse files
committed
Allow generic parameters to be specified in expressions without ::
1 parent 7ee7207 commit 8959c99

File tree

9 files changed

+71
-75
lines changed

9 files changed

+71
-75
lines changed

src/libsyntax/parse/parser.rs

+39-18
Original file line numberDiff line numberDiff line change
@@ -1725,11 +1725,10 @@ impl<'a> Parser<'a> {
17251725
} else if self.eat_keyword(keywords::Const) {
17261726
Mutability::Immutable
17271727
} else {
1728-
let span = self.prev_span;
1729-
self.span_err(span,
1730-
"expected mut or const in raw pointer type (use \
1731-
`*mut T` or `*const T` as appropriate)");
1732-
Mutability::Immutable
1728+
let mut err = self.fatal("expected mut or const in raw pointer type (use \
1729+
`*mut T` or `*const T` as appropriate)");
1730+
err.span_label(self.prev_span, "expected mut or const");
1731+
return Err(err);
17331732
};
17341733
let t = self.parse_ty_no_plus()?;
17351734
Ok(MutTy { ty: t, mutbl: mutbl })
@@ -2041,20 +2040,26 @@ impl<'a> Parser<'a> {
20412040
-> PResult<'a, PathSegment> {
20422041
let ident = self.parse_path_segment_ident()?;
20432042

2044-
let is_args_start = |token: &token::Token| match *token {
2045-
token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true,
2043+
let is_args_start = |token: &token::Token, include_paren: bool| match *token {
2044+
token::Lt | token::BinOp(token::Shl) => true,
2045+
token::OpenDelim(token::Paren) => include_paren,
20462046
_ => false,
20472047
};
2048-
let check_args_start = |this: &mut Self| {
2049-
this.expected_tokens.extend_from_slice(
2050-
&[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))]
2051-
);
2052-
is_args_start(&this.token)
2048+
let check_args_start = |this: &mut Self, include_paren: bool| {
2049+
this.expected_tokens.push(TokenType::Token(token::Lt));
2050+
if include_paren {
2051+
this.expected_tokens.push(TokenType::Token(token::OpenDelim(token::Paren)));
2052+
}
2053+
is_args_start(&this.token, include_paren)
20532054
};
20542055

2055-
Ok(if style == PathStyle::Type && check_args_start(self) ||
2056+
let expr_without_disambig = style == PathStyle::Expr && check_args_start(self, false);
2057+
let parser_snapshot_before_generics = self.clone();
2058+
2059+
Ok(if style == PathStyle::Type && check_args_start(self, true) ||
20562060
style != PathStyle::Mod && self.check(&token::ModSep)
2057-
&& self.look_ahead(1, |t| is_args_start(t)) {
2061+
&& self.look_ahead(1, |t| is_args_start(t, true))
2062+
|| expr_without_disambig {
20582063
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
20592064
let lo = self.span;
20602065
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
@@ -2064,10 +2069,26 @@ impl<'a> Parser<'a> {
20642069

20652070
let args = if self.eat_lt() {
20662071
// `<'a, T, A = U>`
2067-
let (args, bindings) = self.parse_generic_args()?;
2068-
self.expect_gt()?;
2069-
let span = lo.to(self.prev_span);
2070-
AngleBracketedArgs { args, bindings, span }.into()
2072+
let args: PResult<_> = do catch {
2073+
let (args, bindings) = self.parse_generic_args()?;
2074+
self.expect_gt()?;
2075+
let span = lo.to(self.prev_span);
2076+
AngleBracketedArgs { args, bindings, span }
2077+
};
2078+
2079+
match args {
2080+
Err(mut err) => {
2081+
if expr_without_disambig {
2082+
err.cancel();
2083+
mem::replace(self, parser_snapshot_before_generics);
2084+
return Ok(PathSegment::from_ident(ident));
2085+
}
2086+
return Err(err);
2087+
}
2088+
_ => {
2089+
args?.into()
2090+
}
2091+
}
20712092
} else {
20722093
// `(T, U) -> R`
20732094
self.bump(); // `(`

src/libsyntax/parse/token.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ pub enum Token {
166166
Comma,
167167
Semi,
168168
Colon,
169-
ModSep,
169+
ModSep, // `::`
170170
RArrow,
171171
LArrow,
172172
FatArrow,

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

+1-1
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

-5
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

+4-4
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() {}
+12-32
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

+2-2
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

+6-6
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
...
+6-6
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)