Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,21 @@ mod test {
"#
));
}

#[test]
fn test_nonnli_with_nil() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There's a typo in the test function name. It should be test_nonnil_with_nil to match the other test file and for clarity.

Suggested change
fn test_nonnli_with_nil() {
fn test_nonnil_with_nil() {

let mut ws = VirtualWorkspace::new();
assert!(!ws.check_code_for(
DiagnosticCode::UnnecessaryAssert,
r#"
assert("abc" ~= nil)
"#
));
assert!(!ws.check_code_for(
DiagnosticCode::UnnecessaryAssert,
r#"
assert(1 == nil)
"#
));
Comment on lines +134 to +145

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The logic of these tests is incorrect. With the changes in infer_binary/mod.rs, the expressions inside assert() will be evaluated as constant booleans (true for "abc" ~= nil and false for 1 == nil). This should trigger the UnnecessaryAssert diagnostic for both cases (an unnecessary and an impossible assert, respectively).

Therefore, ws.check_code_for(...) should return true, and you should be using assert!(...) to verify that the diagnostic is correctly reported.

Suggested change
assert!(!ws.check_code_for(
DiagnosticCode::UnnecessaryAssert,
r#"
assert("abc" ~= nil)
"#
));
assert!(!ws.check_code_for(
DiagnosticCode::UnnecessaryAssert,
r#"
assert(1 == nil)
"#
));
assert!(ws.check_code_for(
DiagnosticCode::UnnecessaryAssert,
r#"
assert("abc" ~= nil)
"#
));
assert!(ws.check_code_for(
DiagnosticCode::UnnecessaryAssert,
r#"
assert(1 == nil)
"#
));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,25 @@ mod test {
"#
));
}

#[test]
fn test_nonnil_with_nil() {
let mut ws = VirtualWorkspace::new();
assert!(!ws.check_code_for(
DiagnosticCode::UnnecessaryIf,
r#"
if 1 ~= nil then
error("Impossible")
end
"#
));
assert!(!ws.check_code_for(
DiagnosticCode::UnnecessaryIf,
r#"
if "abc" == nil then
error("Impossible")
end
"#
));
Comment on lines +33 to +48

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The logic of these tests is incorrect. With the changes in infer_binary/mod.rs, the conditions in the if statements will be evaluated as constant booleans (true for 1 ~= nil and false for "abc" == nil). This should trigger the UnnecessaryIf diagnostic for both cases (an unnecessary and an impossible if-condition, respectively).

Therefore, ws.check_code_for(...) should return true, and you should be using assert!(...) to verify that the diagnostic is correctly reported.

Suggested change
assert!(!ws.check_code_for(
DiagnosticCode::UnnecessaryIf,
r#"
if 1 ~= nil then
error("Impossible")
end
"#
));
assert!(!ws.check_code_for(
DiagnosticCode::UnnecessaryIf,
r#"
if "abc" == nil then
error("Impossible")
end
"#
));
assert!(ws.check_code_for(
DiagnosticCode::UnnecessaryIf,
r#"
if 1 ~= nil then
error("Impossible")
end
"#
));
assert!(ws.check_code_for(
DiagnosticCode::UnnecessaryIf,
r#"
if "abc" == nil then
error("Impossible")
end
"#
));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,16 @@ fn infer_cmp_expr(_: &DbIndex, left: LuaType, right: LuaType, op: BinaryOperator
BinaryOperator::OpNe => Ok(LuaType::BooleanConst(i != j)),
_ => Ok(LuaType::Boolean),
},
(LuaType::Nil, right) if right.is_const() => match op {
BinaryOperator::OpEq => Ok(LuaType::BooleanConst(false)),
BinaryOperator::OpNe => Ok(LuaType::BooleanConst(true)),
_ => Ok(LuaType::Boolean),
},
(left, LuaType::Nil) if left.is_const() => match op {
BinaryOperator::OpEq => Ok(LuaType::BooleanConst(false)),
BinaryOperator::OpNe => Ok(LuaType::BooleanConst(true)),
_ => Ok(LuaType::Boolean),
},
Comment on lines +509 to +518

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These two match arms handle the cases (nil, const) and (const, nil) respectively, and their logic is identical. You can combine them into a single arm to reduce code duplication and improve maintainability.

Suggested change
(LuaType::Nil, right) if right.is_const() => match op {
BinaryOperator::OpEq => Ok(LuaType::BooleanConst(false)),
BinaryOperator::OpNe => Ok(LuaType::BooleanConst(true)),
_ => Ok(LuaType::Boolean),
},
(left, LuaType::Nil) if left.is_const() => match op {
BinaryOperator::OpEq => Ok(LuaType::BooleanConst(false)),
BinaryOperator::OpNe => Ok(LuaType::BooleanConst(true)),
_ => Ok(LuaType::Boolean),
},
(left, right) if (left.is_nil() && right.is_const()) || (right.is_nil() && left.is_const()) => match op {
BinaryOperator::OpEq => Ok(LuaType::BooleanConst(false)),
BinaryOperator::OpNe => Ok(LuaType::BooleanConst(true)),
_ => Ok(LuaType::Boolean),
},

(left, right) if left.is_const() && right.is_const() => Ok(LuaType::BooleanConst(false)),
_ => Ok(LuaType::Boolean),
}
Expand Down