mirror of
https://github.com/erg-lang/erg.git
synced 2025-07-07 13:15:21 +00:00
fix: complement type narrowing bug
This commit is contained in:
parent
8043a13644
commit
21582953c0
2 changed files with 40 additions and 22 deletions
|
@ -1141,35 +1141,45 @@ 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"),
|
||||
) {
|
||||
match &ident.inspect()[..] {
|
||||
"isinstance" | "issubclass" => {
|
||||
self.get_bin_guard_type(ident.name.token(), lhs, rhs)
|
||||
}
|
||||
"hasattr" => {
|
||||
let ast::Expr::Literal(lit) = rhs else {
|
||||
return None;
|
||||
};
|
||||
if !lit.is(TokenKind::StrLit) {
|
||||
return None;
|
||||
(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)
|
||||
}
|
||||
let name = lit.token.content.trim_matches('\"');
|
||||
let target = self.expr_to_cast_target(lhs);
|
||||
let rec = dict! {
|
||||
Field::new(VisibilityModifier::Public, Str::rc(name)) => Type::Obj,
|
||||
};
|
||||
let to = Type::Record(rec).structuralize();
|
||||
Some(guard(self.module.context.name.clone(), target, to))
|
||||
"hasattr" => {
|
||||
let ast::Expr::Literal(lit) = rhs else {
|
||||
return None;
|
||||
};
|
||||
if !lit.is(TokenKind::StrLit) {
|
||||
return None;
|
||||
}
|
||||
let name = lit.token.content.trim_matches('\"');
|
||||
let target = self.expr_to_cast_target(lhs);
|
||||
let rec = dict! {
|
||||
Field::new(VisibilityModifier::Public, Str::rc(name)) => Type::Obj,
|
||||
};
|
||||
let to = Type::Record(rec).structuralize();
|
||||
Some(guard(self.module.context.name.clone(), target, to))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
_ => 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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue