Skip to content

Commit 58114b1

Browse files
committed
Auto merge of #53578 - varkor:disappearing-turbofish-crater-run, r=<try>
[Do not merge] Optional turbofish breakage test As an academic exercise, to satisfy ourselves that we completely understand the lay of the land, we'd like to see how often ambiguous cases arise in real-world Rust code. (Following on from #53511.) @rust-lang/infra: is it possible to get a check-only crater run for this change? r? @ghost
2 parents 994cdd9 + ca2849a commit 58114b1

File tree

10 files changed

+85
-76
lines changed

10 files changed

+85
-76
lines changed

src/libsyntax/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#![feature(str_escape)]
2929
#![feature(try_trait)]
3030
#![feature(unicode_internals)]
31+
#![feature(catch_expr)]
3132

3233
#![recursion_limit="256"]
3334

src/libsyntax/parse/parser.rs

+52-19
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ pub struct Parser<'a> {
250250
desugar_doc_comments: bool,
251251
/// Whether we should configure out of line modules as we parse.
252252
pub cfg_mods: bool,
253+
/// Whether we should prevent recovery from parsing areas (during backtracking).
254+
prevent_recovery: bool,
253255
}
254256

255257

@@ -569,6 +571,7 @@ impl<'a> Parser<'a> {
569571
},
570572
desugar_doc_comments,
571573
cfg_mods: true,
574+
prevent_recovery: false,
572575
};
573576

574577
let tok = parser.next_tok();
@@ -1111,6 +1114,9 @@ impl<'a> Parser<'a> {
11111114
first = false;
11121115
} else {
11131116
if let Err(mut e) = self.expect(t) {
1117+
if self.prevent_recovery {
1118+
return Err(e);
1119+
}
11141120
// Attempt to keep parsing if it was a similar separator
11151121
if let Some(ref tokens) = t.similar_tokens() {
11161122
if tokens.contains(&self.token) {
@@ -1725,11 +1731,10 @@ impl<'a> Parser<'a> {
17251731
} else if self.eat_keyword(keywords::Const) {
17261732
Mutability::Immutable
17271733
} 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
1734+
let mut err = self.fatal("expected mut or const in raw pointer type (use \
1735+
`*mut T` or `*const T` as appropriate)");
1736+
err.span_label(self.prev_span, "expected mut or const");
1737+
return Err(err);
17331738
};
17341739
let t = self.parse_ty_no_plus()?;
17351740
Ok(MutTy { ty: t, mutbl: mutbl })
@@ -2041,20 +2046,32 @@ impl<'a> Parser<'a> {
20412046
-> PResult<'a, PathSegment> {
20422047
let ident = self.parse_path_segment_ident()?;
20432048

2044-
let is_args_start = |token: &token::Token| match *token {
2045-
token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true,
2049+
let is_args_start = |token: &token::Token, include_paren: bool| match *token {
2050+
token::Lt | token::BinOp(token::Shl) => true,
2051+
token::OpenDelim(token::Paren) => include_paren,
20462052
_ => false,
20472053
};
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)
2054+
let check_args_start = |this: &mut Self, include_paren: bool| {
2055+
this.expected_tokens.push(TokenType::Token(token::Lt));
2056+
if include_paren {
2057+
this.expected_tokens.push(TokenType::Token(token::OpenDelim(token::Paren)));
2058+
}
2059+
is_args_start(&this.token, include_paren)
20532060
};
20542061

2055-
Ok(if style == PathStyle::Type && check_args_start(self) ||
2056-
style != PathStyle::Mod && self.check(&token::ModSep)
2057-
&& self.look_ahead(1, |t| is_args_start(t)) {
2062+
let mut parser_snapshot_before_generics = None;
2063+
2064+
Ok(if style == PathStyle::Type && check_args_start(self, true)
2065+
|| style != PathStyle::Mod && self.check(&token::ModSep)
2066+
&& self.look_ahead(1, |t| is_args_start(t, true))
2067+
|| style == PathStyle::Expr && check_args_start(self, false) && {
2068+
// Check for generic arguments in an expression without a disambiguating `::`.
2069+
// We have to save a snapshot, because it could end up being an expression
2070+
// instead.
2071+
parser_snapshot_before_generics = Some(self.clone());
2072+
self.prevent_recovery = true;
2073+
true
2074+
} {
20582075
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
20592076
let lo = self.span;
20602077
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
@@ -2064,10 +2081,26 @@ impl<'a> Parser<'a> {
20642081

20652082
let args = if self.eat_lt() {
20662083
// `<'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()
2084+
let args: PResult<_> = do catch {
2085+
let (args, bindings) = self.parse_generic_args()?;
2086+
self.expect_gt()?;
2087+
let span = lo.to(self.prev_span);
2088+
AngleBracketedArgs { args, bindings, span }
2089+
};
2090+
2091+
match args {
2092+
Err(mut err) => {
2093+
if let Some(snapshot) = parser_snapshot_before_generics {
2094+
err.cancel();
2095+
mem::replace(self, snapshot);
2096+
return Ok(PathSegment::from_ident(ident));
2097+
}
2098+
return Err(err);
2099+
}
2100+
_ => {
2101+
args?.into()
2102+
}
2103+
}
20712104
} else {
20722105
// `(T, U) -> R`
20732106
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)