Skip to content

Commit 5e2cf56

Browse files
author
Grant Wuerker
committed
unsafe block
1 parent 65f3804 commit 5e2cf56

File tree

15 files changed

+281
-11
lines changed

15 files changed

+281
-11
lines changed

crates/hir-analysis/src/name_resolution/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> {
425425
expr: ExprId,
426426
expr_data: &Expr,
427427
) {
428-
if matches!(expr_data, Expr::Block(_)) {
428+
if matches!(expr_data, Expr::Block { .. }) {
429429
walk_expr(self, ctxt, expr)
430430
}
431431
}

crates/hir/src/hir_def/body.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl<'db> Visitor for BlockOrderCalculator<'db> {
164164
expr: ExprId,
165165
expr_data: &Expr,
166166
) {
167-
if ctxt.body() == self.body && matches!(expr_data, Expr::Block(..)) {
167+
if ctxt.body() == self.body && matches!(expr_data, Expr::Block { .. }) {
168168
self.order.insert(expr, self.fresh_number);
169169
self.fresh_number += 1;
170170
}

crates/hir/src/hir_def/expr.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use super::{Body, GenericArgListId, IdentId, IntegerId, LitKind, Partial, PatId,
77
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
88
pub enum Expr {
99
Lit(LitKind),
10-
Block(Vec<StmtId>),
10+
Block {
11+
stmts: Vec<StmtId>,
12+
is_unsafe: bool,
13+
},
1114
/// The first `ExprId` is the lhs, the second is the rhs.
1215
///
1316
/// and a `BinOp`.

crates/hir/src/lower/expr.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@ impl Expr {
2929
let stmt = Stmt::push_to_body(ctxt, stmt);
3030
stmts.push(stmt);
3131
}
32-
let expr_id = ctxt.push_expr(Self::Block(stmts), HirOrigin::raw(&ast));
32+
let expr_id = ctxt.push_expr(
33+
Self::Block {
34+
stmts,
35+
is_unsafe: block.unsafe_kw().is_some(),
36+
},
37+
HirOrigin::raw(&ast),
38+
);
3339

3440
for item in block.items() {
3541
ItemKind::lower_ast(ctxt.f_ctxt, item);

crates/hir/src/span/expr.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,14 @@ define_lazy_span_node!(
199199

200200
define_lazy_span_node!(LazyMatchArmSpan);
201201

202+
define_lazy_span_node!(
203+
LazyBlockExprSpan,
204+
ast::BlockExpr,
205+
@token {
206+
(unsafe_kw, unsafe_kw),
207+
}
208+
);
209+
202210
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
203211
pub(crate) struct ExprRoot {
204212
expr: ExprId,

crates/hir/src/visitor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ where
909909
},
910910
),
911911

912-
Expr::Block(stmts) => {
912+
Expr::Block { stmts, .. } => {
913913
let s_graph = ctxt.top_mod().scope_graph(ctxt.db);
914914
let scope = ctxt.scope();
915915
for item in s_graph.child_items(scope) {
@@ -1987,7 +1987,7 @@ where
19871987
/// `scope` is the scope that encloses the expression.
19881988
pub fn with_expr(db: &'db dyn HirDb, scope: ScopeId, body: Body, expr: ExprId) -> Self {
19891989
let scope_id = match expr.data(db, body) {
1990-
Partial::Present(Expr::Block(_)) => ScopeId::Block(body, expr),
1990+
Partial::Present(Expr::Block { .. }) => ScopeId::Block(body, expr),
19911991
_ => scope,
19921992
};
19931993

crates/parser2/src/ast/expr.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ impl BlockExpr {
7474
pub fn items(&self) -> impl Iterator<Item = super::Item> {
7575
support::children(self.syntax())
7676
}
77+
78+
pub fn unsafe_kw(&self) -> Option<SyntaxToken> {
79+
support::token(self.syntax(), SK::UnsafeKw)
80+
}
7781
}
7882

7983
ast_node! {

crates/parser2/src/parser/expr_atom.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub(super) fn parse_expr_atom<S: TokenStream>(
2323
match parser.current_kind() {
2424
Some(IfKw) => parser.parse(IfExprScope::default(), None),
2525
Some(MatchKw) => parser.parse(MatchExprScope::default(), None),
26+
Some(UnsafeKw) => parser.parse(BlockExprScope::default(), None),
2627
Some(LBrace) => parser.parse(BlockExprScope::default(), None),
2728
Some(LParen) => parser.parse(ParenScope::default(), None),
2829
Some(LBracket) => parser.parse(ArrayScope::default(), None),
@@ -53,6 +54,10 @@ define_scope! {
5354
}
5455
impl super::Parse for BlockExprScope {
5556
fn parse<S: TokenStream>(&mut self, parser: &mut Parser<S>) {
57+
if parser.current_kind() == Some(SyntaxKind::UnsafeKw) {
58+
parser.bump_expected(SyntaxKind::UnsafeKw);
59+
}
60+
5661
parser.bump_expected(SyntaxKind::LBrace);
5762

5863
loop {
@@ -62,6 +67,15 @@ impl super::Parse for BlockExprScope {
6267
break;
6368
}
6469

70+
if let (Some(kind_0), Some(kind_1), Some(kind_2)) = parser.peek_three() {
71+
if kind_0 == SyntaxKind::UnsafeKw
72+
&& (kind_1 == SyntaxKind::LBrace || kind_2 == SyntaxKind::LBrace)
73+
{
74+
parser.parse(BlockExprScope::default(), None);
75+
continue;
76+
}
77+
}
78+
6579
if parser
6680
.current_kind()
6781
.map(SyntaxKind::is_item_head)

crates/parser2/src/parser/item.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ impl super::Parse for ItemScope {
7171
fn parse<S: TokenStream>(&mut self, parser: &mut Parser<S>) {
7272
use crate::SyntaxKind::*;
7373

74+
// if parser.peek_two() == (Some(UnsafeKw), Some(LBrace)) {
75+
// parser.parse(BlockExprScope::default(), None);
76+
// return;
77+
// } else {
78+
// println!("{:?}", parser.peek_two(),)
79+
// }
80+
7481
let mut checkpoint = attr::parse_attr_list(parser);
7582
let modifier_scope = ItemModifierScope::default();
7683
let modifier = match parser.current_kind() {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
unsafe { foo() }
2+
3+
unsafe {
4+
let a = 42
5+
std::evm::mstore(offset: 0, value: a)
6+
return
7+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
source: crates/parser2/tests/syntax_node.rs
3+
expression: node
4+
input_file: crates/parser2/test_files/syntax_node/exprs/unsafe.fe
5+
---
6+
Root@0..97
7+
BlockExpr@0..16
8+
UnsafeKw@0..6 "unsafe"
9+
WhiteSpace@6..7 " "
10+
LBrace@7..8 "{"
11+
WhiteSpace@8..9 " "
12+
ExprStmt@9..14
13+
CallExpr@9..14
14+
PathExpr@9..12
15+
Path@9..12
16+
PathSegment@9..12
17+
Ident@9..12 "foo"
18+
CallArgList@12..14
19+
LParen@12..13 "("
20+
RParen@13..14 ")"
21+
WhiteSpace@14..15 " "
22+
RBrace@15..16 "}"
23+
Newline@16..18 "\n\n"
24+
BlockExpr@18..96
25+
UnsafeKw@18..24 "unsafe"
26+
WhiteSpace@24..25 " "
27+
LBrace@25..26 "{"
28+
Newline@26..27 "\n"
29+
WhiteSpace@27..31 " "
30+
LetStmt@31..41
31+
LetKw@31..34 "let"
32+
WhiteSpace@34..35 " "
33+
PathPat@35..36
34+
Path@35..36
35+
PathSegment@35..36
36+
Ident@35..36 "a"
37+
WhiteSpace@36..37 " "
38+
Eq@37..38 "="
39+
WhiteSpace@38..39 " "
40+
LitExpr@39..41
41+
Lit@39..41
42+
Int@39..41 "42"
43+
Newline@41..42 "\n"
44+
WhiteSpace@42..46 " "
45+
ExprStmt@46..83
46+
CallExpr@46..83
47+
PathExpr@46..62
48+
Path@46..62
49+
PathSegment@46..49
50+
Ident@46..49 "std"
51+
Colon2@49..51 "::"
52+
PathSegment@51..54
53+
Ident@51..54 "evm"
54+
Colon2@54..56 "::"
55+
PathSegment@56..62
56+
Ident@56..62 "mstore"
57+
CallArgList@62..83
58+
LParen@62..63 "("
59+
CallArg@63..72
60+
Ident@63..69 "offset"
61+
Colon@69..70 ":"
62+
WhiteSpace@70..71 " "
63+
LitExpr@71..72
64+
Lit@71..72
65+
Int@71..72 "0"
66+
Comma@72..73 ","
67+
WhiteSpace@73..74 " "
68+
CallArg@74..82
69+
Ident@74..79 "value"
70+
Colon@79..80 ":"
71+
WhiteSpace@80..81 " "
72+
PathExpr@81..82
73+
Path@81..82
74+
PathSegment@81..82
75+
Ident@81..82 "a"
76+
RParen@82..83 ")"
77+
Newline@83..84 "\n"
78+
WhiteSpace@84..88 " "
79+
ReturnStmt@88..94
80+
ReturnKw@88..94 "return"
81+
Newline@94..95 "\n"
82+
RBrace@95..96 "}"
83+
Newline@96..97 "\n"
84+

crates/parser2/test_files/syntax_node/items/func.fe

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,25 @@ fn generics1<T: Trait, U>(t: T, u: Option<U>) -> T
1818
t
1919
}
2020

21-
fn decl<T, U>(t: MyStruct<T, U>) -> Result<T, Err> {}
21+
fn decl<T, U>(t: MyStruct<T, U>) -> Result<T, Err> {}
22+
23+
fn foo() {
24+
unsafe {
25+
bar()
26+
}
27+
}
28+
29+
fn foo2() {
30+
unsafe {
31+
bar2()
32+
}
33+
}
34+
35+
// fails due to newlines
36+
// fn foo3() {
37+
// unsafe
38+
39+
// {
40+
// bar3()
41+
// }
42+
// }

crates/parser2/test_files/syntax_node/items/func.snap

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ source: crates/parser2/tests/syntax_node.rs
33
expression: node
44
input_file: crates/parser2/test_files/syntax_node/items/func.fe
55
---
6-
Root@0..361
7-
ItemList@0..361
6+
Root@0..561
7+
ItemList@0..462
88
Item@0..32
99
Func@0..30
1010
ItemModifier@0..3
@@ -282,7 +282,7 @@ Root@0..361
282282
Newline@304..305 "\n"
283283
RBrace@305..306 "}"
284284
Newline@306..308 "\n\n"
285-
Item@308..361
285+
Item@308..363
286286
Func@308..361
287287
FnKw@308..310 "fn"
288288
WhiteSpace@310..311 " "
@@ -348,4 +348,88 @@ Root@0..361
348348
BlockExpr@359..361
349349
LBrace@359..360 "{"
350350
RBrace@360..361 "}"
351+
Newline@361..363 "\n\n"
352+
Item@363..410
353+
Func@363..408
354+
FnKw@363..365 "fn"
355+
WhiteSpace@365..366 " "
356+
Ident@366..369 "foo"
357+
FuncParamList@369..371
358+
LParen@369..370 "("
359+
RParen@370..371 ")"
360+
WhiteSpace@371..372 " "
361+
BlockExpr@372..408
362+
LBrace@372..373 "{"
363+
Newline@373..374 "\n"
364+
WhiteSpace@374..378 " "
365+
BlockExpr@378..406
366+
UnsafeKw@378..384 "unsafe"
367+
WhiteSpace@384..385 " "
368+
LBrace@385..386 "{"
369+
Newline@386..387 "\n"
370+
WhiteSpace@387..395 " "
371+
ExprStmt@395..400
372+
CallExpr@395..400
373+
PathExpr@395..398
374+
Path@395..398
375+
PathSegment@395..398
376+
Ident@395..398 "bar"
377+
CallArgList@398..400
378+
LParen@398..399 "("
379+
RParen@399..400 ")"
380+
Newline@400..401 "\n"
381+
WhiteSpace@401..405 " "
382+
RBrace@405..406 "}"
383+
Newline@406..407 "\n"
384+
RBrace@407..408 "}"
385+
Newline@408..410 "\n\n"
386+
Item@410..462
387+
Func@410..460
388+
FnKw@410..412 "fn"
389+
WhiteSpace@412..413 " "
390+
Ident@413..417 "foo2"
391+
FuncParamList@417..419
392+
LParen@417..418 "("
393+
RParen@418..419 ")"
394+
WhiteSpace@419..420 " "
395+
BlockExpr@420..460
396+
LBrace@420..421 "{"
397+
Newline@421..422 "\n"
398+
WhiteSpace@422..426 " "
399+
BlockExpr@426..458
400+
UnsafeKw@426..432 "unsafe"
401+
WhiteSpace@432..436 " "
402+
LBrace@436..437 "{"
403+
Newline@437..438 "\n"
404+
WhiteSpace@438..446 " "
405+
ExprStmt@446..452
406+
CallExpr@446..452
407+
PathExpr@446..450
408+
Path@446..450
409+
PathSegment@446..450
410+
Ident@446..450 "bar2"
411+
CallArgList@450..452
412+
LParen@450..451 "("
413+
RParen@451..452 ")"
414+
Newline@452..453 "\n"
415+
WhiteSpace@453..457 " "
416+
RBrace@457..458 "}"
417+
Newline@458..459 "\n"
418+
RBrace@459..460 "}"
419+
Newline@460..462 "\n\n"
420+
Comment@462..486 "// fails due to newlines"
421+
Newline@486..487 "\n"
422+
Comment@487..501 "// fn foo3() {"
423+
Newline@501..502 "\n"
424+
Comment@502..515 "// unsafe"
425+
Newline@515..516 "\n"
426+
WhiteSpace@516..520 " "
427+
Newline@520..521 "\n"
428+
Comment@521..529 "// {"
429+
Newline@529..530 "\n"
430+
Comment@530..547 "// bar3()"
431+
Newline@547..548 "\n"
432+
Comment@548..556 "// }"
433+
Newline@556..557 "\n"
434+
Comment@557..561 "// }"
351435

crates/parser2/test_files/syntax_node/stmts/let.fe

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ let x = if b {
2020
let x = match b {
2121
MyEnum::A(x) | MyEnum::B(x) => x
2222
_ => 0
23+
}
24+
25+
let z = unsafe {
26+
foo()
2327
}

0 commit comments

Comments
 (0)