about summary refs log tree commit diff
path: root/compiler/rustc_parse
diff options
context:
space:
mode:
authorest31 <MTest31@outlook.com>2023-06-02 18:53:04 +0200
committerest31 <MTest31@outlook.com>2023-06-08 23:42:58 +0200
commit1b90f5efaf46073a7da509a895a0688e1c6300c3 (patch)
tree1dfa03e86f163a72e16a6d62df81f0aead4684c6 /compiler/rustc_parse
parentd74ec96e8d334c765e35707f7b7f3c6499a1b43c (diff)
downloadrust-1b90f5efaf46073a7da509a895a0688e1c6300c3.tar.gz
rust-1b90f5efaf46073a7da509a895a0688e1c6300c3.zip
Support float-like tuple indices in offset_of!()
The tokenizer gives us whole float literal tokens, we have to split them up
in order to be able to create field access from them.
Diffstat (limited to 'compiler/rustc_parse')
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs47
1 files changed, 45 insertions, 2 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 9e5f85dc7dc..df06115ef3b 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1852,10 +1852,53 @@ impl<'a> Parser<'a> {
         let (fields, _trailing, _recovered) = self.parse_seq_to_before_end(
             &TokenKind::CloseDelim(Delimiter::Parenthesis),
             seq_sep,
-            Parser::parse_field_name,
+            |this| {
+                let token::Literal(token::Lit { kind: token::Float, symbol, suffix }) = this.token.kind
+                else {
+                    return Ok(thin_vec![this.parse_field_name()?]);
+                };
+                let res = match this.break_up_float(symbol) {
+                    // 1e2
+                    DestructuredFloat::Single(sym, sp) => {
+                        this.bump();
+                        thin_vec![Ident::new(sym, sp)]
+                    }
+                    // 1.
+                    DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => {
+                        assert!(suffix.is_none());
+                        // Analogous to Self::break_and_eat
+                        this.token_cursor.break_last_token = true;
+                        // This might work, in cases like `1. 2.3`, and might not,
+                        // in cases like `offset_of!(Ty, 1.)`.
+                        this.token = Token::new(token::Ident(sym, false), sym_span);
+                        this.bump_with((Token::new(token::Dot, dot_span), this.token_spacing));
+                        thin_vec![Ident::new(sym, sym_span)]
+                    }
+                    // 1.2 | 1.2e3
+                    DestructuredFloat::MiddleDot(
+                        symbol1,
+                        ident1_span,
+                        _dot_span,
+                        symbol2,
+                        ident2_span,
+                    ) => {
+                        this.bump();
+                        thin_vec![
+                            Ident::new(symbol1, ident1_span),
+                            Ident::new(symbol2, ident2_span)
+                        ]
+                    }
+                    DestructuredFloat::Error => {
+                        this.bump();
+                        thin_vec![Ident::new(symbol, this.prev_token.span)]
+                    }
+                };
+                Ok(res)
+            },
         )?;
+        let fields = fields.into_iter().flatten().collect::<Vec<_>>();
         let span = lo.to(self.token.span);
-        Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.to_vec().into())))
+        Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.into())))
     }
 
     /// Returns a string literal if the next token is a string literal.