From 6a2db4758ac6cb48703df5109ab7a87e6b33d8d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ibrahim=20Numanagic=CC=81?= Date: Thu, 16 Feb 2023 11:09:11 -0800 Subject: [PATCH] Fix empty tuple unification --- codon/parser/ast/types/class.cpp | 17 ++++++++++------- codon/parser/ast/types/class.h | 6 +++--- codon/parser/visitors/typecheck/class.cpp | 2 ++ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/codon/parser/ast/types/class.cpp b/codon/parser/ast/types/class.cpp index ef272418..d7cb5119 100644 --- a/codon/parser/ast/types/class.cpp +++ b/codon/parser/ast/types/class.cpp @@ -129,12 +129,12 @@ std::string ClassType::realizedTypeName() const { } RecordType::RecordType(Cache *cache, std::string name, std::string niceName, - std::vector generics, std::vector args) + std::vector generics, std::vector args, bool isInternal) : 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 args) - : ClassType(base), args(std::move(args)) {} +RecordType::RecordType(const ClassTypePtr &base, std::vector args, bool isInternal) + : ClassType(base), args(std::move(args)), isInternal(isInternal) {} int RecordType::unify(Type *typ, Unification *us) { 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. if (startswith(name, TYPE_TUPLE) || startswith(tr->name, TYPE_TUPLE)) { - return s1 + int(name == tr->name); + if (!args.empty() || (!isInternal && !tr->isInternal)) // prevent int<->() unification + return s1 + int(name == tr->name); + else + return -1; } return this->ClassType::unify(tr.get(), us); } else if (auto t = typ->getLink()) { @@ -172,7 +175,7 @@ TypePtr RecordType::generalize(int atLevel) { auto a = args; for (auto &t : a) t = t->generalize(atLevel); - return std::make_shared(c, a); + return std::make_shared(c, a, isInternal); } TypePtr RecordType::instantiate(int atLevel, int *unboundCount, @@ -182,7 +185,7 @@ TypePtr RecordType::instantiate(int atLevel, int *unboundCount, auto a = args; for (auto &t : a) t = t->instantiate(atLevel, unboundCount, cache); - return std::make_shared(c, a); + return std::make_shared(c, a, isInternal); } std::vector RecordType::getUnbounds() const { diff --git a/codon/parser/ast/types/class.h b/codon/parser/ast/types/class.h index 1865a9b7..0a4a6100 100644 --- a/codon/parser/ast/types/class.h +++ b/codon/parser/ast/types/class.h @@ -77,13 +77,13 @@ using ClassTypePtr = std::shared_ptr; struct RecordType : public ClassType { /// List of tuple arguments. std::vector args; - char flags = 0; + bool isInternal; explicit RecordType( Cache *cache, std::string name, std::string niceName, std::vector generics = std::vector(), - std::vector args = std::vector()); - RecordType(const ClassTypePtr &base, std::vector args); + std::vector args = std::vector(), bool isInternal = false); + RecordType(const ClassTypePtr &base, std::vector args, bool isInternal = false); public: int unify(Type *typ, Unification *undo) override; diff --git a/codon/parser/visitors/typecheck/class.cpp b/codon/parser/visitors/typecheck/class.cpp index 9e5b781b..d273041e 100644 --- a/codon/parser/visitors/typecheck/class.cpp +++ b/codon/parser/visitors/typecheck/class.cpp @@ -26,6 +26,8 @@ void TypecheckVisitor::visit(ClassStmt *stmt) { auto typ = Type::makeType(ctx->cache, stmt->name, ctx->cache->rev(stmt->name), stmt->isRecord()) ->getClass(); + if (stmt->isRecord() && stmt->hasAttr(Attr::Internal)) + typ->getRecord()->isInternal = true; if (stmt->isRecord() && startswith(stmt->name, TYPE_PARTIAL)) { // Special handling of partial types (e.g., `Partial.0001.foo`) if (auto p = in(ctx->cache->partials, stmt->name))