Skip to content

Commit

Permalink
Sync to upstream/release/608 (#1145)
Browse files Browse the repository at this point in the history
# Old Solver:

- Fix a bug in the old solver where a user could use the keyword
`typeof` as the name of a type alias.
- Fix stringification of scientific notation to omit a trailing decimal
place when not followed by a digit e.g. `1.e+20` -> `1e+20`
# New Solver
- Continuing work on the New non-strict mode
- Introduce `keyof` and `rawkeyof` type function for acquiring the type
of all keys in a table or class
(luau-lang/rfcs#16)

---
Co-authored-by: Aaron Weiss <[email protected]>
Co-authored-by: Alexander McCord <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: Lily Brown <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
Co-authored-by: Vighnesh Vijay <[email protected]>

---------

Co-authored-by: Aaron Weiss <[email protected]>
Co-authored-by: Alexander McCord <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: David Cope <[email protected]>
Co-authored-by: Lily Brown <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
  • Loading branch information
8 people authored Jan 12, 2024
1 parent c0f5538 commit f31232d
Show file tree
Hide file tree
Showing 75 changed files with 3,122 additions and 816 deletions.
2 changes: 2 additions & 0 deletions Analysis/include/Luau/Substitution.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ struct TarjanNode
// https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
struct Tarjan
{
Tarjan();

// Vertices (types and type packs) are indexed, using pre-order traversal.
DenseHashMap<TypeId, int> typeToIndex{nullptr};
DenseHashMap<TypePackId, int> packToIndex{nullptr};
Expand Down
6 changes: 3 additions & 3 deletions Analysis/include/Luau/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
#include "Luau/Predicate.h"
#include "Luau/Unifiable.h"
#include "Luau/Variant.h"
#include "Luau/TypeFwd.h"
#include "Luau/VecDeque.h"

#include <atomic>
#include <deque>
#include <map>
#include <memory>
#include <optional>
Expand Down Expand Up @@ -768,6 +767,7 @@ bool isThread(TypeId ty);
bool isBuffer(TypeId ty);
bool isOptional(TypeId ty);
bool isTableIntersection(TypeId ty);
bool isTableUnion(TypeId ty);
bool isOverloadedFunction(TypeId ty);

// True when string is a subtype of ty
Expand Down Expand Up @@ -992,7 +992,7 @@ struct TypeIterator
// (T* t, size_t currentIndex)
using SavedIterInfo = std::pair<const T*, size_t>;

std::deque<SavedIterInfo> stack;
VecDeque<SavedIterInfo> stack;
DenseHashSet<const T*> seen{nullptr}; // Only needed to protect the iterator from hanging the thread.

void advance()
Expand Down
2 changes: 2 additions & 0 deletions Analysis/include/Luau/TypeFamily.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ struct BuiltinTypeFamilies
TypeFamily eqFamily;

TypeFamily refineFamily;
TypeFamily keyofFamily;
TypeFamily rawkeyofFamily;

void addToScope(NotNull<TypeArena> arena, NotNull<Scope> scope) const;
};
Expand Down
15 changes: 4 additions & 11 deletions Analysis/src/Autocomplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution);
LUAU_FASTFLAG(DebugLuauReadWriteProperties);
LUAU_FASTFLAG(LuauClipExtraHasEndProps);
LUAU_FASTFLAGVARIABLE(LuauAutocompleteDoEnd, false);
LUAU_FASTFLAGVARIABLE(LuauAutocompleteStringLiteralBounds, false);

static const std::unordered_set<std::string> kStatementStartingKeywords = {
Expand Down Expand Up @@ -1093,11 +1092,8 @@ static AutocompleteEntryMap autocompleteStatement(
result.emplace("end", AutocompleteEntry{AutocompleteEntryKind::Keyword});
else if (AstExprFunction* exprFunction = (*it)->as<AstExprFunction>(); exprFunction && !exprFunction->body->hasEnd)
result.emplace("end", AutocompleteEntry{AutocompleteEntryKind::Keyword});
if (FFlag::LuauAutocompleteDoEnd)
{
if (AstStatBlock* exprBlock = (*it)->as<AstStatBlock>(); exprBlock && !exprBlock->hasEnd)
result.emplace("end", AutocompleteEntry{AutocompleteEntryKind::Keyword});
}
if (AstStatBlock* exprBlock = (*it)->as<AstStatBlock>(); exprBlock && !exprBlock->hasEnd)
result.emplace("end", AutocompleteEntry{AutocompleteEntryKind::Keyword});
}
}
else
Expand All @@ -1114,11 +1110,8 @@ static AutocompleteEntryMap autocompleteStatement(
result.emplace("end", AutocompleteEntry{AutocompleteEntryKind::Keyword});
else if (AstExprFunction* exprFunction = (*it)->as<AstExprFunction>(); exprFunction && !exprFunction->DEPRECATED_hasEnd)
result.emplace("end", AutocompleteEntry{AutocompleteEntryKind::Keyword});
if (FFlag::LuauAutocompleteDoEnd)
{
if (AstStatBlock* exprBlock = (*it)->as<AstStatBlock>(); exprBlock && !exprBlock->hasEnd)
result.emplace("end", AutocompleteEntry{AutocompleteEntryKind::Keyword});
}
if (AstStatBlock* exprBlock = (*it)->as<AstStatBlock>(); exprBlock && !exprBlock->hasEnd)
result.emplace("end", AutocompleteEntry{AutocompleteEntryKind::Keyword});
}
}

