mirror of
https://github.com/erg-lang/erg.git
synced 2025-07-07 21:25:31 +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> {
|
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.obj.as_ref(),
|
||||||
&call.attr_name,
|
&call.attr_name,
|
||||||
&call.args.nth_or_key(0, "object"),
|
&call.args.nth_or_key(0, "object"),
|
||||||
&call.args.nth_or_key(1, "classinfo"),
|
&call.args.nth_or_key(1, "classinfo"),
|
||||||
) {
|
) {
|
||||||
match &ident.inspect()[..] {
|
(ast::Expr::Accessor(ast::Accessor::Ident(ident)), None, Some(lhs), Some(rhs)) => {
|
||||||
"isinstance" | "issubclass" => {
|
match &ident.inspect()[..] {
|
||||||
self.get_bin_guard_type(ident.name.token(), lhs, rhs)
|
"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;
|
|
||||||
}
|
}
|
||||||
let name = lit.token.content.trim_matches('\"');
|
"hasattr" => {
|
||||||
let target = self.expr_to_cast_target(lhs);
|
let ast::Expr::Literal(lit) = rhs else {
|
||||||
let rec = dict! {
|
return None;
|
||||||
Field::new(VisibilityModifier::Public, Str::rc(name)) => Type::Obj,
|
};
|
||||||
};
|
if !lit.is(TokenKind::StrLit) {
|
||||||
let to = Type::Record(rec).structuralize();
|
return None;
|
||||||
Some(guard(self.module.context.name.clone(), target, to))
|
}
|
||||||
|
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 {
|
(ast::Expr::Accessor(ast::Accessor::Ident(ident)), None, Some(arg), None) => {
|
||||||
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 {
|
for (nth, (arg, param)) in pos_args {
|
||||||
match self.lower_expr(arg.expr, param) {
|
match self.lower_expr(arg.expr, param) {
|
||||||
Ok(expr) => {
|
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());
|
self.push_guard(nth, kind, expr.ref_t());
|
||||||
}
|
}
|
||||||
hir_pos_args[nth] = hir::PosArg::new(expr);
|
hir_pos_args[nth] = hir::PosArg::new(expr);
|
||||||
|
|
|
@ -25,3 +25,9 @@ is_int(x: Obj) = x in Int
|
||||||
y as Obj = 1
|
y as Obj = 1
|
||||||
assert is_int y
|
assert is_int y
|
||||||
y: Int
|
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