// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details #include "Luau/Quantify.h" #include "Luau/VisitTypeVar.h" namespace Luau { struct Quantifier { ModulePtr module; TypeLevel level; std::vector generics; std::vector genericPacks; Quantifier(ModulePtr module, TypeLevel level) : module(module) , level(level) { } void cycle(TypeId) {} void cycle(TypePackId) {} bool operator()(TypeId ty, const FreeTypeVar& ftv) { if (!level.subsumes(ftv.level)) return false; *asMutable(ty) = GenericTypeVar{level}; generics.push_back(ty); return false; } template bool operator()(TypeId ty, const T& t) { return true; } template bool operator()(TypePackId, const T&) { return true; } bool operator()(TypeId ty, const TableTypeVar&) { TableTypeVar& ttv = *getMutable(ty); if (ttv.state == TableState::Sealed || ttv.state == TableState::Generic) return false; if (!level.subsumes(ttv.level)) return false; if (ttv.state == TableState::Free) ttv.state = TableState::Generic; else if (ttv.state == TableState::Unsealed) ttv.state = TableState::Sealed; ttv.level = level; return true; } bool operator()(TypePackId tp, const FreeTypePack& ftp) { if (!level.subsumes(ftp.level)) return false; *asMutable(tp) = GenericTypePack{level}; genericPacks.push_back(tp); return true; } }; void quantify(ModulePtr module, TypeId ty, TypeLevel level) { Quantifier q{std::move(module), level}; DenseHashSet seen{nullptr}; visitTypeVarOnce(ty, q, seen); FunctionTypeVar* ftv = getMutable(ty); LUAU_ASSERT(ftv); ftv->generics = q.generics; ftv->genericPacks = q.genericPacks; } } // namespace Luau