2021-10-29 13:25:12 -07: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 13:53:47 -07:00
|
|
|
#include "Luau/Clone.h"
|
2022-04-14 14:57:15 -07:00
|
|
|
#include "Luau/Common.h"
|
2023-11-03 12:47:28 -07:00
|
|
|
#include "Luau/ConstraintGenerator.h"
|
2022-04-14 14:57:15 -07:00
|
|
|
#include "Luau/Normalize.h"
|
2021-12-02 15:20:08 -08:00
|
|
|
#include "Luau/RecursionCounter.h"
|
2021-11-04 19:07:18 -07:00
|
|
|
#include "Luau/Scope.h"
|
2023-01-06 18:07:19 +02:00
|
|
|
#include "Luau/Type.h"
|
2021-10-29 13:25:12 -07:00
|
|
|
#include "Luau/TypeInfer.h"
|
|
|
|
#include "Luau/TypePack.h"
|
2023-01-03 19:33:19 +02:00
|
|
|
#include "Luau/VisitType.h"
|
2021-10-29 13:25:12 -07:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2022-06-03 13:32:20 -07:00
|
|
|
LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution);
|
2024-07-11 15:13:45 -07:00
|
|
|
LUAU_FASTFLAGVARIABLE(LuauSkipEmptyInstantiations, false);
|
2022-01-27 13:29:34 -08:00
|
|
|
|
2021-10-29 13:25:12 -07:00
|
|
|
namespace Luau
|
|
|
|
{
|
|
|
|
|
|
|
|
static bool contains(Position pos, Comment comment)
|
|
|
|
{
|
|
|
|
if (comment.location.contains(pos))
|
|
|
|
return true;
|
2021-12-10 13:17:10 -08:00
|
|
|
else if (comment.type == Lexeme::BrokenComment &&
|
2021-10-29 13:25:12 -07: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;
|
|
|
|
}
|
|
|
|
|
2023-04-14 15:05:27 +03:00
|
|
|
static bool isWithinComment(const std::vector<Comment>& commentLocations, Position pos)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
2023-04-14 15:05:27 +03:00
|
|
|
auto iter = std::lower_bound(
|
|
|
|
commentLocations.begin(), commentLocations.end(), Comment{Lexeme::Comment, Location{pos, pos}}, [](const Comment& a, const Comment& b) {
|
2021-10-29 13:25:12 -07:00
|
|
|
return a.location.end < b.location.end;
|
|
|
|
});
|
|
|
|
|
2023-04-14 15:05:27 +03:00
|
|
|
if (iter == commentLocations.end())
|
2021-10-29 13:25:12 -07:00
|
|
|
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;
|
2023-04-14 15:05:27 +03:00
|
|
|
if (iter == commentLocations.end())
|
2021-10-29 13:25:12 -07:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return contains(pos, *iter);
|
|
|
|
}
|
|
|
|
|
2023-04-14 15:05:27 +03:00
|
|
|
bool isWithinComment(const SourceModule& sourceModule, Position pos)
|
|
|
|
{
|
|
|
|
return isWithinComment(sourceModule.commentLocations, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isWithinComment(const ParseResult& result, Position pos)
|
|
|
|
{
|
|
|
|
return isWithinComment(result.commentLocations, pos);
|
|
|
|
}
|
|
|
|
|
2022-08-11 13:42:54 -07:00
|
|
|
struct ClonePublicInterface : Substitution
|
|
|
|
{
|
2023-01-03 19:33:19 +02:00
|
|
|
NotNull<BuiltinTypes> builtinTypes;
|
2022-08-11 13:42:54 -07:00
|
|
|
NotNull<Module> module;
|
|
|
|
|
2023-01-03 19:33:19 +02:00
|
|
|
ClonePublicInterface(const TxnLog* log, NotNull<BuiltinTypes> builtinTypes, Module* module)
|
2022-08-11 13:42:54 -07:00
|
|
|
: Substitution(log, &module->interfaceTypes)
|
2023-01-03 19:33:19 +02:00
|
|
|
, builtinTypes(builtinTypes)
|
2022-08-11 13:42:54 -07:00
|
|
|
, module(module)
|
|
|
|
{
|
|
|
|
LUAU_ASSERT(module);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isDirty(TypeId ty) override
|
|
|
|
{
|
|
|
|
if (ty->owningArena == &module->internalTypes)
|
|
|
|
return true;
|
|
|
|
|
2023-01-03 19:33:19 +02:00
|
|
|
if (const FunctionType* ftv = get<FunctionType>(ty))
|
2022-08-11 13:42:54 -07:00
|
|
|
return ftv->level.level != 0;
|
2023-01-03 19:33:19 +02:00
|
|
|
if (const TableType* ttv = get<TableType>(ty))
|
2022-08-11 13:42:54 -07:00
|
|
|
return ttv->level.level != 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isDirty(TypePackId tp) override
|
|
|
|
{
|
|
|
|
return tp->owningArena == &module->internalTypes;
|
|
|
|
}
|
|
|
|
|
2023-05-25 23:46:51 +03:00
|
|
|
bool ignoreChildrenVisit(TypeId ty) override
|
|
|
|
{
|
2023-07-14 08:57:16 -07:00
|
|
|
if (ty->owningArena != &module->internalTypes)
|
2023-05-25 23:46:51 +03:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ignoreChildrenVisit(TypePackId tp) override
|
|
|
|
{
|
2023-07-14 08:57:16 -07:00
|
|
|
if (tp->owningArena != &module->internalTypes)
|
2023-05-25 23:46:51 +03:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-08-11 13:42:54 -07:00
|
|
|
TypeId clean(TypeId ty) override
|
|
|
|
{
|
|
|
|
TypeId result = clone(ty);
|
|
|
|
|
2023-01-03 19:33:19 +02:00
|
|
|
if (FunctionType* ftv = getMutable<FunctionType>(result))
|
2024-07-11 15:13:45 -07:00
|
|
|
{
|
|
|
|
if (FFlag::LuauSkipEmptyInstantiations && ftv->generics.empty() && ftv->genericPacks.empty())
|
|
|
|
{
|
|
|
|
GenericTypeFinder marker;
|
|
|
|
marker.traverse(result);
|
|
|
|
|
|
|
|
if (!marker.found)
|
|
|
|
ftv->hasNoFreeOrGenericTypes = true;
|
|
|
|
}
|
|
|
|
|
2022-08-11 13:42:54 -07:00
|
|
|
ftv->level = TypeLevel{0, 0};
|
2024-07-11 15:13:45 -07:00
|
|
|
}
|
2023-01-03 19:33:19 +02:00
|
|
|
else if (TableType* ttv = getMutable<TableType>(result))
|
2024-07-11 15:13:45 -07:00
|
|
|
{
|
2022-08-11 13:42:54 -07:00
|
|
|
ttv->level = TypeLevel{0, 0};
|
2024-07-11 15:13:45 -07:00
|
|
|
}
|
2022-08-11 13:42:54 -07:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
TypePackId clean(TypePackId tp) override
|
|
|
|
{
|
|
|
|
return clone(tp);
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeId cloneType(TypeId ty)
|
|
|
|
{
|
|
|
|
std::optional<TypeId> result = substitute(ty);
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
return *result;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
module->errors.push_back(TypeError{module->scopes[0].first, UnificationTooComplex{}});
|
2023-01-03 19:33:19 +02:00
|
|
|
return builtinTypes->errorRecoveryType();
|
2022-08-11 13:42:54 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TypePackId cloneTypePack(TypePackId tp)
|
|
|
|
{
|
|
|
|
std::optional<TypePackId> result = substitute(tp);
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
return *result;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
module->errors.push_back(TypeError{module->scopes[0].first, UnificationTooComplex{}});
|
2023-01-03 19:33:19 +02:00
|
|
|
return builtinTypes->errorRecoveryTypePack();
|
2022-08-11 13:42:54 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeFun cloneTypeFun(const TypeFun& tf)
|
|
|
|
{
|
|
|
|
std::vector<GenericTypeDefinition> typeParams;
|
|
|
|
std::vector<GenericTypePackDefinition> typePackParams;
|
|
|
|
|
|
|
|
for (GenericTypeDefinition typeParam : tf.typeParams)
|
|
|
|
{
|
|
|
|
TypeId ty = cloneType(typeParam.ty);
|
|
|
|
std::optional<TypeId> defaultValue;
|
|
|
|
|
|
|
|
if (typeParam.defaultValue)
|
|
|
|
defaultValue = cloneType(*typeParam.defaultValue);
|
|
|
|
|
|
|
|
typeParams.push_back(GenericTypeDefinition{ty, defaultValue});
|
|
|
|
}
|
|
|
|
|
|
|
|
for (GenericTypePackDefinition typePackParam : tf.typePackParams)
|
|
|
|
{
|
|
|
|
TypePackId tp = cloneTypePack(typePackParam.tp);
|
|
|
|
std::optional<TypePackId> defaultValue;
|
|
|
|
|
|
|
|
if (typePackParam.defaultValue)
|
|
|
|
defaultValue = cloneTypePack(*typePackParam.defaultValue);
|
|
|
|
|
|
|
|
typePackParams.push_back(GenericTypePackDefinition{tp, defaultValue});
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeId type = cloneType(tf.type);
|
|
|
|
|
|
|
|
return TypeFun{typeParams, typePackParams, type};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-10-29 13:25:12 -07:00
|
|
|
Module::~Module()
|
|
|
|
{
|
|
|
|
unfreeze(interfaceTypes);
|
|
|
|
unfreeze(internalTypes);
|
|
|
|
}
|
|
|
|
|
2023-01-03 19:33:19 +02:00
|
|
|
void Module::clonePublicInterface(NotNull<BuiltinTypes> builtinTypes, InternalErrorReporter& ice)
|
2021-10-29 13:25:12 -07:00
|
|
|
{
|
2023-08-11 15:55:30 +03:00
|
|
|
CloneState cloneState{builtinTypes};
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-07-28 20:41:13 -07:00
|
|
|
ScopePtr moduleScope = getModuleScope();
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-07-28 20:41:13 -07:00
|
|
|
TypePackId returnType = moduleScope->returnType;
|
2022-06-03 13:32:20 -07:00
|
|
|
std::optional<TypePackId> varargPack = FFlag::DebugLuauDeferredConstraintResolution ? std::nullopt : moduleScope->varargPack;
|
|
|
|
|
2022-08-11 13:42:54 -07:00
|
|
|
TxnLog log;
|
2023-01-03 19:33:19 +02:00
|
|
|
ClonePublicInterface clonePublicInterface{&log, builtinTypes, this};
|
2022-08-11 13:42:54 -07:00
|
|
|
|
2023-07-14 08:57:16 -07:00
|
|
|
returnType = clonePublicInterface.cloneTypePack(returnType);
|
2022-06-03 13:32:20 -07:00
|
|
|
|
2022-07-28 20:41:13 -07:00
|
|
|
moduleScope->returnType = returnType;
|
|
|
|
if (varargPack)
|
2022-06-03 13:32:20 -07:00
|
|
|
{
|
2023-07-14 08:57:16 -07:00
|
|
|
varargPack = clonePublicInterface.cloneTypePack(*varargPack);
|
2022-07-28 20:41:13 -07:00
|
|
|
moduleScope->varargPack = varargPack;
|
2022-06-03 13:32:20 -07:00
|
|
|
}
|
2022-04-14 14:57:15 -07:00
|
|
|
|
2023-01-06 18:07:19 +02:00
|
|
|
for (auto& [name, tf] : moduleScope->exportedTypeBindings)
|
2022-04-14 14:57:15 -07:00
|
|
|
{
|
2023-07-14 08:57:16 -07:00
|
|
|
tf = clonePublicInterface.cloneTypeFun(tf);
|
2022-04-14 14:57:15 -07:00
|
|
|
}
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2022-04-21 14:04:22 -07:00
|
|
|
for (auto& [name, ty] : declaredGlobals)
|
2022-03-17 17:06:25 -07:00
|
|
|
{
|
2023-07-14 08:57:16 -07:00
|
|
|
ty = clonePublicInterface.cloneType(ty);
|
2022-03-17 17:06:25 -07:00
|
|
|
}
|
|
|
|
|
2023-01-06 18:07:19 +02:00
|
|
|
// Copy external stuff over to Module itself
|
2023-02-10 10:50:54 -08:00
|
|
|
this->returnType = moduleScope->returnType;
|
2023-05-19 11:59:59 -07:00
|
|
|
this->exportedTypeBindings = moduleScope->exportedTypeBindings;
|
2022-05-19 16:46:52 -07:00
|
|
|
}
|
2021-10-29 13:25:12 -07:00
|
|
|
|
2023-01-06 18:07:19 +02:00
|
|
|
bool Module::hasModuleScope() const
|
|
|
|
{
|
|
|
|
return !scopes.empty();
|
|
|
|
}
|
|
|
|
|
2022-05-19 16:46:52 -07:00
|
|
|
ScopePtr Module::getModuleScope() const
|
|
|
|
{
|
2023-01-06 18:07:19 +02:00
|
|
|
LUAU_ASSERT(hasModuleScope());
|
2022-05-19 16:46:52 -07:00
|
|
|
return scopes.front().second;
|
2021-10-29 13:25:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Luau
|