fix: complement type narrowing bug

This commit is contained in:
Shunsuke Shibayama 2025-02-08 15:10:48 +09:00
parent 8043a13644
commit 21582953c0
2 changed files with 40 additions and 22 deletions

View file

@ -1141,12 +1141,13 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
}
fn get_call_guard_type(&self, call: &ast::Call) -> Option<Type> {
if let (ast::Expr::Accessor(ast::Accessor::Ident(ident)), None, Some(lhs), Some(rhs)) = (
match (
call.obj.as_ref(),
&call.attr_name,
&call.args.nth_or_key(0, "object"),
&call.args.nth_or_key(1, "classinfo"),
) {
(ast::Expr::Accessor(ast::Accessor::Ident(ident)), None, Some(lhs), Some(rhs)) => {
match &ident.inspect()[..] {
"isinstance" | "issubclass" => {
self.get_bin_guard_type(ident.name.token(), lhs, rhs)
@ -1168,8 +1169,17 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
}
_ => None,
}
} else {
None
}
(ast::Expr::Accessor(ast::Accessor::Ident(ident)), None, Some(arg), None) => {
match &ident.inspect()[..] {
"not" => {
let arg = self.get_guard_type(arg)?;
Some(self.module.context.complement(&arg))
}
_ => None,
}
}
_ => None,
}
}
@ -1428,7 +1438,9 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
for (nth, (arg, param)) in pos_args {
match self.lower_expr(arg.expr, param) {
Ok(expr) => {
if let Some(kind) = self.module.context.control_kind() {
// e.g. `if not isinstance(x, Int)`
// push {x in not Int}, not {x in Int}
if let Some(kind) = self.module.context.current_control_flow() {
self.push_guard(nth, kind, expr.ref_t());
}
hir_pos_args[nth] = hir::PosArg::new(expr);

View file

@ -25,3 +25,9 @@ is_int(x: Obj) = x in Int
y as Obj = 1
assert is_int y
y: Int
bs x: Bytes or Str =
discard if not(isinstance(x, Str)), do:
# x: Bytes
str(x, "ascii")
_ = bs "abc"