about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-10-04 06:14:13 +0200
committerGitHub <noreply@github.com>2022-10-04 06:14:13 +0200
commit185ca0f1815e5b05524670c7178b7e8cb31ebec2 (patch)
tree7624cb7dd1eadc05d975a87723d69fe650c7c416 /compiler
parentf86ee786a55b10dac83f5a7c1043b81677da7683 (diff)
parent88dab8d9b3c3556e29bc551efa5ff727a15e0c6d (diff)
Rollup merge of #102639 - nnethercote:improve-spans-splitting, r=Aaron1011
Improve spans when splitting multi-char operator tokens for proc macros.

When a two-char (or three-char) operator token is split into single-char operator tokens before being passed to a proc macro, the single-char tokens are given the original span of length two (or three). This PR gives them more accurate spans.

r? `@Aaron1011`
cc `@petrochenkov`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs16
1 files changed, 14 insertions, 2 deletions
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index ff09a9fb87a..17a348ec6ba 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -115,8 +115,20 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
             // before that get `joint = true`.
             let mut op = |s: &str| {
                 assert!(s.is_ascii());
-                trees.extend(s.bytes().enumerate().map(|(idx, ch)| {
-                    let is_final = idx == s.len() - 1;
+                trees.extend(s.bytes().enumerate().map(|(i, ch)| {
+                    let is_final = i == s.len() - 1;
+                    // Split the token span into single chars. Unless the span
+                    // is an unusual one, e.g. due to proc macro expansion. We
+                    // determine this by assuming any span with a length that
+                    // matches the operator length is a normal one, and any
+                    // span with a different length is an unusual one.
+                    let span = if (span.hi() - span.lo()).to_usize() == s.len() {
+                        let lo = span.lo() + BytePos::from_usize(i);
+                        let hi = lo + BytePos::from_usize(1);
+                        span.with_lo(lo).with_hi(hi)
+                    } else {
+                        span
+                    };
                     TokenTree::Punct(Punct { ch, joint: if is_final { joint } else { true }, span })
                 }));
             };