Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Do not merge] Allow generic parameters to be specified in expressions without :: #53511

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 53 additions & 19 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1714,11 +1714,10 @@ impl<'a> Parser<'a> {
} else if self.eat_keyword(keywords::Const) {
Mutability::Immutable
} else {
let span = self.prev_span;
self.span_err(span,
"expected mut or const in raw pointer type (use \
`*mut T` or `*const T` as appropriate)");
Mutability::Immutable
let mut err = self.fatal("expected mut or const in raw pointer type (use \
`*mut T` or `*const T` as appropriate)");
err.span_label(self.prev_span, "expected mut or const");
return Err(err);
};
let t = self.parse_ty_no_plus()?;
Ok(MutTy { ty: t, mutbl: mutbl })
Expand Down Expand Up @@ -2022,20 +2021,39 @@ impl<'a> Parser<'a> {
-> PResult<'a, PathSegment> {
let ident = self.parse_path_segment_ident()?;

let is_args_start = |token: &token::Token| match *token {
token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true,
let is_args_start = |token: &token::Token, include_paren: bool| match *token {
token::Lt | token::BinOp(token::Shl) => true,
token::OpenDelim(token::Paren) => include_paren,
_ => false,
};
let check_args_start = |this: &mut Self| {
this.expected_tokens.extend_from_slice(
&[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))]
);
is_args_start(&this.token)
let check_args_start = |this: &mut Self, include_paren: bool| {
this.expected_tokens.push(TokenType::Token(token::Lt));
if include_paren {
this.expected_tokens.push(TokenType::Token(token::OpenDelim(token::Paren)));
}
is_args_start(&this.token, include_paren)
};

Ok(if style == PathStyle::Type && check_args_start(self) ||
style != PathStyle::Mod && self.check(&token::ModSep)
&& self.look_ahead(1, |t| is_args_start(t)) {
let mut parser_snapshot_before_generics = None;

Ok(if style == PathStyle::Type && check_args_start(self, true)
|| style != PathStyle::Mod && self.check(&token::ModSep)
&& self.look_ahead(1, |t| is_args_start(t, true))
&& {
if style == PathStyle::Expr {
// Simulate every occurrence of `::<>` actually being `<>`.
self.eat(&token::ModSep);
parser_snapshot_before_generics = Some(self.clone());
}
true
}
|| style == PathStyle::Expr && check_args_start(self, false) && {
// Check for generic arguments in an expression without a disambiguating `::`.
// We have to save a snapshot, because it could end up being an expression
// instead.
parser_snapshot_before_generics = Some(self.clone());
true
} {
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
let lo = self.span;
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
Expand All @@ -2045,10 +2063,26 @@ impl<'a> Parser<'a> {

let args = if self.eat_lt() {
// `<'a, T, A = U>`
let (args, bindings) = self.parse_generic_args()?;
self.expect_gt()?;
let span = lo.to(self.prev_span);
AngleBracketedArgs { args, bindings, span }.into()
let args: PResult<_> = do catch {
let (args, bindings) = self.parse_generic_args()?;
self.expect_gt()?;
let span = lo.to(self.prev_span);
AngleBracketedArgs { args, bindings, span }
};

match args {
Err(mut err) => {
if let Some(snapshot) = parser_snapshot_before_generics {
err.cancel();
mem::replace(self, snapshot);
return Ok(PathSegment::from_ident(ident));
}
return Err(err);
}
_ => {
args?.into()
}
}
} else {
// `(T, U) -> R`
self.bump(); // `(`
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ pub enum Token {
Comma,
Semi,
Colon,
ModSep,
ModSep, // `::`
RArrow,
LArrow,
FatArrow,
Expand Down
2 changes: 1 addition & 1 deletion src/test/parse-fail/pat-ranges-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
// Parsing of range patterns

fn main() {
let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!`
let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, `<`, or `=`, found `!`
}
5 changes: 0 additions & 5 deletions src/test/parse-fail/require-parens-for-chained-comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,4 @@ fn main() {

false == 0 < 2;
//~^ ERROR: chained comparison operators require parentheses

f<X>();
//~^ ERROR: chained comparison operators require parentheses
//~| HELP: use `::<...>` instead of `<...>`
//~| HELP: or use `(...)`
}
8 changes: 4 additions & 4 deletions src/test/ui/did_you_mean/issue-40396.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
// except according to those terms.

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

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

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

fn main() {}
44 changes: 12 additions & 32 deletions src/test/ui/did_you_mean/issue-40396.stderr
Original file line number Diff line number Diff line change
@@ -1,38 +1,18 @@
error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:12:37
error[E0423]: expected function, found struct `Vec`
--> $DIR/issue-40396.rs:20:38
|
LL | println!("{:?}", (0..13).collect<Vec<i32>>()); //~ ERROR chained comparison
| ^^^^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments

error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:16:25
|
LL | println!("{:?}", Vec<i32>::new()); //~ ERROR chained comparison
| ^^^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments

error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:20:37
|
LL | println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
| ^^^^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
LL | println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR expected function, found struct `Vec`
| ^^^^^^^^ did you mean `Vec { /* fields */ }`?

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

error: aborting due to 4 previous errors
error: aborting due to 2 previous errors

Some errors occurred: E0423, E0615.
For more information about an error, try `rustc --explain E0423`.
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-6596-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ LL | { $inp $nonexistent }
LL | g!(foo);
| -------- in this macro invocation

error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `nonexistent`
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `nonexistent`
--> $DIR/issue-6596-2.rs:15:16
|
LL | { $inp $nonexistent }
| ^^^^^^^^^^^^ expected one of 8 possible tokens here
| ^^^^^^^^^^^^ expected one of 9 possible tokens here
...
LL | g!(foo);
| -------- in this macro invocation
Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/macro_backtrace/main.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error`
--> $DIR/main.rs:19:20
|
LL | / macro_rules! pong {
LL | | () => { syntax error };
| | ^^^^^ expected one of 8 possible tokens here
| | ^^^^^ expected one of 9 possible tokens here
LL | | }
| |_- in this expansion of `pong!`
...
LL | pong!();
| -------- in this macro invocation

error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error`
--> $DIR/main.rs:19:20
|
LL | / macro_rules! pong {
LL | | () => { syntax error };
| | ^^^^^ expected one of 8 possible tokens here
| | ^^^^^ expected one of 9 possible tokens here
LL | | }
| |_- in this expansion of `pong!`
...
Expand All @@ -30,12 +30,12 @@ LL | ( ) => { pong ! ( ) ; }
| | in this macro invocation
| in this expansion of `ping!`

error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error`
--> $DIR/main.rs:19:20
|
LL | / macro_rules! pong {
LL | | () => { syntax error };
| | ^^^^^ expected one of 8 possible tokens here
| | ^^^^^ expected one of 9 possible tokens here
LL | | }
| |_- in this expansion of `pong!` (#5)
...
Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/raw/raw-literal-keywords.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true`
error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `true`
--> $DIR/raw-literal-keywords.rs:16:10
|
LL | r#if true { } //~ ERROR found `true`
| ^^^^ expected one of 8 possible tokens here
| ^^^^ expected one of 9 possible tokens here

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

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

error: aborting due to 3 previous errors