about summary refs log tree commit diff
path: root/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-10-28 10:32:13 +0000
committerGitHub <noreply@github.com>2021-10-28 10:32:13 +0000
commitf4ba64ee2a05f3a38458a4a10dfd59eee9fd2a16 (patch)
treea68e10e2a38433f4a0acbed8fde467bad5f01698 /tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff
parent210a1d5ece776320ab4a36c25d0442a197939aa9 (diff)
parent485c5e67173e444bcb8eeef14c413a7030f6b875 (diff)
downloadrust-f4ba64ee2a05f3a38458a4a10dfd59eee9fd2a16.tar.gz
rust-f4ba64ee2a05f3a38458a4a10dfd59eee9fd2a16.zip
Merge #10623
10623: internal: replace L_DOLLAR/R_DOLLAR with parenthesis hack r=matklad a=matklad

The general problem we are dealing with here is this:

```
macro_rules! thrice {
    ($e:expr) => { $e * 3}
}

fn main() {
    let x = thrice!(1 + 2);
}
```

we really want this to print 9 rather than 7.

The way rustc solves this is rather ad-hoc. In rustc, token trees are
allowed to include whole AST fragments, so 1+2 is passed through macro
expansion as a single unit. This is a significant violation of token
tree model.

In rust-analyzer, we intended to handle this in a more elegant way,
using token trees with "invisible" delimiters. The idea was is that we
introduce a new kind of parenthesis, "left $"/"right $", and let the
parser intelligently handle this.

The idea was inspired by the relevant comment in the proc_macro crate:

https://doc.rust-lang.org/stable/proc_macro/enum.Delimiter.html#variant.None

> An implicit delimiter, that may, for example, appear around tokens
> coming from a “macro variable” $var. It is important to preserve
> operator priorities in cases like $var * 3 where $var is 1 + 2.
> Implicit delimiters might not survive roundtrip of a token stream
> through a string.

Now that we are older and wiser, we conclude that the idea doesn't work.

_First_, the comment in the proc-macro crate is wishful thinking. Rustc
currently completely ignores none delimiters. It solves the (1 + 2) * 3
problem by having magical token trees which can't be duplicated:

* https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer/topic/TIL.20that.20token.20streams.20are.20magic
* https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Handling.20of.20Delimiter.3A.3ANone.20by.20the.20parser

_Second_, it's not like our implementation in rust-analyzer works. We
special-case expressions (as opposed to treating all kinds of $var
captures the same) and we don't know how parser error recovery should
work with these dollar-parenthesis.

So, in this PR we simplify the whole thing away by not pretending that
we are doing something proper and instead just explicitly special-casing
expressions by wrapping them into real `()`.

In the future, to maintain bug-parity with `rustc` what we are going to
do is probably adding an explicit `CAPTURED_EXPR` *token* which we can
explicitly account for in the parser.

If/when rustc starts handling delimiter=none properly, we'll port that
logic as well, in addition to special handling.

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
Diffstat (limited to 'tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff')
0 files changed, 0 insertions, 0 deletions