2021-10-29 21:25:12 +01:00
|
|
|
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
|
|
#include "Luau/Module.h"
|
|
|
|
|
2022-04-07 22:29:01 +01:00
|
|
|
#include "Luau/Clone.h"
|
2022-04-15 00:57:43 +01:00
|
|
|
#include "Luau/Common.h"
|
2022-06-03 23:15:45 +01:00
|
|
|
#include "Luau/ConstraintGraphBuilder.h"
|
2022-04-15 00:57:43 +01:00
|
|
|
#include "Luau/Normalize.h"
|
2021-12-03 06:41:04 +00:00
|
|
|
#include "Luau/RecursionCounter.h"
|
2021-11-05 02:34:35 +00:00
|
|
|
#include "Luau/Scope.h"
|
2021-10-29 21:25:12 +01:00
|
|
|
#include "Luau/TypeInfer.h"
|
|
|
|
#include "Luau/TypePack.h"
|
|
|
|
#include "Luau/TypeVar.h"
|
|
|
|
#include "Luau/VisitTypeVar.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2022-05-20 01:02:24 +01:00
|
|
|
LUAU_FASTFLAG(LuauLowerBoundsCalculation);
|
|
|
|
LUAU_FASTFLAG(LuauNormalizeFlagIsConservative);
|
2022-06-03 23:15:45 +01:00
|
|
|
LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution);
|
2022-07-21 22:16:54 +01:00
|
|
|
LUAU_FASTFLAGVARIABLE(LuauForceExportSurfacesToBeNormal, false);
|
2022-01-27 23:46:05 +00:00
|
|
|
|
2021-10-29 21:25:12 +01:00
|
|
|
namespace Luau
|
|
|
|
{
|
|
|
|
|
|
|
|
static bool contains(Position pos, Comment comment)
|
|
|
|
{
|
|
|
|
if (comment.location.contains(pos))
|
|
|
|
return true;
|
2021-12-10 22:05:05 +00:00
|
|
|
else if (comment.type == Lexeme::BrokenComment &&
|
2021-10-29 21:25:12 +01:00
|
|
|
comment.location.begin <= pos) // Broken comments are broken specifically because they don't have an end
|
|
|
|
return true;
|
|
|
|
else if (comment.type == Lexeme::Comment && comment.location.end == pos)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isWithinComment(const SourceModule& sourceModule, Position pos)
|
|
|
|
{
|
|
|
|
auto iter = std::lower_bound(sourceModule.commentLocations.begin(), sourceModule.commentLocations.end(),
|
|
|
|
Comment{Lexeme::Comment, Location{pos, pos}}, [](const Comment& a, const Comment& b) {
|
|
|
|
return a.location.end < b.location.end;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (iter == sourceModule.commentLocations.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (contains(pos, *iter))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Due to the nature of std::lower_bound, it is possible that iter points at a comment that ends
|
|
|
|
// at pos. We'll try the next comment, if it exists.
|
|
|
|
++iter;
|
|
|
|
if (iter == sourceModule.commentLocations.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return contains(pos, *iter);
|
|
|
|
}
|
|
|
|
|
2022-05-20 01:02:24 +01:00
|
|
|
struct ForceNormal : TypeVarOnceVisitor
|
2021-10-29 21:25:12 +01:00
|
|
|
{
|
2022-05-26 23:08:16 +01:00
|
|
|
const TypeArena* typeArena = nullptr;
|
|
|
|
|
|
|
|
ForceNormal(const TypeArena* typeArena)
|
|
|
|
: typeArena(typeArena)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-05-20 01:02:24 +01:00
|
|
|
bool visit(TypeId ty) override
|
|
|
|
{
|
2022-05-26 23:08:16 +01:00
|
|
|
if (ty->owningArena != typeArena)
|
|
|
|
return false;
|
|
|
|
|
2022-05-20 01:02:24 +01:00
|
|
|
asMutable(ty)->normal = true;
|
|
|
|
return true;
|
|
|
|
}
|
2021-10-29 21:25:12 +01:00
|
|
|
|
2022-05-20 01:02:24 +01:00
|
|
|
bool visit(TypeId ty, const FreeTypeVar& ftv) override
|
|
|
|
{
|
|
|
|
visit(ty);
|
|
|
|
return true;
|
|
|
|
}
|
2021-10-29 21:25:12 +01:00
|
|
|
|
2022-05-20 01:02:24 +01:00
|
|
|
bool visit(TypePackId tp, const FreeTypePack& ftp) override
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
2021-10-29 21:25:12 +01:00
|
|
|
|
|
|
|
Module::~Module()
|
|
|
|
{
|
|
|
|
unfreeze(interfaceTypes);
|
|
|
|
unfreeze(internalTypes);
|
|
|
|
}
|
|
|
|
|
2022-05-20 01:02:24 +01:00
|
|
|
void Module::clonePublicInterface(InternalErrorReporter& ice)
|
2021-10-29 21:25:12 +01:00
|
|
|
{
|
|
|
|
LUAU_ASSERT(interfaceTypes.typeVars.empty());
|
|
|
|
LUAU_ASSERT(interfaceTypes.typePacks.empty());
|
|
|
|
|
2021-12-03 06:41:04 +00:00
|
|
|
CloneState cloneState;
|
2021-10-29 21:25:12 +01:00
|
|
|
|
2022-06-03 23:15:45 +01:00
|
|
|
ScopePtr moduleScope = FFlag::DebugLuauDeferredConstraintResolution ? nullptr : getModuleScope();
|
|
|
|
Scope2* moduleScope2 = FFlag::DebugLuauDeferredConstraintResolution ? getModuleScope2() : nullptr;
|
2021-10-29 21:25:12 +01:00
|
|
|
|
2022-06-03 23:15:45 +01:00
|
|
|
TypePackId returnType = FFlag::DebugLuauDeferredConstraintResolution ? moduleScope2->returnType : moduleScope->returnType;
|
|
|
|
std::optional<TypePackId> varargPack = FFlag::DebugLuauDeferredConstraintResolution ? std::nullopt : moduleScope->varargPack;
|
|
|
|
std::unordered_map<Name, TypeFun>* exportedTypeBindings =
|
|
|
|
FFlag::DebugLuauDeferredConstraintResolution ? nullptr : &moduleScope->exportedTypeBindings;
|
|
|
|
|
|
|
|
returnType = clone(returnType, interfaceTypes, cloneState);
|
|
|
|
|
|
|
|
if (moduleScope)
|
|
|
|
{
|
|
|
|
moduleScope->returnType = returnType;
|
|
|
|
if (varargPack)
|
|
|
|
{
|
|
|
|
varargPack = clone(*varargPack, interfaceTypes, cloneState);
|
|
|
|
moduleScope->varargPack = varargPack;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LUAU_ASSERT(moduleScope2);
|
|
|
|
moduleScope2->returnType = returnType; // TODO varargPack
|
|
|
|
}
|
2022-04-15 00:57:43 +01:00
|
|
|
|
2022-07-21 22:16:54 +01:00
|
|
|
ForceNormal forceNormal{&interfaceTypes};
|
|
|
|
|
2022-04-15 00:57:43 +01:00
|
|
|
if (FFlag::LuauLowerBoundsCalculation)
|
|
|
|
{
|
2022-06-03 23:15:45 +01:00
|
|
|
normalize(returnType, interfaceTypes, ice);
|
2022-07-21 22:16:54 +01:00
|
|
|
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
|
|
|
forceNormal.traverse(returnType);
|
2022-06-03 23:15:45 +01:00
|
|
|
if (varargPack)
|
2022-07-21 22:16:54 +01:00
|
|
|
{
|
2022-06-03 23:15:45 +01:00
|
|
|
normalize(*varargPack, interfaceTypes, ice);
|
2022-07-21 22:16:54 +01:00
|
|
|
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
|
|
|
forceNormal.traverse(*varargPack);
|
|
|
|
}
|
2022-04-15 00:57:43 +01:00
|
|
|
}
|
2021-10-29 21:25:12 +01:00
|
|
|
|
2022-06-03 23:15:45 +01:00
|
|
|
if (exportedTypeBindings)
|
2022-04-15 00:57:43 +01:00
|
|
|
{
|
2022-06-03 23:15:45 +01:00
|
|
|
for (auto& [name, tf] : *exportedTypeBindings)
|
2022-05-20 01:02:24 +01:00
|
|
|
{
|
2022-06-03 23:15:45 +01:00
|
|
|
tf = clone(tf, interfaceTypes, cloneState);
|
|
|
|
if (FFlag::LuauLowerBoundsCalculation)
|
2022-05-20 01:02:24 +01:00
|
|
|
{
|
2022-06-03 23:15:45 +01:00
|
|
|
normalize(tf.type, interfaceTypes, ice);
|
|
|
|
|
|
|
|
if (FFlag::LuauNormalizeFlagIsConservative)
|
|
|
|
{
|
|
|
|
// We're about to freeze the memory. We know that the flag is conservative by design. Cyclic tables
|
|
|
|
// won't be marked normal. If the types aren't normal by now, they never will be.
|
|
|
|
forceNormal.traverse(tf.type);
|
2022-07-21 22:16:54 +01:00
|
|
|
for (GenericTypeDefinition param : tf.typeParams)
|
|
|
|
{
|
|
|
|
forceNormal.traverse(param.ty);
|
|
|
|
|
|
|
|
if (param.defaultValue)
|
|
|
|
{
|
|
|
|
normalize(*param.defaultValue, interfaceTypes, ice);
|
|
|
|
forceNormal.traverse(*param.defaultValue);
|
|
|
|
}
|
|
|
|
}
|
2022-06-03 23:15:45 +01:00
|
|
|
}
|
2022-05-20 01:02:24 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-15 00:57:43 +01:00
|
|
|
}
|
2021-10-29 21:25:12 +01:00
|
|
|
|
2022-06-03 23:15:45 +01:00
|
|
|
for (TypeId ty : returnType)
|
2022-04-15 00:57:43 +01:00
|
|
|
{
|
2021-10-29 21:25:12 +01:00
|
|
|
if (get<GenericTypeVar>(follow(ty)))
|
2022-04-15 00:57:43 +01:00
|
|
|
{
|
|
|
|
auto t = asMutable(ty);
|
|
|
|
t->ty = AnyTypeVar{};
|
|
|
|
t->normal = true;
|
|
|
|
}
|
|
|
|
}
|
2021-10-29 21:25:12 +01:00
|
|
|
|
2022-04-21 22:44:27 +01:00
|
|
|
for (auto& [name, ty] : declaredGlobals)
|
2022-03-18 00:46:04 +00:00
|
|
|
{
|
2022-04-21 22:44:27 +01:00
|
|
|
ty = clone(ty, interfaceTypes, cloneState);
|
|
|
|
if (FFlag::LuauLowerBoundsCalculation)
|
2022-07-21 22:16:54 +01:00
|
|
|
{
|
2022-04-21 22:44:27 +01:00
|
|
|
normalize(ty, interfaceTypes, ice);
|
2022-07-21 22:16:54 +01:00
|
|
|
|
|
|
|
if (FFlag::LuauForceExportSurfacesToBeNormal)
|
|
|
|
forceNormal.traverse(ty);
|
|
|
|
}
|
2022-03-18 00:46:04 +00:00
|
|
|
}
|
|
|
|
|
2021-10-29 21:25:12 +01:00
|
|
|
freeze(internalTypes);
|
|
|
|
freeze(interfaceTypes);
|
2022-05-20 01:02:24 +01:00
|
|
|
}
|
2021-10-29 21:25:12 +01:00
|
|
|
|
2022-05-20 01:02:24 +01:00
|
|
|
ScopePtr Module::getModuleScope() const
|
|
|
|
{
|
|
|
|
LUAU_ASSERT(!scopes.empty());
|
|
|
|
return scopes.front().second;
|
2021-10-29 21:25:12 +01:00
|
|
|
}
|
|
|
|
|
2022-06-03 23:15:45 +01:00
|
|
|
Scope2* Module::getModuleScope2() const
|
|
|
|
{
|
|
|
|
LUAU_ASSERT(!scope2s.empty());
|
|
|
|
return scope2s.front().second.get();
|
|
|
|
}
|
|
|
|
|
2021-10-29 21:25:12 +01:00
|
|
|
} // namespace Luau
|