about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-def/src/body/lower.rs9
-rw-r--r--crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs29
-rw-r--r--crates/hir-expand/src/builtin_fn_macro.rs12
-rw-r--r--crates/hir-ty/src/infer/closure.rs1
-rw-r--r--crates/ide-assists/src/handlers/convert_bool_then.rs1
-rw-r--r--crates/ide-assists/src/handlers/promote_local_to_const.rs3
-rw-r--r--crates/ide-assists/src/handlers/remove_dbg.rs5
-rw-r--r--crates/ide-assists/src/utils/suggest_name.rs1
-rw-r--r--crates/ide-db/src/syntax_helpers/node_ext.rs6
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs10
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs54
-rw-r--r--crates/parser/src/lexed_str.rs1
-rw-r--r--crates/parser/src/syntax_kind/generated.rs18
-rw-r--r--crates/syntax/rust.ungram16
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs135
-rw-r--r--crates/syntax/src/ast/prec.rs19
-rw-r--r--crates/syntax/src/tests/ast_src.rs18
17 files changed, 257 insertions, 81 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index 6a2ac15465f..43f58a1bdb0 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -579,11 +579,6 @@ impl ExprCollector<'_> {
                     syntax_ptr,
                 )
             }
-            ast::Expr::BoxExpr(e) => {
-                let expr = self.collect_expr_opt(e.expr());
-                self.alloc_expr(Expr::Box { expr }, syntax_ptr)
-            }
-
             ast::Expr::ArrayExpr(e) => {
                 let kind = e.kind();
 
@@ -653,6 +648,9 @@ impl ExprCollector<'_> {
                 }
             }
             ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
+            ast::Expr::AsmExpr(_) => self.missing_expr(),
+            ast::Expr::OffsetOfExpr(_) => self.missing_expr(),
+            ast::Expr::FormatArgsExpr(_) => self.missing_expr(),
         })
     }
 
@@ -663,6 +661,7 @@ impl ExprCollector<'_> {
         let result_expr_id = self.alloc_expr(Expr::Missing, syntax_ptr);
         let prev_binding_owner = self.current_binding_owner.take();
         self.current_binding_owner = Some(result_expr_id);
+
         (result_expr_id, prev_binding_owner)
     }
 
diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index b232651db96..ea02072ff5c 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -23,6 +23,35 @@ fn main() { 0 as u32; }
 }
 
 #[test]
