Skip to content

Commit caeea45

Browse files
committed
Auto merge of #15557 - Veykril:builtin-syntax, r=Veykril
Parse builtin# syntax and add typechecking for builtin#offset_of expression Also removes box syntax, fixes #14504 cc rust-lang/compiler-team#580 #15082
2 parents 2df30e1 + 3431d58 commit caeea45

File tree

30 files changed

+465
-265
lines changed

30 files changed

+465
-265
lines changed

crates/hir-def/src/body/lower.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use crate::{
3030
expander::Expander,
3131
hir::{
3232
dummy_expr_id, Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy,
33-
ClosureKind, Expr, ExprId, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability,
34-
Pat, PatId, RecordFieldPat, RecordLitField, Statement,
33+
ClosureKind, Expr, ExprId, InlineAsm, Label, LabelId, Literal, LiteralOrConst, MatchArm,
34+
Movability, OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
3535
},
3636
item_scope::BuiltinShadowMode,
3737
lang_item::LangItem,
@@ -579,11 +579,6 @@ impl ExprCollector<'_> {
579579
syntax_ptr,
580580
)
581581
}
582-
ast::Expr::BoxExpr(e) => {
583-
let expr = self.collect_expr_opt(e.expr());
584-
self.alloc_expr(Expr::Box { expr }, syntax_ptr)
585-
}
586-
587582
ast::Expr::ArrayExpr(e) => {
588583
let kind = e.kind();
589584

@@ -653,6 +648,16 @@ impl ExprCollector<'_> {
653648
}
654649
}
655650
ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
651+
ast::Expr::AsmExpr(e) => {
652+
let expr = Expr::InlineAsm(InlineAsm { e: self.collect_expr_opt(e.expr()) });
653+
self.alloc_expr(expr, syntax_ptr)
654+
}
655+
ast::Expr::OffsetOfExpr(e) => {
656+
let container = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
657+
let fields = e.fields().map(|it| it.as_name()).collect();
658+
self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr)
659+
}
660+
ast::Expr::FormatArgsExpr(_) => self.missing_expr(),
656661
})
657662
}
658663

@@ -663,6 +668,7 @@ impl ExprCollector<'_> {
663668
let result_expr_id = self.alloc_expr(Expr::Missing, syntax_ptr);
664669
let prev_binding_owner = self.current_binding_owner.take();
665670
self.current_binding_owner = Some(result_expr_id);
671+
666672
(result_expr_id, prev_binding_owner)
667673
}
668674

crates/hir-def/src/body/pretty.rs

+11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::fmt::{self, Write};
44

55
use hir_expand::db::ExpandDatabase;
6+
use itertools::Itertools;
67
use syntax::ast::HasName;
78

