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

Flaw/inconsistency between block expression description and rustc. #762

Open
crlf0710 opened this issue Feb 16, 2020 · 4 comments · May be fixed by #1414
Open

Flaw/inconsistency between block expression description and rustc. #762

crlf0710 opened this issue Feb 16, 2020 · 4 comments · May be fixed by #1414
Labels
A-grammar Area: Syntax and parsing

Comments

@crlf0710
Copy link
Member

Currently this compiles:

fn foo() -> i32 {
    {3}
}

According to https://doc.rust-lang.org/nightly/reference/expressions/block-expr.html , the {3} part cannot be parsed as tail expression, since it's not ExpressionWithoutBlock. If it is parsed as Statement, then there should be a compile error, because its type is not () and the semicolon could not be not eliminated.

@Centril

@ehuss
Copy link
Contributor

ehuss commented Feb 16, 2020

ExpressionWithoutBlock isn't intended to convey that it is the only kind of "tail expression" in a block. It's intended to convey that ExpressionWithoutBlock can only appear at the end of a block. Blocks as expressions are part of the Statement rule (ExpressionStatement -> ExpressionWithBlock). This is subtly organized to properly handle ; between statements.

This was written with the concept that a block consists of N statements with ; separating statements, and the last one is the value of the block. I agree it is a little confusing. Looking at it a bit, I think Statements could maybe be changed to use Expression at the end, and it should be the same. I don't remember, but I think I was trying to avoid ambiguity with ExpressionStatement, but that probably isn't too important. Just assume + isn't greedy; the reference doesn't really specify how the grammar is to be interpreted.

Should also probably clarify the sentence "The type of ExpressionWithBlock expressions when used as statements must be the unit type." as this was intended to cover this case, but that is worded poorly.

I guess we should decide if a block is defined as "N statements plus a tail expression" or if it is "N statements, and the value is the last statement". I think rustc uses the latter (probably easier to implement), but maybe the former is a better mental model? The former is how I think of it conceptually.

@crlf0710
Copy link
Member Author

@ehuss Thank you for confirming that the compiler's behavior is the source of truth in this case here!

I don't have opinion on which is the better choice here. If the first is chosen, i think it'll be good to also unify the wording of "tail expression" and "final expression" too, since both are occurring in the text; if the second is chosen, maybe we'll need to write something about "value of statement", e.g. assign unit values to declaration statements, and use the expression values as the value of expression statements.

@ehuss
Copy link
Contributor

ehuss commented Jun 22, 2022

cc rust-lang/rust#61733

@tczajka
Copy link
Contributor

tczajka commented Oct 10, 2023

Just assume + isn't greedy

This doesn't help: the grammar is actually unambiguous here, so it doesn't matter whether + is greedy. It's just that the grammar has a symbol called Statement when in fact the last Statement is sometimes not a statement (when it's an ExpressionStatement without a semicolon).

Also the textual description below isn't clear about this. It talks about "final optional expression" but it doesn't say that when the last thing in a block is an ExpressionWithBlock then it's considered the final expression rather than a statement, despite the syntax.

@tczajka tczajka linked a pull request Oct 10, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-grammar Area: Syntax and parsing
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants