mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
feat: improve record type narrowing
This commit is contained in:
parent
35f55c62d3
commit
ce5eafca9b
7 changed files with 62 additions and 4 deletions
|
@ -1304,7 +1304,7 @@ impl Context {
|
|||
/// union(Array(Int, 2), Array(Str, 2)) == Array(Int or Str, 2)
|
||||
/// union(Array(Int, 2), Array(Str, 3)) == Array(Int, 2) or Array(Int, 3)
|
||||
/// union({ .a = Int }, { .a = Str }) == { .a = Int or Str }
|
||||
/// union({ .a = Int }, { .a = Int; .b = Int }) == { .a = Int }
|
||||
/// union({ .a = Int }, { .a = Int; .b = Int }) == { .a = Int } or { .a = Int; .b = Int } # not to lost `b` information
|
||||
/// union((A and B) or C) == (A or C) and (B or C)
|
||||
/// ```
|
||||
pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type {
|
||||
|
@ -1326,7 +1326,7 @@ impl Context {
|
|||
union
|
||||
}
|
||||
}
|
||||
(Record(l), Record(r)) => {
|
||||
(Record(l), Record(r)) if l.len() == r.len() && l.len() == 1 => {
|
||||
let mut union = Dict::new();
|
||||
for (l_k, l_v) in l.iter() {
|
||||
if let Some((r_k, r_v)) = r.get_key_value(l_k) {
|
||||
|
|
|
@ -1030,6 +1030,36 @@ impl Context {
|
|||
}
|
||||
}
|
||||
Type::Structural(t) => self.get_attr_info_from_attributive(t, ident, namespace),
|
||||
// TODO: And
|
||||
Type::Or(l, r) => {
|
||||
let l_info = self.get_attr_info_from_attributive(l, ident, namespace);
|
||||
let r_info = self.get_attr_info_from_attributive(r, ident, namespace);
|
||||
match (l_info, r_info) {
|
||||
(Triple::Ok(l), Triple::Ok(r)) => {
|
||||
let res = self.union(&l.t, &r.t);
|
||||
let vis = if l.vis.is_public() && r.vis.is_public() {
|
||||
Visibility::DUMMY_PUBLIC
|
||||
} else {
|
||||
Visibility::DUMMY_PRIVATE
|
||||
};
|
||||
let vi = VarInfo::new(
|
||||
res,
|
||||
l.muty,
|
||||
vis,
|
||||
l.kind,
|
||||
l.comptime_decos,
|
||||
l.ctx,
|
||||
l.py_name,
|
||||
l.def_loc,
|
||||
);
|
||||
Triple::Ok(vi)
|
||||
},
|
||||
(Triple::Ok(_), Triple::Err(e))
|
||||
| (Triple::Err(e), Triple::Ok(_)) => Triple::Err(e),
|
||||
(Triple::Err(e1), Triple::Err(_e2)) => Triple::Err(e1),
|
||||
_ => Triple::None,
|
||||
}
|
||||
}
|
||||
_other => Triple::None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2405,6 +2405,16 @@ impl Context {
|
|||
if expr == target.as_ref() {
|
||||
return Some(*guard.to.clone());
|
||||
}
|
||||
// { r.x in Int } => { r in Structural { .x = Int } }
|
||||
else if let ast::Expr::Accessor(ast::Accessor::Attr(attr)) = target.as_ref() {
|
||||
if attr.obj.as_ref() == expr {
|
||||
let mut rec = Dict::new();
|
||||
let vis = self.instantiate_vis_modifier(&attr.ident.vis).ok()?;
|
||||
let field = Field::new(vis, attr.ident.inspect().clone());
|
||||
rec.insert(field, *guard.to.clone());
|
||||
return Some(Type::Record(rec).structuralize());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue