Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/Analysis/src/Quantify.cpp
2746 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
3
#include "Luau/Quantify.h"
4
5
#include "Luau/Scope.h"
6
#include "Luau/Substitution.h"
7
#include "Luau/TxnLog.h"
8
#include "Luau/Type.h"
9
#include "Luau/VisitType.h"
10
11
12
namespace Luau
13
{
14
15
struct Quantifier final : TypeOnceVisitor
16
{
17
TypeLevel level;
18
std::vector<TypeId> generics;
19
std::vector<TypePackId> genericPacks;
20
Scope* scope = nullptr;
21
bool seenGenericType = false;
22
bool seenMutableType = false;
23
24
explicit Quantifier(TypeLevel level)
25
: TypeOnceVisitor("Quantifier", /* skipBoundTypes */ false)
26
, level(level)
27
{
28
}
29
30
/// @return true if outer encloses inner
31
bool subsumes(Scope* outer, Scope* inner)
32
{
33
while (inner)
34
{
35
if (inner == outer)
36
return true;
37
inner = inner->parent.get();
38
}
39
40
return false;
41
}
42
43
bool visit(TypeId ty, const FreeType& ftv) override
44
{
45
seenMutableType = true;
46
47
if (!level.subsumes(ftv.level))
48
return false;
49
50
*asMutable(ty) = GenericType{level};
51
52
generics.push_back(ty);
53
54
return false;
55
}
56
57
bool visit(TypeId ty, const TableType&) override
58
{
59
LUAU_ASSERT(getMutable<TableType>(ty));
60
TableType& ttv = *getMutable<TableType>(ty);
61
62
if (ttv.state == TableState::Generic)
63
seenGenericType = true;
64
65
if (ttv.state == TableState::Free)
66
seenMutableType = true;
67
68
if (!level.subsumes(ttv.level))
69
{
70
if (ttv.state == TableState::Unsealed)
71
seenMutableType = true;
72
return false;
73
}
74
75
if (ttv.state == TableState::Free)
76
{
77
ttv.state = TableState::Generic;
78
seenGenericType = true;
79
}
80
else if (ttv.state == TableState::Unsealed)
81
ttv.state = TableState::Sealed;
82
83
ttv.level = level;
84
85
return true;
86
}
87
88
bool visit(TypePackId tp, const FreeTypePack& ftp) override
89
{
90
seenMutableType = true;
91
92
if (!level.subsumes(ftp.level))
93
return false;
94
95
*asMutable(tp) = GenericTypePack{level};
96
genericPacks.push_back(tp);
97
return true;
98
}
99
};
100
101
void quantify(TypeId ty, TypeLevel level)
102
{
103
Quantifier q{level};
104
q.traverse(ty);
105
106
FunctionType* ftv = getMutable<FunctionType>(ty);
107
LUAU_ASSERT(ftv);
108
ftv->generics.insert(ftv->generics.end(), q.generics.begin(), q.generics.end());
109
ftv->genericPacks.insert(ftv->genericPacks.end(), q.genericPacks.begin(), q.genericPacks.end());
110
}
111
112
} // namespace Luau
113
114