89
use crate::{
@@ -154,6 +155,16 @@ impl Printer<'_> {
154155
match expr {
155156
Expr::Missing => w!(self, "�"),
156157
Expr::Underscore => w!(self, "_"),
158+
Expr::InlineAsm(_) => w!(self, "builtin#asm(_)"),
159+
Expr::OffsetOf(offset_of) => {
160+
w!(self, "builtin#offset_of(");
161+
self.print_type_ref(&offset_of.container);
162+
w!(
163+
self,
164+
", {})",
165+
offset_of.fields.iter().format_with(".", |field, f| f(&field.display(self.db)))
166+
);
167+
}
157168
Expr::Path(path) => self.print_path(path),
158169
Expr::If { condition, then_branch, else_branch } => {
159170
w!(self, "if ");

crates/hir-def/src/hir.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,19 @@ pub enum Expr {
281281
Array(Array),
282282
Literal(Literal),
283283
Underscore,
284+
OffsetOf(OffsetOf),
285+
InlineAsm(InlineAsm),
286+
}
287+
288+
#[derive(Debug, Clone, PartialEq, Eq)]
289+
pub struct OffsetOf {
290+
pub container: Interned<TypeRef>,
291+
pub fields: Box<[Name]>,
292+
}
293+
294+
#[derive(Debug, Clone, PartialEq, Eq)]
295+
pub struct InlineAsm {
296+
pub e: ExprId,
284297
}
285298

286299
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -341,7 +354,8 @@ impl Expr {
341354
pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
342355
match self {
343356
Expr::Missing => {}
344-
Expr::Path(_) => {}
357+
Expr::Path(_) | Expr::OffsetOf(_) => {}
358+
Expr::InlineAsm(e) => f(e.e),
345359
Expr::If { condition, then_branch, else_branch } => {
346360
f(*condition);
347361
f(*then_branch);

crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs

+39
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,45 @@ fn main() { 0 as u32; }
2222
);
2323
}
2424

25+
#[test]
26+
fn test_asm_expand() {
27+
check(
28+
r#"
29+
#[rustc_builtin_macro]
30+
macro_rules! asm {() => {}}
31+
32+
fn main() {
33+
let i: u64 = 3;
34+
let o: u64;
35+
unsafe {
36+
asm!(
37+
"mov {0}, {1}",
38+
"add {0}, 5",
39+
out(reg) o,
40+
in(reg) i,
41+
);
42+
}
43+
}
44+
"#,
45+
expect![[r##"
46+
#[rustc_builtin_macro]
47+
macro_rules! asm {() => {}}
48+
49+
fn main() {
50+
let i: u64 = 3;
51+
let o: u64;
52+
unsafe {
53+
builtin #asm ( {
54+
$crate::format_args!("mov {0}, {1}");
55+
$crate::format_args!("add {0}, 5");
56+
}
57+
);
58+
}
59+
}
60+
"##]],
61+
);
62+
}
63+
2564
#[test]
2665
fn test_line_expand() {
2766
check(

crates/hir-expand/src/builtin_fn_macro.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ fn asm_expand(
399399
_id: MacroCallId,
400400
tt: &tt::Subtree,
401401
) -> ExpandResult<tt::Subtree> {
402+
// FIXME: parse asm here
403+
402404
// We expand all assembly snippets to `format_args!` invocations to get format syntax
403405
// highlighting for them.
404406

@@ -415,10 +417,12 @@ fn asm_expand(
415417
}
416418
}
417419

418-
let expanded = quote! {{
419-
##literals
420-
loop {}
421-
}};
420+
let pound = quote! {@PUNCT '#'};
421+
let expanded = quote! {
422+
builtin #pound asm (
423+
{##literals}
424+
)
425+
};
422426
ExpandResult::ok(expanded)
423427
}
424428

crates/hir-ty/src/infer/closure.rs

+3
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ impl InferenceContext<'_> {
452452

453453
fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
454454
match &self.body[tgt_expr] {
455+
Expr::OffsetOf(_) => (),
456+
Expr::InlineAsm(e) => self.walk_expr_without_adjust(e.e),
455457
Expr::If { condition, then_branch, else_branch } => {
456458
self.consume_expr(*condition);
457459
self.consume_expr(*then_branch);
@@ -620,6 +622,7 @@ impl InferenceContext<'_> {
620622
| Expr::Tuple { exprs, is_assignee_expr: _ } => {
621623
self.consume_exprs(exprs.iter().copied())
622624
}
625+
623626
Expr::Missing
624627
| Expr::Continue { .. }
625628
| Expr::Path(_)

crates/hir-ty/src/infer/expr.rs

+5
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,11 @@ impl InferenceContext<'_> {
843843
});
844844
expected
845845
}
846+
Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
847+
Expr::InlineAsm(it) => {
848+
self.infer_expr_no_expect(it.e);
849+
self.result.standard_types.unit.clone()
850+
}
846851
};
847852
// use a new type variable if we got unknown here
848853
let ty = self.insert_type_vars_shallow(ty);

crates/hir-ty/src/infer/mutability.rs

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ impl InferenceContext<'_> {
3535
fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutability) {
3636
match &self.body[tgt_expr] {
3737
Expr::Missing => (),
38+
Expr::InlineAsm(e) => self.infer_mut_expr_without_adjust(e.e, Mutability::Not),
39+
Expr::OffsetOf(_) => (),
3840
&Expr::If { condition, then_branch, else_branch } => {
3941
self.infer_mut_expr(condition, Mutability::Not);
4042
self.infer_mut_expr(then_branch, Mutability::Not);

crates/hir-ty/src/mir/lower.rs

+6
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
370370
mut current: BasicBlockId,
371371
) -> Result<Option<BasicBlockId>> {
372372
match &self.body.exprs[expr_id] {
373+
Expr::OffsetOf(_) => {
374+
not_supported!("builtin#offset_of")
375+
}
376+
Expr::InlineAsm(_) => {
377+
not_supported!("builtin#asm")
378+
}
373379
Expr::Missing => {
374380
if let DefWithBodyId::FunctionId(f) = self.owner {
375381
let assoc = f.lookup(self.db.upcast());

crates/hir-ty/src/tests/simple.rs

+26-63
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,6 @@ use expect_test::expect;
22

33
use super::{check, check_infer, check_no_mismatches, check_types};
44

5-
#[test]
6-
fn infer_box() {
7-
check_types(
8-
r#"
9-
//- /main.rs crate:main deps:std
10-
fn test() {
11-
let x = box 1;
12-
let t = (x, box x, box &1, box [1]);
13-
t;
14-
} //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; 1]>)
15-
16-
//- /std.rs crate:std
17-
#[prelude_import] use prelude::*;
18-
mod prelude {}
19-
20-
mod boxed {
21-
#[lang = "owned_box"]
22-
pub struct Box<T: ?Sized> {
23-
inner: *mut T,
24-
}
25-
}
26-
"#,
27-
);
28-
}
29-
30-
#[test]
31-
fn infer_box_with_allocator() {
32-
check_types(
33-
r#"
34-
//- /main.rs crate:main deps:std
35-
fn test() {
36-
let x = box 1;
37-
let t = (x, box x, box &1, box [1]);
38-
t;
39-
} //^ (Box<i32, {unknown}>, Box<Box<i32, {unknown}>, {unknown}>, Box<&i32, {unknown}>, Box<[i32; 1], {unknown}>)
40-
41-
//- /std.rs crate:std
42-
#[prelude_import] use prelude::*;
43-
mod boxed {
44-
#[lang = "owned_box"]
45-
pub struct Box<T: ?Sized, A: Allocator> {
46-
inner: *mut T,
47-
allocator: A,
48-
}
49-
}
50-
"#,
51-
);
52-
}
53-
545
#[test]
556
fn infer_adt_self() {
567
check_types(
@@ -2763,8 +2714,8 @@ impl<T> [T] {
27632714
}
27642715
27652716
fn test() {
2766-
let vec = <[_]>::into_vec(box [1i32]);
2767-
let v: Vec<Box<dyn B>> = <[_]> :: into_vec(box [box Astruct]);
2717+
let vec = <[_]>::into_vec(#[rustc_box] Box::new([1i32]));
2718+
let v: Vec<Box<dyn B>> = <[_]> :: into_vec(#[rustc_box] Box::new([#[rustc_box] Box::new(Astruct)]));
27682719
}
27692720
27702721
trait B{}
@@ -2774,20 +2725,20 @@ impl B for Astruct {}
27742725
expect![[r#"
27752726
604..608 'self': Box<[T], A>
27762727
637..669 '{ ... }': Vec<T, A>
2777-
683..796 '{ ...t]); }': ()
2728+
683..853 '{ ...])); }': ()
27782729
693..696 'vec': Vec<i32, Global>
27792730
699..714 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global>
2780-
699..726 '<[_]>:...1i32])': Vec<i32, Global>
2781-
715..725 'box [1i32]': Box<[i32; 1], Global>
2782-
719..725 '[1i32]': [i32; 1]
2783-
720..724 '1i32': i32
2784-
736..737 'v': Vec<Box<dyn B, Global>, Global>
2785-
757..774 '<[_]> ...to_vec': fn into_vec<Box<dyn B, Global>, Global>(Box<[Box<dyn B, Global>], Global>) -> Vec<Box<dyn B, Global>, Global>
2786-
757..793 '<[_]> ...ruct])': Vec<Box<dyn B, Global>, Global>
2787-
775..792 'box [b...truct]': Box<[Box<dyn B, Global>; 1], Global>
2788-
779..792 '[box Astruct]': [Box<dyn B, Global>; 1]
2789-
780..791 'box Astruct': Box<Astruct, Global>
2790-
784..791 'Astruct': Astruct
2731+
699..745 '<[_]>:...i32]))': Vec<i32, Global>
2732+
715..744 '#[rust...1i32])': Box<[i32; 1], Global>
2733+
737..743 '[1i32]': [i32; 1]
2734+
738..742 '1i32': i32
2735+
755..756 'v': Vec<Box<dyn B, Global>, Global>
2736+
776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B, Global>, Global>(Box<[Box<dyn B, Global>], Global>) -> Vec<Box<dyn B, Global>, Global>
2737+
776..850 '<[_]> ...ct)]))': Vec<Box<dyn B, Global>, Global>
2738+
794..849 '#[rust...uct)])': Box<[Box<dyn B, Global>; 1], Global>
2739+
816..848 '[#[rus...ruct)]': [Box<dyn B, Global>; 1]
2740+
817..847 '#[rust...truct)': Box<Astruct, Global>
2741+
839..846 'Astruct': Astruct
27912742
"#]],
27922743
)
27932744
}
@@ -3649,3 +3600,15 @@ fn main() {
36493600
"#,
36503601
);
36513602
}
3603+
3604+
#[test]
3605+
fn offset_of() {
3606+
check_types(
3607+
r#"
3608+
fn main() {
3609+
builtin#offset_of((,), 0);
3610+
// ^^^^^^^^^^^^^^^^^^^^^^^^^ usize
3611+
}
3612+
"#,
3613+
);
3614+
}

0 commit comments

Comments
 (0)