{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rust/issues/28379","labels_url":"https://api.github.com/repos/rust-lang/rust/issues/28379/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/28379/comments","events_url":"https://api.github.com/repos/rust-lang/rust/issues/28379/events","html_url":"https://github.com/rust-lang/rust/issues/28379","id":106185450,"number":28379,"title":"Field access of block: discrepancy between parser-lalr and rustc","user":{"login":"rprichard","id":1572855,"avatar_url":"https://avatars.githubusercontent.com/u/1572855?v=3","gravatar_id":"","url":"https://api.github.com/users/rprichard","html_url":"https://github.com/rprichard","followers_url":"https://api.github.com/users/rprichard/followers","following_url":"https://api.github.com/users/rprichard/following{/other_user}","gists_url":"https://api.github.com/users/rprichard/gists{/gist_id}","starred_url":"https://api.github.com/users/rprichard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rprichard/subscriptions","organizations_url":"https://api.github.com/users/rprichard/orgs","repos_url":"https://api.github.com/users/rprichard/repos","events_url":"https://api.github.com/users/rprichard/events{/privacy}","received_events_url":"https://api.github.com/users/rprichard/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rust-lang/rust/labels/A-lang","name":"A-lang","color":"d7e102"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-09-12T21:20:19Z","updated_at":"2015-09-30T20:45:06Z","closed_at":null,"body":"```rust\r\nstruct S { f: u32 }\r\nfn main() {\r\n    { S { f: 42 } }.f; // rustc accepts, parser-lalr rejects\r\n    { 42 } as i32; // rustc and parser-lalr reject\r\n    { 42 } == 42; // rustc and parser-lalr reject\r\n}\r\n```\r\nThe grammar in src/grammar/parser-lalr.y should probably be relaxed to accept the first example.\r\n\r\nAFAIK, Rust could allow the other two cases (and others), because there are no statements or expressions that begin with `as` or `==`.\r\n"},"comment":{"url":"https://api.github.com/repos/rust-lang/rust/issues/comments/144537691","html_url":"https://github.com/rust-lang/rust/issues/28379#issuecomment-144537691","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/28379","id":144537691,"user":{"login":"rprichard","id":1572855,"avatar_url":"https://avatars.githubusercontent.com/u/1572855?v=3","gravatar_id":"","url":"https://api.github.com/users/rprichard","html_url":"https://github.com/rprichard","followers_url":"https://api.github.com/users/rprichard/followers","following_url":"https://api.github.com/users/rprichard/following{/other_user}","gists_url":"https://api.github.com/users/rprichard/gists{/gist_id}","starred_url":"https://api.github.com/users/rprichard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rprichard/subscriptions","organizations_url":"https://api.github.com/users/rprichard/orgs","repos_url":"https://api.github.com/users/rprichard/repos","events_url":"https://api.github.com/users/rprichard/events{/privacy}","received_events_url":"https://api.github.com/users/rprichard/received_events","type":"User","site_admin":false},"created_at":"2015-09-30T20:45:05Z","updated_at":"2015-09-30T20:45:05Z","body":"If `{1}` is a statement-like expression, then it *can* appear in a binary expression.  This is accepted by `rustc` and `parser-lalr`:\r\n```rust\r\nfn main() {\r\n  1 == {1};\r\n  1 == ({1} + {1});\r\n}\r\n```\r\nAs the LALR grammar describes it, a semicolon-terminated expression statement is a `nonblock_expr` non-terminal.  A `nonblock_expr` can be a binary operation, and the LHS must also be a `nonblock_expr`, whereas the RHS can be an arbitrary `expr`.  I can't think of a nicer way to describe the rule at the moment.\r\n\r\nBoth parsers reject this:\r\n```rust\r\nfn main() {\r\n  {1} == 1;\r\n}\r\n```\r\n\r\nI discovered an interesting case, though:\r\n```rust\r\nfn main() {\r\n  let x = { 1 + {2} * {3} };\r\n  println!(\"{}\", x);\r\n}\r\n```\r\n\r\nThis code parses and compiles, but the two parsers disagree on what it should output.\r\n\r\n`rustc` says `9`, indicating a parse tree of (1 + 2) * 3.\r\n`parser-lalr -v` instead parses it as expected, 1 + (2 * 3):\r\n```\r\n|   |   |   |   |   |   |   (ExprBlock\r\n|   |   |   |   |   |   |   |   (ExprBinary\r\n|   |   |   |   |   |   |   |   |   BiAdd\r\n|   |   |   |   |   |   |   |   |   (ExprLit\r\n|   |   |   |   |   |   |   |   |   |   (LitInteger\r\n|   |   |   |   |   |   |   |   |   |   |   1\r\n|   |   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   |   (ExprBinary\r\n|   |   |   |   |   |   |   |   |   |   BiMul\r\n|   |   |   |   |   |   |   |   |   |   (ExprBlock\r\n|   |   |   |   |   |   |   |   |   |   |   (ExprLit\r\n|   |   |   |   |   |   |   |   |   |   |   |   (LitInteger\r\n|   |   |   |   |   |   |   |   |   |   |   |   |   2\r\n|   |   |   |   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   |   |   (ExprBlock\r\n|   |   |   |   |   |   |   |   |   |   |   (ExprLit\r\n|   |   |   |   |   |   |   |   |   |   |   |   (LitInteger\r\n|   |   |   |   |   |   |   |   |   |   |   |   |   3\r\n|   |   |   |   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   |   )\r\n|   |   |   |   |   |   |   )\r\n```\r\nIf I remove the unnecessary block around the expression, `rustc` prints `7` as expected:\r\n```rust\r\nfn main() {\r\n  let x = 1 + {2} * {3};  // removed the unnecessary block here\r\n  println!(\"{}\", x);\r\n}\r\n```\r\n"}}