Fix empty tuple unification

pull/335/head
Ibrahim Numanagić 2023-02-16 11:09:11 -08:00
parent 6da0f9b804
commit 6a2db4758a
3 changed files with 15 additions and 10 deletions

View File

@ -129,12 +129,12 @@ std::string ClassType::realizedTypeName() const {
} }
RecordType::RecordType(Cache *cache, std::string name, std::string niceName, RecordType::RecordType(Cache *cache, std::string name, std::string niceName,
std::vector<Generic> generics, std::vector<TypePtr> args) std::vector<Generic> generics, std::vector<TypePtr> args, bool isInternal)
: ClassType(cache, std::move(name), std::move(niceName), std::move(generics)), : ClassType(cache, std::move(name), std::move(niceName), std::move(generics)),
args(std::move(args)) {} args(std::move(args)), isInternal(false) {}
RecordType::RecordType(const ClassTypePtr &base, std::vector<TypePtr> args) RecordType::RecordType(const ClassTypePtr &base, std::vector<TypePtr> args, bool isInternal)
: ClassType(base), args(std::move(args)) {} : ClassType(base), args(std::move(args)), isInternal(isInternal) {}
int RecordType::unify(Type *typ, Unification *us) { int RecordType::unify(Type *typ, Unification *us) {
if (auto tr = typ->getRecord()) { if (auto tr = typ->getRecord()) {
@ -157,7 +157,10 @@ int RecordType::unify(Type *typ, Unification *us) {
} }
// Handle Tuple<->@tuple: when unifying tuples, only record members matter. // Handle Tuple<->@tuple: when unifying tuples, only record members matter.
if (startswith(name, TYPE_TUPLE) || startswith(tr->name, TYPE_TUPLE)) { if (startswith(name, TYPE_TUPLE) || startswith(tr->name, TYPE_TUPLE)) {
if (!args.empty() || (!isInternal && !tr->isInternal)) // prevent int<->() unification
return s1 + int(name == tr->name); return s1 + int(name == tr->name);
else
return -1;
} }
return this->ClassType::unify(tr.get(), us); return this->ClassType::unify(tr.get(), us);
} else if (auto t = typ->getLink()) { } else if (auto t = typ->getLink()) {
@ -172,7 +175,7 @@ TypePtr RecordType::generalize(int atLevel) {
auto a = args; auto a = args;
for (auto &t : a) for (auto &t : a)
t = t->generalize(atLevel); t = t->generalize(atLevel);
return std::make_shared<RecordType>(c, a); return std::make_shared<RecordType>(c, a, isInternal);
} }
TypePtr RecordType::instantiate(int atLevel, int *unboundCount, TypePtr RecordType::instantiate(int atLevel, int *unboundCount,
@ -182,7 +185,7 @@ TypePtr RecordType::instantiate(int atLevel, int *unboundCount,
auto a = args; auto a = args;
for (auto &t : a) for (auto &t : a)
t = t->instantiate(atLevel, unboundCount, cache); t = t->instantiate(atLevel, unboundCount, cache);
return std::make_shared<RecordType>(c, a); return std::make_shared<RecordType>(c, a, isInternal);
} }
std::vector<TypePtr> RecordType::getUnbounds() const { std::vector<TypePtr> RecordType::getUnbounds() const {

View File

@ -77,13 +77,13 @@ using ClassTypePtr = std::shared_ptr<ClassType>;
struct RecordType : public ClassType { struct RecordType : public ClassType {
/// List of tuple arguments. /// List of tuple arguments.
std::vector<TypePtr> args; std::vector<TypePtr> args;
char flags = 0; bool isInternal;
explicit RecordType( explicit RecordType(
Cache *cache, std::string name, std::string niceName, Cache *cache, std::string name, std::string niceName,
std::vector<ClassType::Generic> generics = std::vector<ClassType::Generic>(), std::vector<ClassType::Generic> generics = std::vector<ClassType::Generic>(),
std::vector<TypePtr> args = std::vector<TypePtr>()); std::vector<TypePtr> args = std::vector<TypePtr>(), bool isInternal = false);
RecordType(const ClassTypePtr &base, std::vector<TypePtr> args); RecordType(const ClassTypePtr &base, std::vector<TypePtr> args, bool isInternal = false);
public: public:
int unify(Type *typ, Unification *undo) override; int unify(Type *typ, Unification *undo) override;

View File

@ -26,6 +26,8 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
auto typ = Type::makeType(ctx->cache, stmt->name, ctx->cache->rev(stmt->name), auto typ = Type::makeType(ctx->cache, stmt->name, ctx->cache->rev(stmt->name),
stmt->isRecord()) stmt->isRecord())
->getClass(); ->getClass();
if (stmt->isRecord() && stmt->hasAttr(Attr::Internal))
typ->getRecord()->isInternal = true;
if (stmt->isRecord() && startswith(stmt->name, TYPE_PARTIAL)) { if (stmt->isRecord() && startswith(stmt->name, TYPE_PARTIAL)) {
// Special handling of partial types (e.g., `Partial.0001.foo`) // Special handling of partial types (e.g., `Partial.0001.foo`)
if (auto p = in(ctx->cache->partials, stmt->name)) if (auto p = in(ctx->cache->partials, stmt->name))