fix: structural type inference bug

This commit is contained in:
Shunsuke Shibayama 2023-12-09 23:35:32 +09:00
parent fd140a810c
commit 30bf5fb7c9
2 changed files with 26 additions and 6 deletions

View file

@ -675,19 +675,27 @@ impl Context {
) -> Triple<VarInfo, TyCheckError> {
// get_attr_info(?T, aaa) == None
// => ?T(<: Structural({ .aaa = ?U }))
if PYTHON_MODE && obj.var_info().is_some_and(|vi| vi.is_untyped_parameter()) {
if PYTHON_MODE
&& obj
.var_info()
.is_some_and(|vi| vi.is_ambiguously_typed_parameter())
{
let constraint = expect.map_or(Constraint::new_type_of(Type), |t| {
Constraint::new_subtype_of(t.clone())
});
let t = free_var(self.level, constraint);
if let Some(fv) = obj.ref_t().as_free() {
if fv.get_sub().is_some() {
let sup = fv.get_super().unwrap();
let vis = self.instantiate_vis_modifier(&ident.vis).unwrap();
let structural = Type::Record(
dict! { Field::new(vis, ident.inspect().clone()) => t.clone() },
)
.structuralize();
fv.update_super(|_| structural);
let intersection = self.intersection(&sup, &structural);
if intersection != Never {
fv.update_super(|_| intersection);
}
}
}
let muty = Mutability::from(&ident.inspect()[..]);
@ -1118,7 +1126,11 @@ impl Context {
) -> SingleTyCheckResult<VarInfo> {
// search_method_info(?T, aaa, pos_args: [1, 2]) == None
// => ?T(<: Structural({ .aaa = (self: ?T, ?U, ?V) -> ?W }))
if PYTHON_MODE && obj.var_info().is_some_and(|vi| vi.is_untyped_parameter()) {
if PYTHON_MODE
&& obj
.var_info()
.is_some_and(|vi| vi.is_ambiguously_typed_parameter())
{
let nd_params = pos_args
.iter()
.map(|_| ParamTy::Pos(free_var(self.level, Constraint::new_type_of(Type))))
@ -1136,12 +1148,16 @@ impl Context {
let subr_t = fn_met(obj.t(), nd_params, None, d_params, None, return_t);
if let Some(fv) = obj.ref_t().as_free() {
if fv.get_sub().is_some() {
let sup = fv.get_super().unwrap();
let vis = self.instantiate_vis_modifier(&attr_name.vis).unwrap();
let structural = Type::Record(
dict! { Field::new(vis, attr_name.inspect().clone()) => subr_t.clone() },
)
.structuralize();
fv.update_super(|_| structural);
let intersection = self.intersection(&sup, &structural);
if intersection != Never {
fv.update_super(|_| intersection);
}
}
}
let muty = Mutability::from(&attr_name.inspect()[..]);

View file

@ -433,8 +433,12 @@ impl VarInfo {
)
}
pub fn is_untyped_parameter(&self) -> bool {
self.kind.is_parameter() && self.t.is_unbound_var()
pub fn is_ambiguously_typed_parameter(&self) -> bool {
self.kind.is_parameter()
&& self
.t
.get_super()
.is_some_and(|sup| sup == Type::Obj || sup.is_structural())
}
pub const fn is_parameter(&self) -> bool {