Skip to content

Commit

Permalink
feat: type narrowing with hasattr
Browse files Browse the repository at this point in the history
  • Loading branch information
mtshiba committed Mar 24, 2024
1 parent ce5eafc commit d7d422d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
24 changes: 22 additions & 2 deletions crates/erg_compiler/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use crate::ty::free::Constraint;
use crate::ty::typaram::TyParam;
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
use crate::ty::{
CastTarget, GuardType, HasType, ParamTy, Predicate, SubrType, Type, VisibilityModifier,
CastTarget, Field, GuardType, HasType, ParamTy, Predicate, SubrType, Type, VisibilityModifier,
};

use crate::context::{
Expand Down Expand Up @@ -994,7 +994,27 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
&call.args.nth_or_key(0, "object"),
&call.args.nth_or_key(1, "classinfo"),
) {
self.get_bin_guard_type(ident.name.token(), lhs, rhs)
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;
}
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,
}
} else {
None
}
Expand Down
8 changes: 8 additions & 0 deletions tests/should_ok/assert_cast.er
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,11 @@ int_or_strs(rec: { .x = Int } or { .x = Str; .y = Str }): Str =
do: rec.y
do: str rec.x
assert int_or_strs({.x = 1}) == "1"

C = Class { .foo = Int; .bar = Str }
D = Class { .baz = Str }
bar x: C or D =
if hasattr(x, "foo"):
do: x.bar
do: "?"
assert bar(C.new { .foo = 1; .bar = "bar" }) == "bar"

0 comments on commit d7d422d

Please sign in to comment.