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

Trailing typecast syntax error when used in functions #46466

Closed
vojtechkral opened this issue Dec 3, 2017 · 8 comments
Closed

Trailing typecast syntax error when used in functions #46466

vojtechkral opened this issue Dec 3, 2017 · 8 comments
Labels
A-parser Area: The parsing of Rust source code to an AST C-bug Category: This is a bug.

Comments

@vojtechkral
Copy link
Contributor

This sort of construct causes a syntax error:

fn foo() -> u32 {
    if true { 3i32 } else { 4i32 } as u32
}
error: expected expression, found keyword `as`

Playground link

The same syntax works fine in an assignment form:

let foo = if true { 3i32 } else { 4i32 } as u32;

And so it is surprising that it doesn't work in a function context.
When parentheses are added, it parses in the function context too:

fn foo() -> u32 {
    (if true { 3i32 } else { 4i32 }) as u32
}

Playground link

The same applies to using match and presumably possibly other expressions as well.

Seems like a bug?

@Havvy
Copy link
Contributor

Havvy commented Dec 3, 2017

Not so much when used as functions, but when a block expression or control flow expression is used as the left expression of a binary expression that is the outer expression of an expression statement or block expression.

The Reference says An expression that consists of only a block expression or control flow expression, that doesn't end a block and evaluates to () can also be used as an expression statement by omitting the trailing semicolon. In these examples, the control flow expression is evaluating to a non-unit value. So either this is a legitimate bug (which I think should be the case) or the reference is wrong.

@vojtechkral
Copy link
Contributor Author

@Havvy Thanks!

If this is indeed a bug, might I perhaps grab the opportunity and get a bit more familiar with the parsing internals by fixing it myself?

@TimNN
Copy link
Contributor

TimNN commented Dec 5, 2017

IIRC this is a known issue. The problem is basically that when the compiler see the if, it needs to decide if the if should be parsed as an expression or a statement, which it can only do from the preceding tokens (This is required so you can do if foo() { bar(); } /* no semicolon here */ foobar();). So in the first example the compiler parses the if as a statement and in the second as an expression.

@Havvy
Copy link
Contributor

Havvy commented Dec 6, 2017

Likewise, if the reference is wrong here, it might be useful to have a diagnostic for when a binary operator starts an expression statement after the implied semicolon from the control flow/block expression.

@kennytm kennytm added A-parser Area: The parsing of Rust source code to an AST C-bug Category: This is a bug. labels Dec 6, 2017
@vojtechkral
Copy link
Contributor Author

I can see a bit of a problem with the specification in the reference: It makes parsing depend on types. Correct me if I'm wrong, but isn't type inferrence a later pass?

@nodakai
Copy link
Contributor

nodakai commented Dec 17, 2017

Minimal reproducer:

fn f() -> i8 {
    { 0 } as i8
}

I was bitten by this issue when I tried to cast an unsafe expression, actually.

@Havvy
Copy link
Contributor

Havvy commented Dec 29, 2017

We've changed the documentation in the reference for now. (Via rust-lang/reference#183)

@estebank
Copy link
Contributor

The compiler now suggests wrapping the expression with parentheses. We're tracking the grammar discussion in #54482.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-parser Area: The parsing of Rust source code to an AST C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

6 participants