Simply constraint matching in solve

This commit is contained in:
ayazhafiz 2021-12-23 20:22:42 -06:00
parent d5bd58c298
commit 409ced0ef2

View file

@ -629,69 +629,63 @@ fn solve(
} }
} }
} }
Present(typ, constr) => { Present(typ, PresenceConstraint::IsOpen) => {
let actual = type_to_var(subs, rank, pools, cached_aliases, typ); let actual = type_to_var(subs, rank, pools, cached_aliases, typ);
match constr { let mut new_desc = subs.get(actual);
PresenceConstraint::IsOpen => { match new_desc.content {
let mut new_desc = subs.get(actual); Content::Structure(FlatType::TagUnion(tags, _)) => {
match new_desc.content { let new_ext = subs.fresh_unnamed_flex_var();
Content::Structure(FlatType::TagUnion(tags, _)) => { let new_union = Content::Structure(FlatType::TagUnion(tags, new_ext));
let new_ext = subs.fresh_unnamed_flex_var(); new_desc.content = new_union;
let new_union = Content::Structure(FlatType::TagUnion(tags, new_ext)); subs.set(actual, new_desc);
new_desc.content = new_union; state
subs.set(actual, new_desc);
state
}
_ => {
// Today, an "open" constraint doesn't affect any types
// other than tag unions. Recursive tag unions are constructed
// at a later time (during occurs checks after tag unions are
// resolved), so that's not handled here either.
// NB: Handle record types here if we add presence constraints
// to their type inference as well.
state
}
}
} }
PresenceConstraint::IncludesTag(tag_name, tys) => { _ => {
let tag_ty = Type::TagUnion( // Today, an "open" constraint doesn't affect any types
vec![(tag_name.clone(), tys.clone())], // other than tag unions. Recursive tag unions are constructed
Box::new(Type::EmptyTagUnion), // at a later time (during occurs checks after tag unions are
// resolved), so that's not handled here either.
// NB: Handle record types here if we add presence constraints
// to their type inference as well.
state
}
}
}
Present(typ, PresenceConstraint::IncludesTag(tag_name, tys)) => {
let actual = type_to_var(subs, rank, pools, cached_aliases, typ);
let tag_ty = Type::TagUnion(
vec![(tag_name.clone(), tys.clone())],
Box::new(Type::EmptyTagUnion),
);
let includes = type_to_var(subs, rank, pools, cached_aliases, &tag_ty);
match unify(subs, actual, includes, Mode::Present) {
Success(vars) => {
introduce(subs, rank, pools, &vars);
state
}
Failure(vars, actual_type, expected_type) => {
introduce(subs, rank, pools, &vars);
// TODO: do we need a better error type here?
let problem = TypeError::BadExpr(
Region::zero(),
Category::When,
actual_type,
Expected::NoExpectation(expected_type),
); );
let includes = type_to_var(subs, rank, pools, cached_aliases, &tag_ty);
match unify(subs, actual, includes, Mode::Present) { problems.push(problem);
Success(vars) => {
introduce(subs, rank, pools, &vars);
state state
}
Failure(vars, actual_type, expected_type) => {
introduce(subs, rank, pools, &vars);
// TODO: do we need a better error type here?
let problem = TypeError::BadExpr(
Region::zero(),
Category::When,
actual_type,
Expected::NoExpectation(expected_type),
);
problems.push(problem);
state
}
BadType(vars, problem) => {
introduce(subs, rank, pools, &vars);
problems.push(TypeError::BadType(problem));
state
}
}
} }
PresenceConstraint::Pattern(_, _, _) => { BadType(vars, problem) => {
unreachable!("Handled in a previous branch") introduce(subs, rank, pools, &vars);
problems.push(TypeError::BadType(problem));
state
} }
} }
} }