Expand Down
15 changes: 14 additions & 1 deletion Analysis/src/BuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
* about a function that takes any number of values, but where each value must have some specific type.
*/

LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution)
LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution);
LUAU_FASTFLAGVARIABLE(LuauSetMetatableOnUnionsOfTables, false);

namespace Luau
{
Expand Down Expand Up @@ -963,6 +964,18 @@ static std::optional<WithPredicate<TypePackId>> magicFunctionSetMetaTable(
else if (get<AnyType>(target) || get<ErrorType>(target) || isTableIntersection(target))
{
}
else if (FFlag::LuauSetMetatableOnUnionsOfTables && isTableUnion(target))
{
const UnionType* ut = get<UnionType>(target);
LUAU_ASSERT(ut);

std::vector<TypeId> resultParts;

for (TypeId ty : ut)
resultParts.push_back(arena.addType(MetatableType{ty, mt}));

return WithPredicate<TypePackId>{arena.addTypePack({arena.addType(UnionType{std::move(resultParts)})})};
}
else
{
typechecker.reportError(TypeError{expr.location, GenericError{"setmetatable should take a table"}});
Expand Down
18 changes: 17 additions & 1 deletion Analysis/src/Clone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ class TypeCloner2
TypeId target = arena->addType(ty->ty);
asMutable(target)->documentationSymbol = ty->documentationSymbol;

if (auto generic = getMutable<GenericType>(target))
generic->scope = nullptr;
else if (auto free = getMutable<FreeType>(target))
free->scope = nullptr;
else if (auto fn = getMutable<FunctionType>(target))
fn->scope = nullptr;
else if (auto table = getMutable<TableType>(target))
table->scope = nullptr;

(*types)[ty] = target;
queue.push_back(target);
return target;
Expand All @@ -175,6 +184,11 @@ class TypeCloner2

TypePackId target = arena->addTypePack(tp->ty);

if (auto generic = getMutable<GenericTypePack>(target))
generic->scope = nullptr;
else if (auto free = getMutable<FreeTypePack>(target))
free->scope = nullptr;

(*packs)[tp] = target;
queue.push_back(target);
return target;
Expand Down Expand Up @@ -563,10 +577,12 @@ struct TypePackCloner
{
defaultClone(t);
}

void operator()(const GenericTypePack& t)
{
defaultClone(t);
}

void operator()(const ErrorTypePack& t)
{
defaultClone(t);
Expand Down Expand Up @@ -633,7 +649,7 @@ void TypeCloner::operator()(const FreeType& t)
{
if (FFlag::DebugLuauDeferredConstraintResolution)
{
FreeType ft{t.scope, clone(t.lowerBound, dest, cloneState), clone(t.upperBound, dest, cloneState)};
FreeType ft{nullptr, clone(t.lowerBound, dest, cloneState), clone(t.upperBound, dest, cloneState)};
TypeId res = dest.addType(ft);
seenTypes[typeId] = res;
}
Expand Down
32 changes: 30 additions & 2 deletions Analysis/src/ConstraintGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,11 @@ ControlFlow ConstraintGenerator::visitBlockWithoutChildScope(const ScopePtr& sco
continue;
}

// A type alias might have no name if the code is syntactically
// illegal. We mustn't prepopulate anything in this case.
if (alias->name == kParseNameError || alias->name == "typeof")
continue;

ScopePtr defnScope = childScope(alias, scope);

TypeId initialType = arena->addType(BlockedType{});
Expand Down Expand Up @@ -1084,6 +1089,15 @@ static bool occursCheck(TypeId needle, TypeId haystack)

ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatTypeAlias* alias)
{
if (alias->name == kParseNameError)
return ControlFlow::None;

if (alias->name == "typeof")
{
reportError(alias->location, GenericError{"Type aliases cannot be named typeof"});
return ControlFlow::None;
}

ScopePtr* defnScope = astTypeAliasDefiningScopes.find(alias);

std::unordered_map<Name, TypeFun>* typeBindings;
Expand Down Expand Up @@ -1516,10 +1530,24 @@ InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstExprCall*
LUAU_ASSERT(target);
LUAU_ASSERT(mt);

target = follow(target);

AstExpr* targetExpr = call->args.data[0];

MetatableType mtv{target, mt};
TypeId resultTy = arena->addType(mtv);
TypeId resultTy = nullptr;

if (isTableUnion(target))
{
const UnionType* targetUnion = get<UnionType>(target);
std::vector<TypeId> newParts;

for (TypeId ty : targetUnion)
newParts.push_back(arena->addType(MetatableType{ty, mt}));

resultTy = arena->addType(UnionType{std::move(newParts)});
}
else
resultTy = arena->addType(MetatableType{target, mt});

if (AstExprLocal* targetLocal = targetExpr->as<AstExprLocal>())
{
Expand Down
7 changes: 4 additions & 3 deletions Analysis/src/ConstraintSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "Luau/TypeFamily.h"
#include "Luau/TypeUtils.h"
#include "Luau/Unifier2.h"
#include "Luau/VecDeque.h"
#include "Luau/VisitType.h"
#include <algorithm>
#include <utility>
Expand Down Expand Up @@ -450,10 +451,10 @@ struct TypeAndLocation

struct FreeTypeSearcher : TypeOnceVisitor
{
std::deque<TypeAndLocation>* result;
VecDeque<TypeAndLocation>* result;
Location location;

FreeTypeSearcher(std::deque<TypeAndLocation>* result, Location location)
FreeTypeSearcher(VecDeque<TypeAndLocation>* result, Location location)
: result(result)
, location(location)
{
Expand Down Expand Up @@ -484,7 +485,7 @@ void ConstraintSolver::finalizeModule()

Unifier2 u2{NotNull{arena}, builtinTypes, rootScope, NotNull{&iceReporter}};

std::deque<TypeAndLocation> queue;
VecDeque<TypeAndLocation> queue;
for (auto& [name, binding] : rootScope->bindings)
queue.push_back({binding.typeId, binding.location});

Expand Down
1 change: 0 additions & 1 deletion Analysis/src/Def.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "Luau/Common.h"

#include <algorithm>
#include <deque>

namespace Luau
{
Expand Down
Loading

0 comments on commit f31232d

Please sign in to comment.