Skip to content

Commit

Permalink
Sync to upstream/release/516 (#397)
Browse files Browse the repository at this point in the history
  • Loading branch information
zeux authored Feb 24, 2022
1 parent 0bd2176 commit c7eca27
Show file tree
Hide file tree
Showing 47 changed files with 858 additions and 872 deletions.
9 changes: 2 additions & 7 deletions Analysis/include/Luau/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
#include <unordered_map>
#include <optional>

LUAU_FASTFLAG(LuauPrepopulateUnionOptionsBeforeAllocation)

namespace Luau
{

Expand Down Expand Up @@ -60,11 +58,8 @@ struct TypeArena
template<typename T>
TypeId addType(T tv)
{
if (FFlag::LuauPrepopulateUnionOptionsBeforeAllocation)
{
if constexpr (std::is_same_v<T, UnionTypeVar>)
LUAU_ASSERT(tv.options.size() >= 2);
}
if constexpr (std::is_same_v<T, UnionTypeVar>)
LUAU_ASSERT(tv.options.size() >= 2);

return addTV(TypeVar(std::move(tv)));
}
Expand Down
2 changes: 2 additions & 0 deletions Analysis/include/Luau/TypeInfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ bool doesCallError(const AstExprCall* call);
bool hasBreak(AstStat* node);
const AstStat* getFallthrough(const AstStat* node);

struct UnifierOptions;
struct Unifier;

// A substitution which replaces generic types in a given set by free types.
Expand Down Expand Up @@ -245,6 +246,7 @@ struct TypeChecker
* Treat any failures as type errors in the final typecheck report.
*/
bool unify(TypeId subTy, TypeId superTy, const Location& location);
bool unify(TypeId subTy, TypeId superTy, const Location& location, const UnifierOptions& options);
bool unify(TypePackId subTy, TypePackId superTy, const Location& location, CountMismatch::Context ctx = CountMismatch::Context::Arg);

/** Attempt to unify the types.
Expand Down
4 changes: 2 additions & 2 deletions Analysis/include/Luau/TypeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Luau

using ScopePtr = std::shared_ptr<struct Scope>;

std::optional<TypeId> findMetatableEntry(ErrorVec& errors, const ScopePtr& globalScope, TypeId type, std::string entry, Location location);
std::optional<TypeId> findTablePropertyRespectingMeta(ErrorVec& errors, const ScopePtr& globalScope, TypeId ty, Name name, Location location);
std::optional<TypeId> findMetatableEntry(ErrorVec& errors, TypeId type, std::string entry, Location location);
std::optional<TypeId> findTablePropertyRespectingMeta(ErrorVec& errors, TypeId ty, Name name, Location location);

} // namespace Luau
29 changes: 26 additions & 3 deletions Analysis/include/Luau/Unifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,31 @@ enum Variance
Invariant
};

// A substitution which replaces singleton types by their wider types
struct Widen : Substitution
{
Widen(TypeArena* arena)
: Substitution(TxnLog::empty(), arena)
{
}

bool isDirty(TypeId ty) override;
bool isDirty(TypePackId ty) override;
TypeId clean(TypeId ty) override;
TypePackId clean(TypePackId ty) override;
bool ignoreChildren(TypeId ty) override;
};

// TODO: Use this more widely.
struct UnifierOptions
{
bool isFunctionCall = false;
};

struct Unifier
{
TypeArena* const types;
Mode mode;
ScopePtr globalScope; // sigh. Needed solely to get at string's metatable.

DEPRECATED_TxnLog DEPRECATED_log;
TxnLog log;
Expand All @@ -34,9 +54,9 @@ struct Unifier

UnifierSharedState& sharedState;

Unifier(TypeArena* types, Mode mode, ScopePtr globalScope, const Location& location, Variance variance, UnifierSharedState& sharedState,
Unifier(TypeArena* types, Mode mode, const Location& location, Variance variance, UnifierSharedState& sharedState,
TxnLog* parentLog = nullptr);
Unifier(TypeArena* types, Mode mode, ScopePtr globalScope, std::vector<std::pair<TypeId, TypeId>>* sharedSeen, const Location& location,
Unifier(TypeArena* types, Mode mode, std::vector<std::pair<TypeId, TypeId>>* sharedSeen, const Location& location,
Variance variance, UnifierSharedState& sharedState, TxnLog* parentLog = nullptr);

// Test whether the two type vars unify. Never commits the result.
Expand Down Expand Up @@ -65,7 +85,10 @@ struct Unifier
void tryUnifyWithMetatable(TypeId subTy, TypeId superTy, bool reversed);
void tryUnifyWithClass(TypeId subTy, TypeId superTy, bool reversed);
void tryUnifyIndexer(const TableIndexer& subIndexer, const TableIndexer& superIndexer);

TypeId widen(TypeId ty);
TypeId deeplyOptional(TypeId ty, std::unordered_map<TypeId, TypeId> seen = {});

void cacheResult(TypeId subTy, TypeId superTy);

public:
Expand Down
4 changes: 2 additions & 2 deletions Analysis/src/Autocomplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,10 @@ static TypeCorrectKind checkTypeCorrectKind(const Module& module, TypeArena* typ
{
ty = follow(ty);

auto canUnify = [&typeArena, &module](TypeId subTy, TypeId superTy) {
auto canUnify = [&typeArena](TypeId subTy, TypeId superTy) {
InternalErrorReporter iceReporter;
UnifierSharedState unifierState(&iceReporter);
Unifier unifier(typeArena, Mode::Strict, module.getModuleScope(), Location(), Variance::Covariant, unifierState);
Unifier unifier(typeArena, Mode::Strict, Location(), Variance::Covariant, unifierState);

if (FFlag::LuauAutocompleteAvoidMutation && !FFlag::LuauUseCommittingTxnLog)
{
Expand Down
1 change: 1 addition & 0 deletions Analysis/src/Linter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ static bool similar(AstExpr* lhs, AstExpr* rhs)

return true;
}
CASE(AstExprIfElse) return similar(le->condition, re->condition) && similar(le->trueExpr, re->trueExpr) && similar(le->falseExpr, re->falseExpr);
else
{
LUAU_ASSERT(!"Unknown expression type");
Expand Down
27 changes: 6 additions & 21 deletions Analysis/src/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ LUAU_FASTFLAGVARIABLE(DebugLuauTrackOwningArena, false) // Remove with FFlagLuau
LUAU_FASTINTVARIABLE(LuauTypeCloneRecursionLimit, 300)
LUAU_FASTFLAG(LuauTypeAliasDefaults)
LUAU_FASTFLAG(LuauImmutableTypes)
LUAU_FASTFLAGVARIABLE(LuauPrepopulateUnionOptionsBeforeAllocation, false)

namespace Luau
{
Expand Down Expand Up @@ -379,28 +378,14 @@ void TypeCloner::operator()(const AnyTypeVar& t)

void TypeCloner::operator()(const UnionTypeVar& t)
{
if (FFlag::LuauPrepopulateUnionOptionsBeforeAllocation)
{
std::vector<TypeId> options;
options.reserve(t.options.size());

for (TypeId ty : t.options)
options.push_back(clone(ty, dest, seenTypes, seenTypePacks, cloneState));

TypeId result = dest.addType(UnionTypeVar{std::move(options)});
seenTypes[typeId] = result;
}
else
{
TypeId result = dest.addType(UnionTypeVar{});
seenTypes[typeId] = result;
std::vector<TypeId> options;
options.reserve(t.options.size());

UnionTypeVar* option = getMutable<UnionTypeVar>(result);
LUAU_ASSERT(option != nullptr);
for (TypeId ty : t.options)
options.push_back(clone(ty, dest, seenTypes, seenTypePacks, cloneState));

for (TypeId ty : t.options)
option->options.push_back(clone(ty, dest, seenTypes, seenTypePacks, cloneState));
}
TypeId result = dest.addType(UnionTypeVar{std::move(options)});
seenTypes[typeId] = result;
}

void TypeCloner::operator()(const IntersectionTypeVar& t)
Expand Down
8 changes: 8 additions & 0 deletions Analysis/src/Transpiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,14 @@ struct Printer
writer.symbol(")");
}
}
else if (const auto& a = typeAnnotation.as<AstTypeSingletonBool>())
{
writer.keyword(a->value ? "true" : "false");
}
else if (const auto& a = typeAnnotation.as<AstTypeSingletonString>())
{
writer.string(std::string_view(a->value.data, a->value.size));
}
else if (typeAnnotation.is<AstTypeError>())
{
writer.symbol("%error-type%");
Expand Down
67 changes: 42 additions & 25 deletions Analysis/src/TypeInfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification, false)
LUAU_FASTFLAGVARIABLE(LuauRecursiveTypeParameterRestriction, false)
LUAU_FASTFLAGVARIABLE(LuauGenericFunctionsDontCacheTypeParams, false)
LUAU_FASTFLAGVARIABLE(LuauImmutableTypes, false)
LUAU_FASTFLAGVARIABLE(LuauNoSealedTypeMod, false)
LUAU_FASTFLAGVARIABLE(LuauQuantifyInPlace2, false)
LUAU_FASTFLAGVARIABLE(LuauSealExports, false)
LUAU_FASTFLAGVARIABLE(LuauSingletonTypes, false)
Expand All @@ -38,14 +37,14 @@ LUAU_FASTFLAGVARIABLE(LuauTypeAliasDefaults, false)
LUAU_FASTFLAGVARIABLE(LuauExpectedTypesOfProperties, false)
LUAU_FASTFLAGVARIABLE(LuauErrorRecoveryType, false)
LUAU_FASTFLAGVARIABLE(LuauPropertiesGetExpectedType, false)
LUAU_FASTFLAGVARIABLE(LuauProperTypeLevels, false)
LUAU_FASTFLAGVARIABLE(LuauAscribeCorrectLevelToInferredProperitesOfFreeTables, false)
LUAU_FASTFLAG(LuauUnionTagMatchFix)
LUAU_FASTFLAGVARIABLE(LuauUnsealedTableLiteral, false)
LUAU_FASTFLAGVARIABLE(LuauTwoPassAliasDefinitionFix, false)
LUAU_FASTFLAGVARIABLE(LuauAssertStripsFalsyTypes, false)
LUAU_FASTFLAGVARIABLE(LuauReturnAnyInsteadOfICE, false) // Eventually removed as false.
LUAU_FASTFLAGVARIABLE(LuauAnotherTypeLevelFix, false)
LUAU_FASTFLAG(LuauWidenIfSupertypeIsFree)
LUAU_FASTFLAGVARIABLE(LuauDoNotTryToReduce, false)

namespace Luau
{
Expand Down Expand Up @@ -1125,7 +1124,7 @@ void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funSco

ty = follow(ty);

if (tableSelf && (FFlag::LuauNoSealedTypeMod ? tableSelf->state != TableState::Sealed : !selfTy->persistent))
if (tableSelf && tableSelf->state != TableState::Sealed)
tableSelf->props[indexName->index.value] = {ty, /* deprecated */ false, {}, indexName->indexLocation};

const FunctionTypeVar* funTy = get<FunctionTypeVar>(ty);
Expand All @@ -1138,7 +1137,7 @@ void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funSco

checkFunctionBody(funScope, ty, *function.func);

if (tableSelf && (FFlag::LuauNoSealedTypeMod ? tableSelf->state != TableState::Sealed : !selfTy->persistent))
if (tableSelf && tableSelf->state != TableState::Sealed)
tableSelf->props[indexName->index.value] = {
follow(quantify(funScope, ty, indexName->indexLocation)), /* deprecated */ false, {}, indexName->indexLocation};
}
Expand Down Expand Up @@ -1210,8 +1209,7 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatTypeAlias& typealias
{
ScopePtr aliasScope = childScope(scope, typealias.location);
aliasScope->level = scope->level.incr();
if (FFlag::LuauProperTypeLevels)
aliasScope->level.subLevel = subLevel;
aliasScope->level.subLevel = subLevel;

auto [generics, genericPacks] =
createGenericTypes(aliasScope, scope->level, typealias, typealias.generics, typealias.genericPacks, /* useCache = */ true);
Expand Down Expand Up @@ -1624,15 +1622,15 @@ ExprResult<TypeId> TypeChecker::checkExpr(const ScopePtr& scope, const AstExprIn
std::optional<TypeId> TypeChecker::findTablePropertyRespectingMeta(TypeId lhsType, Name name, const Location& location)
{
ErrorVec errors;
auto result = Luau::findTablePropertyRespectingMeta(errors, globalScope, lhsType, name, location);
auto result = Luau::findTablePropertyRespectingMeta(errors, lhsType, name, location);
reportErrors(errors);
return result;
}

std::optional<TypeId> TypeChecker::findMetatableEntry(TypeId type, std::string entry, const Location& location)
{
ErrorVec errors;
auto result = Luau::findMetatableEntry(errors, globalScope, type, entry, location);
auto result = Luau::findMetatableEntry(errors, type, entry, location);
reportErrors(errors);
return result;
}
Expand Down Expand Up @@ -1751,13 +1749,23 @@ std::optional<TypeId> TypeChecker::getIndexTypeFromType(
return std::nullopt;
}

// TODO(amccord): Write some logic to correctly handle intersections. CLI-34659
std::vector<TypeId> result = reduceUnion(parts);
if (FFlag::LuauDoNotTryToReduce)
{
if (parts.size() == 1)
return parts[0];

if (result.size() == 1)
return result[0];
return addType(IntersectionTypeVar{std::move(parts)}); // Not at all correct.
}
else
{
// TODO(amccord): Write some logic to correctly handle intersections. CLI-34659
std::vector<TypeId> result = reduceUnion(parts);

return addType(IntersectionTypeVar{result});
if (result.size() == 1)
return result[0];

return addType(IntersectionTypeVar{result});
}
}

if (addErrors)
Expand Down Expand Up @@ -2823,10 +2831,7 @@ TypeId TypeChecker::checkLValueBinding(const ScopePtr& scope, const AstExprIndex
TypeId TypeChecker::checkFunctionName(const ScopePtr& scope, AstExpr& funName, TypeLevel level)
{
auto freshTy = [&]() {
if (FFlag::LuauProperTypeLevels)
return freshType(level);
else
return freshType(scope);
return freshType(level);
};

if (auto globalName = funName.as<AstExprGlobal>())
Expand Down Expand Up @@ -3790,7 +3795,14 @@ std::optional<ExprResult<TypePackId>> TypeChecker::checkCallOverload(const Scope
// has been instantiated, so is a monotype. We can therefore
// unify it with a monomorphic function.
TypeId r = addType(FunctionTypeVar(scope->level, argPack, retPack));
unify(fn, r, expr.location);
if (FFlag::LuauWidenIfSupertypeIsFree)
{
UnifierOptions options;
options.isFunctionCall = true;
unify(r, fn, expr.location, options);
}
else
unify(fn, r, expr.location);
return {{retPack}};
}

Expand Down Expand Up @@ -4243,9 +4255,15 @@ TypeId TypeChecker::anyIfNonstrict(TypeId ty) const
}

bool TypeChecker::unify(TypeId subTy, TypeId superTy, const Location& location)
{
UnifierOptions options;
return unify(subTy, superTy, location, options);
}

bool TypeChecker::unify(TypeId subTy, TypeId superTy, const Location& location, const UnifierOptions& options)
{
Unifier state = mkUnifier(location);
state.tryUnify(subTy, superTy);
state.tryUnify(subTy, superTy, options.isFunctionCall);

if (FFlag::LuauUseCommittingTxnLog)
state.log.commit();
Expand Down Expand Up @@ -4654,7 +4672,7 @@ void TypeChecker::diagnoseMissingTableKey(UnknownProperty* utk, TypeErrorData& d
}
};

if (auto ttv = getTableType(FFlag::LuauUnionTagMatchFix ? utk->table : follow(utk->table)))
if (auto ttv = getTableType(utk->table))
accumulate(ttv->props);
else if (auto ctv = get<ClassTypeVar>(follow(utk->table)))
{
Expand Down Expand Up @@ -4691,8 +4709,7 @@ ScopePtr TypeChecker::childFunctionScope(const ScopePtr& parent, const Location&
ScopePtr TypeChecker::childScope(const ScopePtr& parent, const Location& location)
{
ScopePtr scope = std::make_shared<Scope>(parent);
if (FFlag::LuauProperTypeLevels)
scope->level = parent->level;
scope->level = parent->level;
scope->varargPack = parent->varargPack;

currentModule->scopes.push_back(std::make_pair(location, scope));
Expand Down Expand Up @@ -4724,7 +4741,7 @@ void TypeChecker::merge(RefinementMap& l, const RefinementMap& r)

Unifier TypeChecker::mkUnifier(const Location& location)
{
return Unifier{&currentModule->internalTypes, currentModule->mode, globalScope, location, Variance::Covariant, unifierState};
return Unifier{&currentModule->internalTypes, currentModule->mode, location, Variance::Covariant, unifierState};
}

TypeId TypeChecker::freshType(const ScopePtr& scope)
Expand Down Expand Up @@ -5444,7 +5461,7 @@ GenericTypeDefinitions TypeChecker::createGenericTypes(const ScopePtr& scope, st

void TypeChecker::refineLValue(const LValue& lvalue, RefinementMap& refis, const ScopePtr& scope, TypeIdPredicate predicate)
{
LUAU_ASSERT(FFlag::LuauDiscriminableUnions2);
LUAU_ASSERT(FFlag::LuauDiscriminableUnions2 || FFlag::LuauAssertStripsFalsyTypes);

const LValue* target = &lvalue;
std::optional<LValue> key; // If set, we know we took the base of the lvalue path and should be walking down each option of the base's type.
Expand Down
Loading

0 comments on commit c7eca27

Please sign in to comment.