Skip to content

Commit e95ed36

Browse files
committed
Fix #521
1 parent 6bb21f7 commit e95ed36

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

crates/emmylua_code_analysis/src/compilation/test/array_test.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,22 @@ mod test {
5050
let t_expected = ws.ty("integer[]");
5151
assert_eq!(t, t_expected)
5252
}
53+
54+
#[test]
55+
fn test_array_for_flow() {
56+
let mut ws = VirtualWorkspace::new();
57+
assert!(ws.check_code_for(
58+
DiagnosticCode::NeedCheckNil,
59+
r#"
60+
--- @param _x string
61+
local function foo(_x) end
62+
63+
local list = {} --- @type string[]
64+
65+
for i = #list, 1, -1 do
66+
foo(list[i])
67+
end
68+
"#,
69+
));
70+
}
5371
}

crates/emmylua_code_analysis/src/semantic/infer/infer_index.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,18 +285,42 @@ fn check_iter_var_range(
285285
let token = decl_syntax_id.to_token_from_root(&root)?;
286286
let parent_node = token.parent()?;
287287
let for_stat = LuaForStat::cast(parent_node)?;
288-
// get second expr
289-
let test_len_expr = for_stat.get_iter_expr().skip(1).next()?;
290-
let LuaExpr::UnaryExpr(unary_expr) = test_len_expr else {
291-
return None;
288+
let iter_exprs = for_stat.get_iter_expr().collect::<Vec<_>>();
289+
let test_len_expr = match iter_exprs.len() {
290+
2 => {
291+
let LuaExpr::UnaryExpr(unary_expr) = iter_exprs[1].clone() else {
292+
return None;
293+
};
294+
unary_expr
295+
}
296+
3 => {
297+
let step_type = infer_expr(db, cache, iter_exprs[2].clone()).ok()?;
298+
let LuaType::IntegerConst(step_value) = step_type else {
299+
return None;
300+
};
301+
if step_value > 0 {
302+
let LuaExpr::UnaryExpr(unary_expr) = iter_exprs[1].clone() else {
303+
return None;
304+
};
305+
unary_expr
306+
} else if step_value < 0 {
307+
let LuaExpr::UnaryExpr(unary_expr) = iter_exprs[0].clone() else {
308+
return None;
309+
};
310+
unary_expr
311+
} else {
312+
return None;
313+
}
314+
}
315+
_ => return None,
292316
};
293317

294-
let op = unary_expr.get_op_token()?;
318+
let op = test_len_expr.get_op_token()?;
295319
if op.get_op() != UnaryOperator::OpLen {
296320
return None;
297321
}
298322

299-
let len_expr = unary_expr.get_expr()?;
323+
let len_expr = test_len_expr.get_expr()?;
300324
let len_expr_var_ref_id = get_var_expr_var_ref_id(db, cache, len_expr)?;
301325
let prefix_expr_var_ref_id = get_var_expr_var_ref_id(db, cache, prefix_expr)?;
302326

0 commit comments

Comments
 (0)