Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/Analysis/include/Luau/Instantiation.h
2727 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#pragma once
3
4
#include "Luau/NotNull.h"
5
#include "Luau/Substitution.h"
6
#include "Luau/TypeFwd.h"
7
#include "Luau/Unifiable.h"
8
#include "Luau/VisitType.h"
9
10
11
namespace Luau
12
{
13
14
struct TxnLog;
15
struct TypeArena;
16
struct TypeCheckLimits;
17
18
// A substitution which replaces generic types in a given set by free types.
19
struct ReplaceGenerics : Substitution
20
{
21
ReplaceGenerics(
22
const TxnLog* log,
23
TypeArena* arena,
24
NotNull<BuiltinTypes> builtinTypes,
25
TypeLevel level,
26
Scope* scope,
27
const std::vector<TypeId>& generics,
28
const std::vector<TypePackId>& genericPacks
29
)
30
: Substitution(log, arena)
31
, builtinTypes(builtinTypes)
32
, level(level)
33
, scope(scope)
34
, generics(generics)
35
, genericPacks(genericPacks)
36
{
37
}
38
39
void resetState(
40
const TxnLog* log,
41
TypeArena* arena,
42
NotNull<BuiltinTypes> builtinTypes,
43
TypeLevel level,
44
Scope* scope,
45
const std::vector<TypeId>& generics,
46
const std::vector<TypePackId>& genericPacks
47
);
48
49
NotNull<BuiltinTypes> builtinTypes;
50
51
TypeLevel level;
52
Scope* scope;
53
std::vector<TypeId> generics;
54
std::vector<TypePackId> genericPacks;
55
56
bool ignoreChildren(TypeId ty) override;
57
bool isDirty(TypeId ty) override;
58
bool isDirty(TypePackId tp) override;
59
TypeId clean(TypeId ty) override;
60
TypePackId clean(TypePackId tp) override;
61
};
62
63
// A substitution which replaces generic functions by monomorphic functions
64
struct Instantiation final : Substitution
65
{
66
Instantiation(const TxnLog* log, TypeArena* arena, NotNull<BuiltinTypes> builtinTypes, TypeLevel level, Scope* scope)
67
: Substitution(log, arena)
68
, builtinTypes(builtinTypes)
69
, level(level)
70
, scope(scope)
71
, reusableReplaceGenerics(log, arena, builtinTypes, level, scope, {}, {})
72
{
73
}
74
75
void resetState(const TxnLog* log, TypeArena* arena, NotNull<BuiltinTypes> builtinTypes, TypeLevel level, Scope* scope);
76
77
NotNull<BuiltinTypes> builtinTypes;
78
79
TypeLevel level;
80
Scope* scope;
81
82
ReplaceGenerics reusableReplaceGenerics;
83
84
bool ignoreChildren(TypeId ty) override;
85
bool isDirty(TypeId ty) override;
86
bool isDirty(TypePackId tp) override;
87
TypeId clean(TypeId ty) override;
88
TypePackId clean(TypePackId tp) override;
89
};
90
91
// Used to find if a FunctionType requires generic type cleanup during instantiation
92
struct GenericTypeFinder : TypeOnceVisitor
93
{
94
bool found = false;
95
96
GenericTypeFinder()
97
: TypeOnceVisitor("GenericTypeFinder", /* skipBoundTypes */ true)
98
{
99
}
100
101
bool visit(TypeId ty) override
102
{
103
return !found;
104
}
105
106
bool visit(TypePackId ty) override
107
{
108
return !found;
109
}
110
111
bool visit(TypeId ty, const Luau::FunctionType& ftv) override
112
{
113
if (ftv.hasNoFreeOrGenericTypes)
114
return false;
115
116
if (!ftv.generics.empty() || !ftv.genericPacks.empty())
117
found = true;
118
119
return !found;
120
}
121
122
bool visit(TypeId ty, const Luau::TableType& ttv) override
123
{
124
if (ttv.state == Luau::TableState::Generic)
125
found = true;
126
127
return !found;
128
}
129
130
bool visit(TypeId ty, const Luau::GenericType&) override
131
{
132
found = true;
133
return false;
134
}
135
136
bool visit(TypePackId ty, const Luau::GenericTypePack&) override
137
{
138
found = true;
139
return false;
140
}
141
142
bool visit(TypeId ty, const Luau::ExternType&) override
143
{
144
// During function instantiation, extern types are not traversed even if they have generics
145
return false;
146
}
147
};
148
149
/** Attempt to instantiate a type. Only used under local type inference.
150
*
151
* When given a generic function type, instantiate() will return a copy with the
152
* generics replaced by fresh types. Instantiation will return the same TypeId
153
* back if the function does not have any generics.
154
*
155
* All higher order generics are left as-is. For example, instantiation of
156
* <X>(<Y>(Y) -> (X, Y)) -> (X, Y) is (<Y>(Y) -> ('x, Y)) -> ('x, Y)
157
*
158
* We substitute the generic X for the free 'x, but leave the generic Y alone.
159
*
160
* Instantiation fails only when processing the type causes internal recursion
161
* limits to be exceeded.
162
*/
163
std::optional<TypeId> instantiate(
164
NotNull<BuiltinTypes> builtinTypes,
165
NotNull<TypeArena> arena,
166
NotNull<TypeCheckLimits> limits,
167
NotNull<Scope> scope,
168
TypeId ty
169
);
170
171
} // namespace Luau
172
173