Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/Analysis/src/IostreamHelpers.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#include "Luau/IostreamHelpers.h"
3
#include "Luau/Error.h"
4
#include "Luau/ToString.h"
5
#include "Luau/TypePath.h"
6
7
#include <type_traits>
8
9
namespace Luau
10
{
11
12
std::ostream& operator<<(std::ostream& stream, const Position& position)
13
{
14
// We add one so that the numbers we display match what people see in their text editors.
15
return stream << "{ line = " << (position.line + 1) << ", col = " << (position.column + 1) << " }";
16
}
17
18
std::ostream& operator<<(std::ostream& stream, const Location& location)
19
{
20
return stream << "Location { " << location.begin << ", " << location.end << " }";
21
}
22
23
std::ostream& operator<<(std::ostream& stream, const AstName& name)
24
{
25
if (name.value)
26
return stream << name.value;
27
else
28
return stream << "<empty>";
29
}
30
31
template<typename T>
32
static void errorToString(std::ostream& stream, const T& err)
33
{
34
if constexpr (false)
35
{
36
}
37
else if constexpr (std::is_same_v<T, TypeMismatch>)
38
stream << "TypeMismatch { " << toString(err.wantedType) << ", " << toString(err.givenType) << " }";
39
else if constexpr (std::is_same_v<T, UnknownSymbol>)
40
stream << "UnknownSymbol { " << err.name << " , context " << err.context << " }";
41
else if constexpr (std::is_same_v<T, UnknownProperty>)
42
stream << "UnknownProperty { " << toString(err.table) << ", key = " << err.key << " }";
43
else if constexpr (std::is_same_v<T, NotATable>)
44
stream << "NotATable { " << toString(err.ty) << " }";
45
else if constexpr (std::is_same_v<T, CannotExtendTable>)
46
stream << "CannotExtendTable { " << toString(err.tableType) << ", context " << err.context << ", prop \"" << err.prop << "\" }";
47
else if constexpr (std::is_same_v<T, CannotCompareUnrelatedTypes>)
48
stream << "CannotCompareUnrelatedTypes { " << toString(err.left) << ", " << toString(err.right) << ", op '" << toString(err.op) << "' }";
49
else if constexpr (std::is_same_v<T, OnlyTablesCanHaveMethods>)
50
stream << "OnlyTablesCanHaveMethods { " << toString(err.tableType) << " }";
51
else if constexpr (std::is_same_v<T, DuplicateTypeDefinition>)
52
stream << "DuplicateTypeDefinition { " << err.name << " }";
53
else if constexpr (std::is_same_v<T, CountMismatch>)
54
stream << "CountMismatch { expected " << err.expected << ", got " << err.actual << ", context " << err.context << " }";
55
else if constexpr (std::is_same_v<T, FunctionDoesNotTakeSelf>)
56
stream << "FunctionDoesNotTakeSelf { }";
57
else if constexpr (std::is_same_v<T, FunctionRequiresSelf>)
58
stream << "FunctionRequiresSelf { }";
59
else if constexpr (std::is_same_v<T, OccursCheckFailed>)
60
stream << "OccursCheckFailed { }";
61
else if constexpr (std::is_same_v<T, UnknownRequire>)
62
stream << "UnknownRequire { " << err.modulePath << " }";
63
else if constexpr (std::is_same_v<T, IncorrectGenericParameterCount>)
64
{
65
stream << "IncorrectGenericParameterCount { name = " << err.name;
66
67
if (!err.typeFun.typeParams.empty() || !err.typeFun.typePackParams.empty())
68
{
69
stream << "<";
70
bool first = true;
71
for (auto param : err.typeFun.typeParams)
72
{
73
if (first)
74
first = false;
75
else
76
stream << ", ";
77
78
stream << toString(param.ty);
79
}
80
81
for (auto param : err.typeFun.typePackParams)
82
{
83
if (first)
84
first = false;
85
else
86
stream << ", ";
87
88
stream << toString(param.tp);
89
}
90
91
stream << ">";
92
}
93
94
stream << ", typeFun = " << toString(err.typeFun.type) << ", actualCount = " << err.actualParameters << " }";
95
}
96
else if constexpr (std::is_same_v<T, SyntaxError>)
97
stream << "SyntaxError { " << err.message << " }";
98
else if constexpr (std::is_same_v<T, CodeTooComplex>)
99
stream << "CodeTooComplex {}";
100
else if constexpr (std::is_same_v<T, UnificationTooComplex>)
101
stream << "UnificationTooComplex {}";
102
else if constexpr (std::is_same_v<T, UnknownPropButFoundLikeProp>)
103
{
104
stream << "UnknownPropButFoundLikeProp { key = '" << err.key << "', suggested = { ";
105
106
bool first = true;
107
for (Name name : err.candidates)
108
{
109
if (first)
110
first = false;
111
else
112
stream << ", ";
113
114
stream << "'" << name << "'";
115
}
116
117
stream << " }, table = " << toString(err.table) << " } ";
118
}
119
else if constexpr (std::is_same_v<T, GenericError>)
120
stream << "GenericError { " << err.message << " }";
121
else if constexpr (std::is_same_v<T, InternalError>)
122
stream << "InternalError { " << err.message << " }";
123
else if constexpr (std::is_same_v<T, ConstraintSolvingIncompleteError>)
124
stream << "ConstraintSolvingIncompleteError {}";
125
else if constexpr (std::is_same_v<T, CannotCallNonFunction>)
126
stream << "CannotCallNonFunction { " << toString(err.ty) << " }";
127
else if constexpr (std::is_same_v<T, ExtraInformation>)
128
stream << "ExtraInformation { " << err.message << " }";
129
else if constexpr (std::is_same_v<T, DeprecatedApiUsed>)
130
stream << "DeprecatedApiUsed { " << err.symbol << ", useInstead = " << err.useInstead << " }";
131
else if constexpr (std::is_same_v<T, ModuleHasCyclicDependency>)
132
{
133
stream << "ModuleHasCyclicDependency {";
134
135
bool first = true;
136
for (const ModuleName& name : err.cycle)
137
{
138
if (first)
139
first = false;
140
else
141
stream << ", ";
142
143
stream << name;
144
}
145
146
stream << "}";
147
}
148
else if constexpr (std::is_same_v<T, IllegalRequire>)
149
stream << "IllegalRequire { " << err.moduleName << ", reason = " << err.reason << " }";
150
else if constexpr (std::is_same_v<T, FunctionExitsWithoutReturning>)
151
stream << "FunctionExitsWithoutReturning {" << toString(err.expectedReturnType) << "}";
152
else if constexpr (std::is_same_v<T, DuplicateGenericParameter>)
153
stream << "DuplicateGenericParameter { " + err.parameterName + " }";
154
else if constexpr (std::is_same_v<T, CannotInferBinaryOperation>)
155
stream << "CannotInferBinaryOperation { op = " + toString(err.op) + ", suggested = '" +
156
(err.suggestedToAnnotate ? *err.suggestedToAnnotate : "") + "', kind "
157
<< err.kind << "}";
158
else if constexpr (std::is_same_v<T, MissingProperties>)
159
{
160
stream << "MissingProperties { superType = '" << toString(err.superType) << "', subType = '" << toString(err.subType) << "', properties = { ";
161
162
bool first = true;
163
for (Name name : err.properties)
164
{
165
if (first)
166
first = false;
167
else
168
stream << ", ";
169
170
stream << "'" << name << "'";
171
}
172
173
stream << " }, context " << err.context << " } ";
174
}
175
else if constexpr (std::is_same_v<T, SwappedGenericTypeParameter>)
176
stream << "SwappedGenericTypeParameter { name = '" + err.name + "', kind = " + std::to_string(err.kind) + " }";
177
else if constexpr (std::is_same_v<T, OptionalValueAccess>)
178
stream << "OptionalValueAccess { optional = '" + toString(err.optional) + "' }";
179
else if constexpr (std::is_same_v<T, MissingUnionProperty>)
180
{
181
stream << "MissingUnionProperty { type = '" + toString(err.type) + "', missing = { ";
182
183
bool first = true;
184
for (auto ty : err.missing)
185
{
186
if (first)
187
first = false;
188
else
189
stream << ", ";
190
191
stream << "'" << toString(ty) << "'";
192
}
193
194
stream << " }, key = '" + err.key + "' }";
195
}
196
else if constexpr (std::is_same_v<T, TypesAreUnrelated>)
197
stream << "TypesAreUnrelated { left = '" + toString(err.left) + "', right = '" + toString(err.right) + "' }";
198
else if constexpr (std::is_same_v<T, NormalizationTooComplex>)
199
stream << "NormalizationTooComplex { }";
200
else if constexpr (std::is_same_v<T, TypePackMismatch>)
201
stream << "TypePackMismatch { wanted = '" + toString(err.wantedTp) + "', given = '" + toString(err.givenTp) + "' }";
202
else if constexpr (std::is_same_v<T, DynamicPropertyLookupOnExternTypesUnsafe>)
203
stream << "DynamicPropertyLookupOnExternTypesUnsafe { " << toString(err.ty) << " }";
204
else if constexpr (std::is_same_v<T, UninhabitedTypeFunction>)
205
stream << "UninhabitedTypeFunction { " << toString(err.ty) << " }";
206
else if constexpr (std::is_same_v<T, ExplicitFunctionAnnotationRecommended>)
207
{
208
std::string recArgs = "[";
209
for (auto [s, t] : err.recommendedArgs)
210
recArgs += " " + s + ": " + toString(t);
211
recArgs += " ]";
212
stream << "ExplicitFunctionAnnotationRecommended { recommendedReturn = '" + toString(err.recommendedReturn) +
213
"', recommendedArgs = " + recArgs + "}";
214
}
215
else if constexpr (std::is_same_v<T, UninhabitedTypePackFunction>)
216
stream << "UninhabitedTypePackFunction { " << toString(err.tp) << " }";
217
else if constexpr (std::is_same_v<T, WhereClauseNeeded>)
218
stream << "WhereClauseNeeded { " << toString(err.ty) << " }";
219
else if constexpr (std::is_same_v<T, PackWhereClauseNeeded>)
220
stream << "PackWhereClauseNeeded { " << toString(err.tp) << " }";
221
else if constexpr (std::is_same_v<T, CheckedFunctionCallError>)
222
stream << "CheckedFunctionCallError { expected = '" << toString(err.expected) << "', passed = '" << toString(err.passed)
223
<< "', checkedFunctionName = " << err.checkedFunctionName << ", argumentIndex = " << std::to_string(err.argumentIndex) << " }";
224
else if constexpr (std::is_same_v<T, NonStrictFunctionDefinitionError>)
225
stream << "NonStrictFunctionDefinitionError { functionName = '" + err.functionName + "', argument = '" + err.argument +
226
"', argumentType = '" + toString(err.argumentType) + "' }";
227
else if constexpr (std::is_same_v<T, PropertyAccessViolation>)
228
stream << "PropertyAccessViolation { table = " << toString(err.table) << ", prop = '" << err.key << "', context = " << err.context << " }";
229
else if constexpr (std::is_same_v<T, CheckedFunctionIncorrectArgs>)
230
stream << "CheckedFunction { functionName = '" + err.functionName + ", expected = " + std::to_string(err.expected) +
231
", actual = " + std::to_string(err.actual) + "}";
232
else if constexpr (std::is_same_v<T, UnexpectedTypeInSubtyping>)
233
stream << "UnexpectedTypeInSubtyping { ty = '" + toString(err.ty) + "' }";
234
else if constexpr (std::is_same_v<T, UnexpectedTypePackInSubtyping>)
235
stream << "UnexpectedTypePackInSubtyping { tp = '" + toString(err.tp) + "' }";
236
else if constexpr (std::is_same_v<T, UserDefinedTypeFunctionError>)
237
stream << "UserDefinedTypeFunctionError { " << err.message << " }";
238
else if constexpr (std::is_same_v<T, BuiltInTypeFunctionError>)
239
stream << "BuiltInTypeFunctionError { " << toString(err.error) << " }";
240
else if constexpr (std::is_same_v<T, ReservedIdentifier>)
241
stream << "ReservedIdentifier { " << err.name << " }";
242
else if constexpr (std::is_same_v<T, CannotAssignToNever>)
243
{
244
stream << "CannotAssignToNever { rvalueType = '" << toString(err.rhsType) << "', reason = '" << err.reason << "', cause = { ";
245
246
bool first = true;
247
for (TypeId ty : err.cause)
248
{
249
if (first)
250
first = false;
251
else
252
stream << ", ";
253
254
stream << "'" << toString(ty) << "'";
255
}
256
257
stream << " } } ";
258
}
259
else if constexpr (std::is_same_v<T, UnexpectedArrayLikeTableItem>)
260
stream << "UnexpectedArrayLikeTableItem {}";
261
else if constexpr (std::is_same_v<T, CannotCheckDynamicStringFormatCalls>)
262
stream << "CannotCheckDynamicStringFormatCalls {}";
263
else if constexpr (std::is_same_v<T, GenericTypeCountMismatch>)
264
{
265
stream << "GenericTypeCountMismatch { subTyGenericCount = " << err.subTyGenericCount << ", superTyGenericCount = " << err.superTyGenericCount
266
<< " }";
267
}
268
else if constexpr (std::is_same_v<T, GenericTypePackCountMismatch>)
269
{
270
stream << "GenericTypePackCountMismatch { subTyGenericPackCount = " << err.subTyGenericPackCount
271
<< ", superTyGenericPackCount = " << err.superTyGenericPackCount << " }";
272
}
273
else if constexpr (std::is_same_v<T, MultipleNonviableOverloads>)
274
stream << "MultipleNonviableOverloads { attemptedArgCount = " << err.attemptedArgCount << " }";
275
else if constexpr (std::is_same_v<T, RecursiveRestraintViolation>)
276
stream << "RecursiveRestraintViolation";
277
else if constexpr (std::is_same_v<T, GenericBoundsMismatch>)
278
{
279
stream << "GenericBoundsMismatch { genericName = " << std::string{err.genericName} << ", lowerBounds = [";
280
for (size_t i = 0; i < err.lowerBounds.size(); ++i)
281
{
282
if (i > 0)
283
stream << ", ";
284
stream << toString(err.lowerBounds[i]);
285
}
286
stream << "], upperBounds = [";
287
for (size_t i = 0; i < err.upperBounds.size(); ++i)
288
{
289
if (i > 0)
290
stream << ", ";
291
stream << toString(err.upperBounds[i]);
292
}
293
stream << "] }";
294
}
295
else if constexpr (std::is_same_v<T, InstantiateGenericsOnNonFunction>)
296
stream << "InstantiateGenericsOnNonFunctionInstantiateGenericsOnNonFunction { interestingEdgeCase = " << err.interestingEdgeCase << " }";
297
else if constexpr (std::is_same_v<T, TypeInstantiationCountMismatch>)
298
stream << "TypeInstantiationCountMismatch { functionName = " << err.functionName.value_or("<unknown>")
299
<< ", functionType = " << toString(err.functionType) << ", providedTypes = " << err.providedTypes
300
<< ", maximumTypes = " << err.maximumTypes << ", providedTypePacks = " << err.providedTypePacks
301
<< ", maximumTypePacks = " << err.maximumTypePacks << " }";
302
else if constexpr (std::is_same_v<T, UnappliedTypeFunction>)
303
stream << "UnappliedTypeFunction {}";
304
else if constexpr (std::is_same_v<T, AmbiguousFunctionCall>)
305
stream << "AmbiguousFunctionCall { " << toString(err.function) << ", " << toString(err.arguments) << " }";
306
else
307
static_assert(always_false_v<T>, "Non-exhaustive type switch");
308
}
309
310
std::ostream& operator<<(std::ostream& stream, const CannotAssignToNever::Reason& reason)
311
{
312
switch (reason)
313
{
314
case CannotAssignToNever::Reason::PropertyNarrowed:
315
return stream << "PropertyNarrowed";
316
default:
317
return stream << "UnknownReason";
318
}
319
}
320
321
std::ostream& operator<<(std::ostream& stream, const InstantiateGenericsOnNonFunction::InterestingEdgeCase& edgeCase)
322
{
323
switch (edgeCase)
324
{
325
case InstantiateGenericsOnNonFunction::InterestingEdgeCase::None:
326
return stream << "None";
327
case InstantiateGenericsOnNonFunction::InterestingEdgeCase::MetatableCall:
328
return stream << "MetatableCall";
329
case InstantiateGenericsOnNonFunction::InterestingEdgeCase::Intersection:
330
return stream << "Intersection";
331
default:
332
LUAU_ASSERT(false);
333
return stream << "Unknown";
334
}
335
}
336
337
std::ostream& operator<<(std::ostream& stream, const TypeErrorData& data)
338
{
339
auto cb = [&](const auto& e)
340
{
341
return errorToString(stream, e);
342
};
343
visit(cb, data);
344
return stream;
345
}
346
347
std::ostream& operator<<(std::ostream& stream, const TypeError& error)
348
{
349
return stream << "TypeError { \"" << error.moduleName << "\", " << error.location << ", " << error.data << " }";
350
}
351
352
std::ostream& operator<<(std::ostream& stream, const TableState& tv)
353
{
354
return stream << static_cast<std::underlying_type<TableState>::type>(tv);
355
}
356
357
std::ostream& operator<<(std::ostream& stream, const Type& tv)
358
{
359
return stream << toString(tv);
360
}
361
362
std::ostream& operator<<(std::ostream& stream, const TypePackVar& tv)
363
{
364
return stream << toString(tv);
365
}
366
367
std::ostream& operator<<(std::ostream& stream, TypeId ty)
368
{
369
// we commonly use a null pointer when a type may not be present; we need to
370
// account for that here.
371
if (!ty)
372
return stream << "<nullptr>";
373
374
return stream << toString(ty);
375
}
376
377
std::ostream& operator<<(std::ostream& stream, TypePackId tp)
378
{
379
// we commonly use a null pointer when a type may not be present; we need to
380
// account for that here.
381
if (!tp)
382
return stream << "<nullptr>";
383
384
return stream << toString(tp);
385
}
386
387
namespace TypePath
388
{
389
390
std::ostream& operator<<(std::ostream& stream, const Path& path)
391
{
392
return stream << toString(path);
393
}
394
395
} // namespace TypePath
396
397
} // namespace Luau
398
399