Skip to content

Commit 50e7039

Browse files
authored
Improved block return type to be never in more places. (#7858)
1 parent d8ee40e commit 50e7039

File tree

2 files changed

+205
-13
lines changed

2 files changed

+205
-13
lines changed

crates/cairo-lang-semantic/src/expr/compute.rs

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,19 +1420,7 @@ pub fn compute_expr_block_semantic(
14201420

14211421
// Convert tail expression (if exists) to semantic model.
14221422
let tail_semantic_expr = tail.map(|tail_expr| compute_expr_semantic(new_ctx, &tail_expr));
1423-
let ty = if let Some(t) = &tail_semantic_expr {
1424-
t.ty()
1425-
} else if let Some(statement) = statements_semantic.last() {
1426-
if let Statement::Return(_) | Statement::Break(_) =
1427-
&new_ctx.arenas.statements[*statement]
1428-
{
1429-
never_ty(new_ctx.db)
1430-
} else {
1431-
unit_ty(db)
1432-
}
1433-
} else {
1434-
unit_ty(db)
1435-
};
1423+
let ty = block_ty(new_ctx, &statements_semantic, &tail_semantic_expr);
14361424
Ok(Expr::Block(ExprBlock {
14371425
statements: statements_semantic,
14381426
tail: tail_semantic_expr.map(|expr| expr.id),
@@ -1442,6 +1430,34 @@ pub fn compute_expr_block_semantic(
14421430
})
14431431
}
14441432

1433+
/// The type returned from a block with the given statements and tail.
1434+
fn block_ty(
1435+
ctx: &ComputationContext<'_>,
1436+
statements: &[StatementId],
1437+
tail: &Option<ExprAndId>,
1438+
) -> TypeId {
1439+
if let Some(tail) = tail {
1440+
return tail.ty();
1441+
}
1442+
let Some(statement) = statements
1443+
.iter()
1444+
.rev()
1445+
.map(|id| &ctx.arenas.statements[*id])
1446+
.find(|s| !matches!(s, Statement::Item(_)))
1447+
else {
1448+
return unit_ty(ctx.db);
1449+
};
1450+
match statement {
1451+
Statement::Item(_) => unreachable!("Was previously filtered out."),
1452+
Statement::Let(_) => unit_ty(ctx.db),
1453+
Statement::Return(_) | Statement::Break(_) | Statement::Continue(_) => never_ty(ctx.db),
1454+
Statement::Expr(expr) => {
1455+
let never_ty = never_ty(ctx.db);
1456+
if ctx.arenas.exprs[expr.expr].ty() == never_ty { never_ty } else { unit_ty(ctx.db) }
1457+
}
1458+
}
1459+
}
1460+
14451461
/// Helper for merging the return types of branch blocks (match or if else).
14461462
#[derive(Debug, Clone)]
14471463
struct FlowMergeTypeHelper {

crates/cairo-lang-semantic/src/expr/semantic_test_data/block

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,179 @@ Block(
8686
)
8787

8888
//! > expected_diagnostics
89+
90+
//! > ==========================================================================
91+
92+
//! > Test block with just item.
93+
94+
//! > test_runner_name
95+
test_expr_semantics(expect_diagnostics: false)
96+
97+
//! > expr_code
98+
{
99+
const _X: u8 = 6;
100+
}
101+
102+
//! > expected_semantics
103+
Block(
104+
ExprBlock {
105+
statements: [
106+
Item(
107+
StatementItem,
108+
),
109+
],
110+
tail: None,
111+
ty: (),
112+
},
113+
)
114+
115+
//! > expected_diagnostics
116+
117+
//! > ==========================================================================
118+
119+
//! > Test block with just return.
120+
121+
//! > test_runner_name
122+
test_expr_semantics(expect_diagnostics: false)
123+
124+
//! > expr_code
125+
{
126+
return;
127+
}
128+
129+
//! > expected_semantics
130+
Block(
131+
ExprBlock {
132+
statements: [
133+
Return(
134+
StatementReturn {
135+
expr_option: None,
136+
},
137+
),
138+
],
139+
tail: None,
140+
ty: core::never,
141+
},
142+
)
143+
144+
//! > expected_diagnostics
145+
146+
//! > ==========================================================================
147+
148+
//! > Test block with just return and item, ignoring item.
149+
150+
//! > test_runner_name
151+
test_expr_semantics(expect_diagnostics: false)
152+
153+
//! > expr_code
154+
{
155+
return;
156+
const _X: u8 = 6;
157+
}
158+
159+
//! > expected_semantics
160+
Block(
161+
ExprBlock {
162+
statements: [
163+
Return(
164+
StatementReturn {
165+
expr_option: None,
166+
},
167+
),
168+
Item(
169+
StatementItem,
170+
),
171+
],
172+
tail: None,
173+
ty: core::never,
174+
},
175+
)
176+
177+
//! > expected_diagnostics
178+
179+
//! > ==========================================================================
180+
181+
//! > Test block with just panic.
182+
183+
//! > test_runner_name
184+
test_expr_semantics(expect_diagnostics: false)
185+
186+
//! > expr_code
187+
{
188+
panic_with_felt252('a');
189+
}
190+
191+
//! > expected_semantics
192+
Block(
193+
ExprBlock {
194+
statements: [
195+
Expr(
196+
StatementExpr {
197+
expr: FunctionCall(
198+
ExprFunctionCall {
199+
function: core::panic_with_felt252,
200+
args: [
201+
Value(
202+
Literal(
203+
ExprLiteral {
204+
value: 97,
205+
ty: core::felt252,
206+
},
207+
),
208+
),
209+
],
210+
coupon_arg: None,
211+
ty: core::never,
212+
},
213+
),
214+
},
215+
),
216+
],
217+
tail: None,
218+
ty: core::never,
219+
},
220+
)
221+
222+
//! > expected_diagnostics
223+
224+
//! > ==========================================================================
225+
226+
//! > Test block with just continue.
227+
228+
//! > test_runner_name
229+
test_expr_semantics(expect_diagnostics: false)
230+
231+
//! > expr_code
232+
loop {
233+
{
234+
continue;
235+
}
236+
}
237+
238+
//! > expected_semantics
239+
Loop(
240+
ExprLoop {
241+
body: Block(
242+
ExprBlock {
243+
statements: [],
244+
tail: Some(
245+
Block(
246+
ExprBlock {
247+
statements: [
248+
Continue(
249+
StatementContinue,
250+
),
251+
],
252+
tail: None,
253+
ty: core::never,
254+
},
255+
),
256+
),
257+
ty: (),
258+
},
259+
),
260+
ty: core::never,
261+
},
262+
)
263+
264+
//! > expected_diagnostics

0 commit comments

Comments
 (0)