+fn test_asm_expand() {
+    check(
+        r#"
+#[rustc_builtin_macro]
+macro_rules! asm {() => {}}
+
+fn main() {
+    let i: u64 = 3;
+    let o: u64;
+    unsafe {
+        asm!(
+            "mov {0}, {1}",
+            "add {0}, 5",
+            out(reg) o,
+            in(reg) i,
+        );
+    }
+}
+"#,
+        expect![[r#"
+#[rustc_builtin_macro]
+macro_rules! column {() => {}}
+
+fn main() { 0 as u32; }
+"#]],
+    );
+}
+
+#[test]
 fn test_line_expand() {
     check(
         r#"
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 6a48acef963..7eec6361760 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -399,6 +399,8 @@ fn asm_expand(
     _id: MacroCallId,
     tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
+    // FIXME: parse asm here
+
     // We expand all assembly snippets to `format_args!` invocations to get format syntax
     // highlighting for them.
 
@@ -415,10 +417,12 @@ fn asm_expand(
         }
     }
 
-    let expanded = quote! {{
-        ##literals
-        loop {}
-    }};
+    let pound = quote! {@PUNCT '#'};
+    let expanded = quote! {
+        builtin #pound asm {
+            ##literals
+        }
+    };
     ExpandResult::ok(expanded)
 }
 
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 23efe616f4f..cb442de843a 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -620,6 +620,7 @@ impl InferenceContext<'_> {
             | Expr::Tuple { exprs, is_assignee_expr: _ } => {
                 self.consume_exprs(exprs.iter().copied())
             }
+
             Expr::Missing
             | Expr::Continue { .. }
             | Expr::Path(_)
diff --git a/crates/ide-assists/src/handlers/convert_bool_then.rs b/crates/ide-assists/src/handlers/convert_bool_then.rs
index 1af52c59218..d231708c55b 100644
--- a/crates/ide-assists/src/handlers/convert_bool_then.rs
+++ b/crates/ide-assists/src/handlers/convert_bool_then.rs
@@ -103,7 +103,6 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_>
                 cond,
                 ast::Expr::BinExpr(_)
                     | ast::Expr::BlockExpr(_)
-                    | ast::Expr::BoxExpr(_)
                     | ast::Expr::BreakExpr(_)
                     | ast::Expr::CastExpr(_)
                     | ast::Expr::ClosureExpr(_)
diff --git a/crates/ide-assists/src/handlers/promote_local_to_const.rs b/crates/ide-assists/src/handlers/promote_local_to_const.rs
index 5cc110cf12b..6fc2aa49974 100644
--- a/crates/ide-assists/src/handlers/promote_local_to_const.rs
+++ b/crates/ide-assists/src/handlers/promote_local_to_const.rs
@@ -120,8 +120,7 @@ fn is_body_const(sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr) -> bool {
                 is_const &=
                     sema.resolve_method_call(&call).map(|it| it.is_const(sema.db)).unwrap_or(true)
             }
-            ast::Expr::BoxExpr(_)
-            | ast::Expr::ForExpr(_)
+            ast::Expr::ForExpr(_)
             | ast::Expr::ReturnExpr(_)
             | ast::Expr::TryExpr(_)
             | ast::Expr::YieldExpr(_)
diff --git a/crates/ide-assists/src/handlers/remove_dbg.rs b/crates/ide-assists/src/handlers/remove_dbg.rs
index e2b82223289..cffa3f55c90 100644
--- a/crates/ide-assists/src/handlers/remove_dbg.rs
+++ b/crates/ide-assists/src/handlers/remove_dbg.rs
@@ -113,10 +113,7 @@ fn compute_dbg_replacement(macro_expr: ast::MacroExpr) -> Option<(TextRange, Opt
                 Some(parent) => match (expr, parent) {
                     (ast::Expr::CastExpr(_), ast::Expr::CastExpr(_)) => false,
                     (
-                        ast::Expr::BoxExpr(_)
-                        | ast::Expr::PrefixExpr(_)
-                        | ast::Expr::RefExpr(_)
-                        | ast::Expr::MacroExpr(_),
+                        ast::Expr::PrefixExpr(_) | ast::Expr::RefExpr(_) | ast::Expr::MacroExpr(_),
                         ast::Expr::AwaitExpr(_)
                         | ast::Expr::CallExpr(_)
                         | ast::Expr::CastExpr(_)
diff --git a/crates/ide-assists/src/utils/suggest_name.rs b/crates/ide-assists/src/utils/suggest_name.rs
index f74ebfae02c..16704d598ef 100644
--- a/crates/ide-assists/src/utils/suggest_name.rs
+++ b/crates/ide-assists/src/utils/suggest_name.rs
@@ -103,7 +103,6 @@ pub(crate) fn for_variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>)
 
         match expr {
             ast::Expr::RefExpr(inner) => next_expr = inner.expr(),
-            ast::Expr::BoxExpr(inner) => next_expr = inner.expr(),
             ast::Expr::AwaitExpr(inner) => next_expr = inner.expr(),
             // ast::Expr::BlockExpr(block) => expr = block.tail_expr(),
             ast::Expr::CastExpr(inner) => next_expr = inner.expr(),
diff --git a/crates/ide-db/src/syntax_helpers/node_ext.rs b/crates/ide-db/src/syntax_helpers/node_ext.rs
index 22ced69d81e..e4e735cecd8 100644
--- a/crates/ide-db/src/syntax_helpers/node_ext.rs
+++ b/crates/ide-db/src/syntax_helpers/node_ext.rs
@@ -312,7 +312,6 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
         ast::Expr::ArrayExpr(_)
         | ast::Expr::AwaitExpr(_)
         | ast::Expr::BinExpr(_)
-        | ast::Expr::BoxExpr(_)
         | ast::Expr::BreakExpr(_)
         | ast::Expr::CallExpr(_)
         | ast::Expr::CastExpr(_)
@@ -335,7 +334,10 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
         | ast::Expr::LetExpr(_)
         | ast::Expr::UnderscoreExpr(_)
         | ast::Expr::YieldExpr(_)
-        | ast::Expr::YeetExpr(_) => cb(expr),
+        | ast::Expr::YeetExpr(_)
+        | ast::Expr::OffsetOfExpr(_)
+        | ast::Expr::FormatArgsExpr(_)
+        | ast::Expr::AsmExpr(_) => cb(expr),
     }
 }
 
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 8749d355c85..aacd57af589 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -534,7 +534,15 @@ fn main() {
     assert!(true, "{}", 1);
     assert!(true, "{} asdasd", 1);
     toho!("{}fmt", 0);
-    asm!("mov eax, {0}");
+    let i: u64 = 3;
+    let o: u64;
+    asm!(
+        "mov {0}, {1}",
+        "add {0}, 5",
+        out(reg) o,
+        in(reg) i,
+    );
+
     format_args!(concat!("{}"), "{}");
     format_args!("{} {} {} {} {} {}", backslash, format_args!("{}", 0), foo, "bar", toho!(), backslash);
 }"#,
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index d8553d3f953..7a4f4e4777d 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -1,3 +1,5 @@
+use crate::grammar::types::type_;
+
 use super::*;
 
 // test expr_literals
@@ -73,6 +75,9 @@ pub(super) fn atom_expr(
     if let Some(m) = literal(p) {
         return Some((m, BlockLike::NotBlock));
     }
+    if p.at_contextual_kw(T![builtin]) && p.nth_at(1, T![#]) {
+        return Some((builtin_expr(p)?, BlockLike::NotBlock));
+    }
     if paths::is_path_start(p) {
         return Some(path_expr(p, r));
     }
@@ -93,7 +98,6 @@ pub(super) fn atom_expr(
             m.complete(p, UNDERSCORE_EXPR)
         }
         T![loop] => loop_expr(p, None),
-        T![box] => box_expr(p, None),
         T![while] => while_expr(p, None),
         T![try] => try_block_expr(p, None),
         T![match] => match_expr(p),
@@ -212,6 +216,38 @@ fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker {
     m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
 }
 
+// test builtin_expr
+// fn foo() {
+//     builtin#asm(0);
+//     builtin#format_args(0);
+//     builtin#builtin(0);
+// }
+fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
+    let m = p.start();
+    p.bump_remap(T![builtin]);
+    p.bump(T![#]);
+    if p.at_contextual_kw(T![offset_of]) {
+        p.expect(T!['(']);
+        type_(p);
+        p.bump(T![,]);
+        p.expect(T![')']);
+        Some(m.complete(p, OFFSET_OF_EXPR))
+    } else if p.at_contextual_kw(T![format_args]) {
+        p.expect(T!['(']);
+        expr(p);
+        p.expect(T![')']);
+        Some(m.complete(p, FORMAT_ARGS_EXPR))
+    } else if p.at_contextual_kw(T![asm]) {
+        p.expect(T!['(']);
+        expr(p);
+        p.expect(T![')']);
+        Some(m.complete(p, ASM_EXPR))
+    } else {
+        m.abandon(p);
+        None
+    }
+}
+
 // test array_expr
 // fn foo() {
 //     [];
@@ -662,19 +698,3 @@ fn try_block_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
     }
     m.complete(p, BLOCK_EXPR)
 }
-
-// test box_expr
-// fn foo() {
-//     let x = box 1i32;
-//     let y = (box 1i32, box 2i32);
-//     let z = Foo(box 1i32, box 2i32);
-// }
-fn box_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
-    assert!(p.at(T![box]));
-    let m = m.unwrap_or_else(|| p.start());
-    p.bump(T![box]);
-    if p.at_ts(EXPR_FIRST) {
-        expr(p);
-    }
-    m.complete(p, BOX_EXPR)
-}
diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs
index e4dce21f32a..36c52953a02 100644
--- a/crates/parser/src/lexed_str.rs
+++ b/crates/parser/src/lexed_str.rs
@@ -221,6 +221,7 @@ impl<'a> Converter<'a> {
                 rustc_lexer::TokenKind::Caret => T![^],
                 rustc_lexer::TokenKind::Percent => T![%],
                 rustc_lexer::TokenKind::Unknown => ERROR,
+                rustc_lexer::TokenKind::UnknownPrefix if token_text == "builtin" => IDENT,
                 rustc_lexer::TokenKind::UnknownPrefix => {
                     err = "unknown literal prefix";
                     IDENT
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index 48f407623d8..3e31e4628bd 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -105,12 +105,16 @@ pub enum SyntaxKind {
     WHILE_KW,
     YIELD_KW,
     AUTO_KW,
+    BUILTIN_KW,
     DEFAULT_KW,
     EXISTENTIAL_KW,
     UNION_KW,
     RAW_KW,
     MACRO_RULES_KW,
     YEET_KW,
+    OFFSET_OF_KW,
+    ASM_KW,
+    FORMAT_ARGS_KW,
     INT_NUMBER,
     FLOAT_NUMBER,
     CHAR,
@@ -203,7 +207,9 @@ pub enum SyntaxKind {
     RECORD_EXPR,
     RECORD_EXPR_FIELD_LIST,
     RECORD_EXPR_FIELD,
-    BOX_EXPR,
+    OFFSET_OF_EXPR,
+    ASM_EXPR,
+    FORMAT_ARGS_EXPR,
     CALL_EXPR,
     INDEX_EXPR,
     METHOD_CALL_EXPR,
@@ -315,12 +321,16 @@ impl SyntaxKind {
                 | WHILE_KW
                 | YIELD_KW
                 | AUTO_KW
+                | BUILTIN_KW
                 | DEFAULT_KW
                 | EXISTENTIAL_KW
                 | UNION_KW
                 | RAW_KW
                 | MACRO_RULES_KW
                 | YEET_KW
+                | OFFSET_OF_KW
+                | ASM_KW
+                | FORMAT_ARGS_KW
         )
     }
     pub fn is_punct(self) -> bool {
@@ -435,12 +445,16 @@ impl SyntaxKind {
     pub fn from_contextual_keyword(ident: &str) -> Option<SyntaxKind> {
         let kw = match ident {
             "auto" => AUTO_KW,
+            "builtin" => BUILTIN_KW,
             "default" => DEFAULT_KW,
             "existential" => EXISTENTIAL_KW,
             "union" => UNION_KW,
             "raw" => RAW_KW,
             "macro_rules" => MACRO_RULES_KW,
             "yeet" => YEET_KW,
+            "offset_of" => OFFSET_OF_KW,
+            "asm" => ASM_KW,
+            "format_args" => FORMAT_ARGS_KW,
             _ => return None,
         };
         Some(kw)
@@ -481,5 +495,5 @@ impl SyntaxKind {
     }
 }
 #[macro_export]
-macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
+macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
 pub use T;
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index ea7ebd85b33..bd9d2ad1784 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -340,10 +340,10 @@ ExprStmt =
 
 Expr =
   ArrayExpr
+| AsmExpr
 | AwaitExpr
 | BinExpr
 | BlockExpr
-| BoxExpr
 | BreakExpr
 | CallExpr
 | CastExpr
@@ -351,6 +351,7 @@ Expr =
 | ContinueExpr
 | FieldExpr
 | ForExpr
+| FormatArgsExpr
 | IfExpr
 | IndexExpr
 | Literal
@@ -358,6 +359,7 @@ Expr =
 | MacroExpr
 | MatchExpr
 | MethodCallExpr
+| OffsetOfExpr
 | ParenExpr
 | PathExpr
 | PrefixExpr
@@ -373,6 +375,15 @@ Expr =
 | LetExpr
 | UnderscoreExpr
 
+OffsetOfExpr =
+  Attr* 'builtin' '#' 'offset_of' '(' ')'
+
+AsmExpr =
+  Attr* 'builtin' '#' 'asm' '(' ')'
+
+FormatArgsExpr =
+  Attr* 'builtin' '#' 'format_args' '(' ')'
+
 MacroExpr =
   MacroCall
 
@@ -526,9 +537,6 @@ UnderscoreExpr =
 AwaitExpr =
   Attr* Expr '.' 'await'
 
-BoxExpr =
-  Attr* 'box' Expr
-
 //*************************//
 //          Types          //
 //*************************//
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 16448db04f8..82b9c28a566 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -805,6 +805,19 @@ impl ArrayExpr {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct AsmExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::HasAttrs for AsmExpr {}
+impl AsmExpr {
+    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn asm_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![asm]) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct AwaitExpr {
     pub(crate) syntax: SyntaxNode,
 }
@@ -823,16 +836,6 @@ impl ast::HasAttrs for BinExpr {}
 impl BinExpr {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BoxExpr {
-    pub(crate) syntax: SyntaxNode,
-}
-impl ast::HasAttrs for BoxExpr {}
-impl BoxExpr {
-    pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct BreakExpr {
     pub(crate) syntax: SyntaxNode,
 }
@@ -916,6 +919,21 @@ impl ForExpr {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FormatArgsExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::HasAttrs for FormatArgsExpr {}
+impl FormatArgsExpr {
+    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn format_args_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![format_args])
+    }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct IfExpr {
     pub(crate) syntax: SyntaxNode,
 }
@@ -985,6 +1003,21 @@ impl MethodCallExpr {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct OffsetOfExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::HasAttrs for OffsetOfExpr {}
+impl OffsetOfExpr {
+    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn offset_of_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![offset_of])
+    }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct ParenExpr {
     pub(crate) syntax: SyntaxNode,
 }
@@ -1555,10 +1588,10 @@ pub enum Type {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Expr {
     ArrayExpr(ArrayExpr),
+    AsmExpr(AsmExpr),
     AwaitExpr(AwaitExpr),
     BinExpr(BinExpr),
     BlockExpr(BlockExpr),
-    BoxExpr(BoxExpr),
     BreakExpr(BreakExpr),
     CallExpr(CallExpr),
     CastExpr(CastExpr),
@@ -1566,6 +1599,7 @@ pub enum Expr {
     ContinueExpr(ContinueExpr),
     FieldExpr(FieldExpr),
     ForExpr(ForExpr),
+    FormatArgsExpr(FormatArgsExpr),
     IfExpr(IfExpr),
     IndexExpr(IndexExpr),
     Literal(Literal),
@@ -1573,6 +1607,7 @@ pub enum Expr {
     MacroExpr(MacroExpr),
     MatchExpr(MatchExpr),
     MethodCallExpr(MethodCallExpr),
+    OffsetOfExpr(OffsetOfExpr),
     ParenExpr(ParenExpr),
     PathExpr(PathExpr),
     PrefixExpr(PrefixExpr),
@@ -2453,8 +2488,8 @@ impl AstNode for ArrayExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for AwaitExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR }
+impl AstNode for AsmExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2464,8 +2499,8 @@ impl AstNode for AwaitExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for BinExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR }
+impl AstNode for AwaitExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2475,8 +2510,8 @@ impl AstNode for BinExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for BoxExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_EXPR }
+impl AstNode for BinExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2563,6 +2598,17 @@ impl AstNode for ForExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl AstNode for FormatArgsExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FORMAT_ARGS_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
 impl AstNode for IfExpr {
     fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2640,6 +2686,17 @@ impl AstNode for MethodCallExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl AstNode for OffsetOfExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == OFFSET_OF_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
 impl AstNode for ParenExpr {
     fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3373,6 +3430,9 @@ impl AstNode for Type {
 impl From<ArrayExpr> for Expr {
     fn from(node: ArrayExpr) -> Expr { Expr::ArrayExpr(node) }
 }
+impl From<AsmExpr> for Expr {
+    fn from(node: AsmExpr) -> Expr { Expr::AsmExpr(node) }
+}
 impl From<AwaitExpr> for Expr {
     fn from(node: AwaitExpr) -> Expr { Expr::AwaitExpr(node) }
 }
@@ -3382,9 +3442,6 @@ impl From<BinExpr> for Expr {
 impl From<BlockExpr> for Expr {
     fn from(node: BlockExpr) -> Expr { Expr::BlockExpr(node) }
 }
-impl From<BoxExpr> for Expr {
-    fn from(node: BoxExpr) -> Expr { Expr::BoxExpr(node) }
-}
 impl From<BreakExpr> for Expr {
     fn from(node: BreakExpr) -> Expr { Expr::BreakExpr(node) }
 }
@@ -3406,6 +3463,9 @@ impl From<FieldExpr> for Expr {
 impl From<ForExpr> for Expr {
     fn from(node: ForExpr) -> Expr { Expr::ForExpr(node) }
 }
+impl From<FormatArgsExpr> for Expr {
+    fn from(node: FormatArgsExpr) -> Expr { Expr::FormatArgsExpr(node) }
+}
 impl From<IfExpr> for Expr {
     fn from(node: IfExpr) -> Expr { Expr::IfExpr(node) }
 }
@@ -3427,6 +3487,9 @@ impl From<MatchExpr> for Expr {
 impl From<MethodCallExpr> for Expr {
     fn from(node: MethodCallExpr) -> Expr { Expr::MethodCallExpr(node) }
 }
+impl From<OffsetOfExpr> for Expr {
+    fn from(node: OffsetOfExpr) -> Expr { Expr::OffsetOfExpr(node) }
+}
 impl From<ParenExpr> for Expr {
     fn from(node: ParenExpr) -> Expr { Expr::ParenExpr(node) }
 }
@@ -3474,10 +3537,10 @@ impl AstNode for Expr {
         matches!(
             kind,
             ARRAY_EXPR
+                | ASM_EXPR
                 | AWAIT_EXPR
                 | BIN_EXPR
                 | BLOCK_EXPR
-                | BOX_EXPR
                 | BREAK_EXPR
                 | CALL_EXPR
                 | CAST_EXPR
@@ -3485,6 +3548,7 @@ impl AstNode for Expr {
                 | CONTINUE_EXPR
                 | FIELD_EXPR
                 | FOR_EXPR
+                | FORMAT_ARGS_EXPR
                 | IF_EXPR
                 | INDEX_EXPR
                 | LITERAL
@@ -3492,6 +3556,7 @@ impl AstNode for Expr {
                 | MACRO_EXPR
                 | MATCH_EXPR
                 | METHOD_CALL_EXPR
+                | OFFSET_OF_EXPR
                 | PAREN_EXPR
                 | PATH_EXPR
                 | PREFIX_EXPR
@@ -3511,10 +3576,10 @@ impl AstNode for Expr {
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
             ARRAY_EXPR => Expr::ArrayExpr(ArrayExpr { syntax }),
+            ASM_EXPR => Expr::AsmExpr(AsmExpr { syntax }),
             AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
             BIN_EXPR => Expr::BinExpr(BinExpr { syntax }),
             BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }),
-            BOX_EXPR => Expr::BoxExpr(BoxExpr { syntax }),
             BREAK_EXPR => Expr::BreakExpr(BreakExpr { syntax }),
             CALL_EXPR => Expr::CallExpr(CallExpr { syntax }),
             CAST_EXPR => Expr::CastExpr(CastExpr { syntax }),
@@ -3522,6 +3587,7 @@ impl AstNode for Expr {
             CONTINUE_EXPR => Expr::ContinueExpr(ContinueExpr { syntax }),
             FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
             FOR_EXPR => Expr::ForExpr(ForExpr { syntax }),
+            FORMAT_ARGS_EXPR => Expr::FormatArgsExpr(FormatArgsExpr { syntax }),
             IF_EXPR => Expr::IfExpr(IfExpr { syntax }),
             INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
             LITERAL => Expr::Literal(Literal { syntax }),
@@ -3529,6 +3595,7 @@ impl AstNode for Expr {
             MACRO_EXPR => Expr::MacroExpr(MacroExpr { syntax }),
             MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
             METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
+            OFFSET_OF_EXPR => Expr::OffsetOfExpr(OffsetOfExpr { syntax }),
             PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }),
             PATH_EXPR => Expr::PathExpr(PathExpr { syntax }),
             PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
@@ -3550,10 +3617,10 @@ impl AstNode for Expr {
     fn syntax(&self) -> &SyntaxNode {
         match self {
             Expr::ArrayExpr(it) => &it.syntax,
+            Expr::AsmExpr(it) => &it.syntax,
             Expr::AwaitExpr(it) => &it.syntax,
             Expr::BinExpr(it) => &it.syntax,
             Expr::BlockExpr(it) => &it.syntax,
-            Expr::BoxExpr(it) => &it.syntax,
             Expr::BreakExpr(it) => &it.syntax,
             Expr::CallExpr(it) => &it.syntax,
             Expr::CastExpr(it) => &it.syntax,
@@ -3561,6 +3628,7 @@ impl AstNode for Expr {
             Expr::ContinueExpr(it) => &it.syntax,
             Expr::FieldExpr(it) => &it.syntax,
             Expr::ForExpr(it) => &it.syntax,
+            Expr::FormatArgsExpr(it) => &it.syntax,
             Expr::IfExpr(it) => &it.syntax,
             Expr::IndexExpr(it) => &it.syntax,
             Expr::Literal(it) => &it.syntax,
@@ -3568,6 +3636,7 @@ impl AstNode for Expr {
             Expr::MacroExpr(it) => &it.syntax,
             Expr::MatchExpr(it) => &it.syntax,
             Expr::MethodCallExpr(it) => &it.syntax,
+            Expr::OffsetOfExpr(it) => &it.syntax,
             Expr::ParenExpr(it) => &it.syntax,
             Expr::PathExpr(it) => &it.syntax,
             Expr::PrefixExpr(it) => &it.syntax,
@@ -4028,9 +4097,9 @@ impl AstNode for AnyHasAttrs {
                 | TYPE_PARAM
                 | LET_STMT
                 | ARRAY_EXPR
+                | ASM_EXPR
                 | AWAIT_EXPR
                 | BIN_EXPR
-                | BOX_EXPR
                 | BREAK_EXPR
                 | CALL_EXPR
                 | CAST_EXPR
@@ -4038,12 +4107,14 @@ impl AstNode for AnyHasAttrs {
                 | CONTINUE_EXPR
                 | FIELD_EXPR
                 | FOR_EXPR
+                | FORMAT_ARGS_EXPR
                 | IF_EXPR
                 | INDEX_EXPR
                 | LITERAL
                 | LOOP_EXPR
                 | MATCH_EXPR
                 | METHOD_CALL_EXPR
+                | OFFSET_OF_EXPR
                 | PAREN_EXPR
                 | PATH_EXPR
                 | PREFIX_EXPR
@@ -4620,17 +4691,17 @@ impl std::fmt::Display for ArrayExpr {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for AwaitExpr {
+impl std::fmt::Display for AsmExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for BinExpr {
+impl std::fmt::Display for AwaitExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for BoxExpr {
+impl std::fmt::Display for BinExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
@@ -4670,6 +4741,11 @@ impl std::fmt::Display for ForExpr {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for FormatArgsExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for IfExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -4705,6 +4781,11 @@ impl std::fmt::Display for MethodCallExpr {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for OffsetOfExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for ParenExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/ast/prec.rs b/crates/syntax/src/ast/prec.rs
index 4ec388914e6..8e04ab8bedc 100644
--- a/crates/syntax/src/ast/prec.rs
+++ b/crates/syntax/src/ast/prec.rs
@@ -130,7 +130,8 @@ impl Expr {
             //
             ContinueExpr(_) => (0, 0),
 
-            ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) | BreakExpr(_) => (0, 1),
+            ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) | BreakExpr(_)
+            | OffsetOfExpr(_) | FormatArgsExpr(_) | AsmExpr(_) => (0, 1),
 
             RangeExpr(_) => (5, 5),
 
@@ -160,7 +161,7 @@ impl Expr {
 
             CastExpr(_) => (25, 26),
 
-            BoxExpr(_) | RefExpr(_) | LetExpr(_) | PrefixExpr(_) => (0, 27),
+            RefExpr(_) | LetExpr(_) | PrefixExpr(_) => (0, 27),
 
             AwaitExpr(_) | CallExpr(_) | MethodCallExpr(_) | IndexExpr(_) | TryExpr(_)
             | MacroExpr(_) => (29, 0),
@@ -202,7 +203,6 @@ impl Expr {
             let rhs = match self {
                 RefExpr(e) => e.expr(),
                 BinExpr(e) => e.rhs(),
-                BoxExpr(e) => e.expr(),
                 BreakExpr(e) => e.expr(),
                 LetExpr(e) => e.expr(),
                 RangeExpr(e) => e.end(),
@@ -279,7 +279,6 @@ impl Expr {
                 CastExpr(e) => e.as_token(),
                 FieldExpr(e) => e.dot_token(),
                 AwaitExpr(e) => e.dot_token(),
-                BoxExpr(e) => e.box_token(),
                 BreakExpr(e) => e.break_token(),
                 CallExpr(e) => e.arg_list().and_then(|args| args.l_paren_token()),
                 ClosureExpr(e) => e.param_list().and_then(|params| params.l_paren_token()),
@@ -293,7 +292,9 @@ impl Expr {
                 YieldExpr(e) => e.yield_token(),
                 YeetExpr(e) => e.do_token(),
                 LetExpr(e) => e.let_token(),
-
+                OffsetOfExpr(e) => e.builtin_token(),
+                FormatArgsExpr(e) => e.builtin_token(),
+                AsmExpr(e) => e.builtin_token(),
                 ArrayExpr(_) | TupleExpr(_) | Literal(_) | PathExpr(_) | ParenExpr(_)
                 | IfExpr(_) | WhileExpr(_) | ForExpr(_) | LoopExpr(_) | MatchExpr(_)
                 | BlockExpr(_) | RecordExpr(_) | UnderscoreExpr(_) | MacroExpr(_) => None,
@@ -310,12 +311,12 @@ impl Expr {
             ArrayExpr(_) | AwaitExpr(_) | BlockExpr(_) | CallExpr(_) | CastExpr(_)
             | ClosureExpr(_) | FieldExpr(_) | IndexExpr(_) | Literal(_) | LoopExpr(_)
             | MacroExpr(_) | MethodCallExpr(_) | ParenExpr(_) | PathExpr(_) | RecordExpr(_)
-            | TryExpr(_) | TupleExpr(_) | UnderscoreExpr(_) => false,
+            | TryExpr(_) | TupleExpr(_) | UnderscoreExpr(_) | OffsetOfExpr(_)
+            | FormatArgsExpr(_) | AsmExpr(_) => false,
 
             // For BinExpr and RangeExpr this is technically wrong -- the child can be on the left...
-            BinExpr(_) | RangeExpr(_) | BoxExpr(_) | BreakExpr(_) | ContinueExpr(_)
-            | PrefixExpr(_) | RefExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_)
-            | LetExpr(_) => self
+            BinExpr(_) | RangeExpr(_) | BreakExpr(_) | ContinueExpr(_) | PrefixExpr(_)
+            | RefExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) | LetExpr(_) => self
                 .syntax()
                 .parent()
                 .and_then(Expr::cast)
diff --git a/crates/syntax/src/tests/ast_src.rs b/crates/syntax/src/tests/ast_src.rs
index e4db33f1c69..2c1d832d1e5 100644
--- a/crates/syntax/src/tests/ast_src.rs
+++ b/crates/syntax/src/tests/ast_src.rs
@@ -70,7 +70,19 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc {
         "match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct",
         "super", "trait", "true", "try", "type", "unsafe", "use", "where", "while", "yield",
     ],
-    contextual_keywords: &["auto", "default", "existential", "union", "raw", "macro_rules", "yeet"],
+    contextual_keywords: &[
+        "auto",
+        "builtin",
+        "default",
+        "existential",
+        "union",
+        "raw",
+        "macro_rules",
+        "yeet",
+        "offset_of",
+        "asm",
+        "format_args",
+    ],
     literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING", "C_STRING"],
     tokens: &["ERROR", "IDENT", "WHITESPACE", "LIFETIME_IDENT", "COMMENT", "SHEBANG"],
     nodes: &[
@@ -154,7 +166,9 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc {
         "RECORD_EXPR",
         "RECORD_EXPR_FIELD_LIST",
         "RECORD_EXPR_FIELD",
-        "BOX_EXPR",
+        "OFFSET_OF_EXPR",
+        "ASM_EXPR",
+        "FORMAT_ARGS_EXPR",
         // postfix
         "CALL_EXPR",
         "INDEX_EXPR",