Skip to content

Commit

Permalink
Sync to upstream/release/595
Browse files Browse the repository at this point in the history
  • Loading branch information
andyfriesen committed Sep 15, 2023
1 parent 8e28c24 commit d8b97f4
Show file tree
Hide file tree
Showing 61 changed files with 1,251 additions and 582 deletions.
7 changes: 4 additions & 3 deletions Analysis/include/Luau/ConstraintGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ struct ConstraintGraphBuilder

DcrLogger* logger;

ConstraintGraphBuilder(ModulePtr module, NotNull<Normalizer> normalizer, NotNull<ModuleResolver> moduleResolver, NotNull<BuiltinTypes> builtinTypes,
NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope, std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope,
DcrLogger* logger, NotNull<DataFlowGraph> dfg, std::vector<RequireCycle> requireCycles);
ConstraintGraphBuilder(ModulePtr module, NotNull<Normalizer> normalizer, NotNull<ModuleResolver> moduleResolver,
NotNull<BuiltinTypes> builtinTypes, NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope,
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope, DcrLogger* logger, NotNull<DataFlowGraph> dfg,
std::vector<RequireCycle> requireCycles);

/**
* Fabricates a new free type belonging to a given scope.
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/GlobalTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ struct GlobalTypes
ScopePtr globalScope; // shared by all modules
};

}
} // namespace Luau
7 changes: 4 additions & 3 deletions Analysis/include/Luau/Instantiation.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ struct TypeCheckLimits;
// A substitution which replaces generic types in a given set by free types.
struct ReplaceGenerics : Substitution
{
ReplaceGenerics(const TxnLog* log, TypeArena* arena, NotNull<BuiltinTypes> builtinTypes, TypeLevel level, Scope* scope, const std::vector<TypeId>& generics,
const std::vector<TypePackId>& genericPacks)
ReplaceGenerics(const TxnLog* log, TypeArena* arena, NotNull<BuiltinTypes> builtinTypes, TypeLevel level, Scope* scope,
const std::vector<TypeId>& generics, const std::vector<TypePackId>& genericPacks)
: Substitution(log, arena)
, builtinTypes(builtinTypes)
, level(level)
Expand Down Expand Up @@ -77,6 +77,7 @@ struct Instantiation : Substitution
* Instantiation fails only when processing the type causes internal recursion
* limits to be exceeded.
*/
std::optional<TypeId> instantiate(NotNull<BuiltinTypes> builtinTypes, NotNull<TypeArena> arena, NotNull<TypeCheckLimits> limits, NotNull<Scope> scope, TypeId ty);
std::optional<TypeId> instantiate(
NotNull<BuiltinTypes> builtinTypes, NotNull<TypeArena> arena, NotNull<TypeCheckLimits> limits, NotNull<Scope> scope, TypeId ty);

} // namespace Luau
94 changes: 59 additions & 35 deletions Analysis/include/Luau/Subtyping.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,18 @@ class TypeIds;
class Normalizer;
struct NormalizedType;
struct NormalizedClassType;
struct NormalizedStringType;
struct NormalizedFunctionType;


struct SubtypingResult
{
// Did the test succeed?
bool isSubtype = false;
bool isErrorSuppressing = false;
bool normalizationTooComplex = false;

// If so, what constraints are implied by this relation?
// If not, what happened?

void andAlso(const SubtypingResult& other);
void orElse(const SubtypingResult& other);
SubtypingResult& andAlso(const SubtypingResult& other);
SubtypingResult& orElse(const SubtypingResult& other);

// Only negates the `isSubtype`.
static SubtypingResult negate(const SubtypingResult& result);
Expand All @@ -47,6 +45,8 @@ struct Subtyping
NotNull<Normalizer> normalizer;
NotNull<InternalErrorReporter> iceReporter;

NotNull<Scope> scope;

enum class Variance
{
Covariant,
Expand All @@ -72,6 +72,12 @@ struct Subtyping

SeenSet seenTypes;

Subtyping(const Subtyping&) = delete;
Subtyping& operator=(const Subtyping&) = delete;

Subtyping(Subtyping&&) = default;
Subtyping& operator=(Subtyping&&) = default;

// TODO cache
// TODO cyclic types
// TODO recursion limits
Expand All @@ -80,43 +86,61 @@ struct Subtyping
SubtypingResult isSubtype(TypePackId subTy, TypePackId superTy);

private:
SubtypingResult isSubtype_(TypeId subTy, TypeId superTy);
SubtypingResult isSubtype_(TypePackId subTy, TypePackId superTy);
SubtypingResult isCovariantWith(TypeId subTy, TypeId superTy);
SubtypingResult isCovariantWith(TypePackId subTy, TypePackId superTy);

template<typename SubTy, typename SuperTy>
SubtypingResult isContravariantWith(SubTy&& subTy, SuperTy&& superTy);

template<typename SubTy, typename SuperTy>
SubtypingResult isInvariantWith(SubTy&& subTy, SuperTy&& superTy);

template<typename SubTy, typename SuperTy>
SubtypingResult isCovariantWith(const TryPair<const SubTy*, const SuperTy*>& pair);

template<typename SubTy, typename SuperTy>
SubtypingResult isContravariantWith(const TryPair<const SubTy*, const SuperTy*>& pair);

template<typename SubTy, typename SuperTy>
SubtypingResult isSubtype_(const TryPair<const SubTy*, const SuperTy*>& pair);

SubtypingResult isSubtype_(TypeId subTy, const UnionType* superUnion);
SubtypingResult isSubtype_(const UnionType* subUnion, TypeId superTy);
SubtypingResult isSubtype_(TypeId subTy, const IntersectionType* superIntersection);
SubtypingResult isSubtype_(const IntersectionType* subIntersection, TypeId superTy);
SubtypingResult isSubtype_(const PrimitiveType* subPrim, const PrimitiveType* superPrim);
SubtypingResult isSubtype_(const SingletonType* subSingleton, const PrimitiveType* superPrim);
SubtypingResult isSubtype_(const SingletonType* subSingleton, const SingletonType* superSingleton);
SubtypingResult isSubtype_(const TableType* subTable, const TableType* superTable);
SubtypingResult isSubtype_(const MetatableType* subMt, const MetatableType* superMt);
SubtypingResult isSubtype_(const MetatableType* subMt, const TableType* superTable);
SubtypingResult isSubtype_(const ClassType* subClass, const ClassType* superClass);
SubtypingResult isSubtype_(const ClassType* subClass, const TableType* superTable); // Actually a class <: shape.
SubtypingResult isSubtype_(const FunctionType* subFunction, const FunctionType* superFunction);
SubtypingResult isSubtype_(const PrimitiveType* subPrim, const TableType* superTable);
SubtypingResult isSubtype_(const SingletonType* subSingleton, const TableType* superTable);

SubtypingResult isSubtype_(const NormalizedType* subNorm, const NormalizedType* superNorm);
SubtypingResult isSubtype_(const NormalizedClassType& subClass, const NormalizedClassType& superClass, const TypeIds& superTables);
SubtypingResult isSubtype_(const NormalizedFunctionType& subFunction, const NormalizedFunctionType& superFunction);
SubtypingResult isSubtype_(const TypeIds& subTypes, const TypeIds& superTypes);

SubtypingResult isSubtype_(const VariadicTypePack* subVariadic, const VariadicTypePack* superVariadic);
SubtypingResult isInvariantWith(const TryPair<const SubTy*, const SuperTy*>& pair);

SubtypingResult isCovariantWith(TypeId subTy, const UnionType* superUnion);
SubtypingResult isCovariantWith(const UnionType* subUnion, TypeId superTy);
SubtypingResult isCovariantWith(TypeId subTy, const IntersectionType* superIntersection);
SubtypingResult isCovariantWith(const IntersectionType* subIntersection, TypeId superTy);

SubtypingResult isCovariantWith(const NegationType* subNegation, TypeId superTy);
SubtypingResult isCovariantWith(const TypeId subTy, const NegationType* superNegation);

SubtypingResult isCovariantWith(const PrimitiveType* subPrim, const PrimitiveType* superPrim);
SubtypingResult isCovariantWith(const SingletonType* subSingleton, const PrimitiveType* superPrim);
SubtypingResult isCovariantWith(const SingletonType* subSingleton, const SingletonType* superSingleton);
SubtypingResult isCovariantWith(const TableType* subTable, const TableType* superTable);
SubtypingResult isCovariantWith(const MetatableType* subMt, const MetatableType* superMt);
SubtypingResult isCovariantWith(const MetatableType* subMt, const TableType* superTable);
SubtypingResult isCovariantWith(const ClassType* subClass, const ClassType* superClass);
SubtypingResult isCovariantWith(const ClassType* subClass, const TableType* superTable);
SubtypingResult isCovariantWith(const FunctionType* subFunction, const FunctionType* superFunction);
SubtypingResult isCovariantWith(const PrimitiveType* subPrim, const TableType* superTable);
SubtypingResult isCovariantWith(const SingletonType* subSingleton, const TableType* superTable);

SubtypingResult isCovariantWith(const NormalizedType* subNorm, const NormalizedType* superNorm);
SubtypingResult isCovariantWith(const NormalizedClassType& subClass, const NormalizedClassType& superClass);
SubtypingResult isCovariantWith(const NormalizedClassType& subClass, const TypeIds& superTables);
SubtypingResult isCovariantWith(const NormalizedStringType& subString, const NormalizedStringType& superString);
SubtypingResult isCovariantWith(const NormalizedStringType& subString, const TypeIds& superTables);
SubtypingResult isCovariantWith(const NormalizedFunctionType& subFunction, const NormalizedFunctionType& superFunction);
SubtypingResult isCovariantWith(const TypeIds& subTypes, const TypeIds& superTypes);

SubtypingResult isCovariantWith(const VariadicTypePack* subVariadic, const VariadicTypePack* superVariadic);

bool bindGeneric(TypeId subTp, TypeId superTp);
bool bindGeneric(TypePackId subTp, TypePackId superTp);

template <typename T, typename Container>
template<typename T, typename Container>
TypeId makeAggregateType(const Container& container, TypeId orElse);

[[noreturn]]
void unexpected(TypePackId tp);
[[noreturn]] void unexpected(TypePackId tp);
};

} // namespace Luau
12 changes: 12 additions & 0 deletions Analysis/include/Luau/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,18 @@ bool isSubclass(const ClassType* cls, const ClassType* parent);

Type* asMutable(TypeId ty);

template<typename... Ts, typename T>
bool is(T&& tv)
{
if (!tv)
return false;

if constexpr (std::is_same_v<TypeId, T> && !(std::is_same_v<BoundType, Ts> || ...))
LUAU_ASSERT(get_if<BoundType>(&tv->ty) == nullptr);

return (get<Ts>(tv) || ...);
}

template<typename T>
const T* get(TypeId tv)
{
Expand Down
4 changes: 2 additions & 2 deletions Analysis/include/Luau/TypeChecker2.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct DcrLogger;
struct TypeCheckLimits;
struct UnifierSharedState;

void check(NotNull<BuiltinTypes> builtinTypes, NotNull<UnifierSharedState> sharedState, NotNull<TypeCheckLimits> limits, DcrLogger* logger, const SourceModule& sourceModule,
Module* module);
void check(NotNull<BuiltinTypes> builtinTypes, NotNull<UnifierSharedState> sharedState, NotNull<TypeCheckLimits> limits, DcrLogger* logger,
const SourceModule& sourceModule, Module* module);

} // namespace Luau
3 changes: 2 additions & 1 deletion Analysis/include/Luau/TypeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ ErrorSuppression shouldSuppressErrors(NotNull<Normalizer> normalizer, TypePackId
// Similar to `std::optional<std::pair<A, B>>`, but whose `sizeof()` is the same as `std::pair<A, B>`
// and cooperates with C++'s `if (auto p = ...)` syntax without the extra fatness of `std::optional`.
template<typename A, typename B>
struct TryPair {
struct TryPair
{
A first;
B second;

Expand Down
6 changes: 4 additions & 2 deletions Analysis/include/Luau/Unifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,12 @@ struct Unifier
* Populate the vector errors with any type errors that may arise.
* Populate the transaction log with the set of TypeIds that need to be reset to undo the unification attempt.
*/
void tryUnify(TypeId subTy, TypeId superTy, bool isFunctionCall = false, bool isIntersection = false, const LiteralProperties* aliasableMap = nullptr);
void tryUnify(
TypeId subTy, TypeId superTy, bool isFunctionCall = false, bool isIntersection = false, const LiteralProperties* aliasableMap = nullptr);

private:
void tryUnify_(TypeId subTy, TypeId superTy, bool isFunctionCall = false, bool isIntersection = false, const LiteralProperties* aliasableMap = nullptr);
void tryUnify_(
TypeId subTy, TypeId superTy, bool isFunctionCall = false, bool isIntersection = false, const LiteralProperties* aliasableMap = nullptr);
void tryUnifyUnionWithType(TypeId subTy, const UnionType* uv, TypeId superTy);

// Traverse the two types provided and block on any BlockedTypes we find.
Expand Down
4 changes: 2 additions & 2 deletions Analysis/include/Luau/Unifier2.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ struct Unifier2
bool unify(TypePackId subTp, TypePackId superTp);

std::optional<TypeId> generalize(NotNull<Scope> scope, TypeId ty);
private:

private:
/**
* @returns simplify(left | right)
*/
Expand All @@ -72,4 +72,4 @@ struct Unifier2
OccursCheckResult occursCheck(DenseHashSet<TypePackId>& seen, TypePackId needle, TypePackId haystack);
};

}
} // namespace Luau
17 changes: 16 additions & 1 deletion Analysis/include/Luau/VisitType.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

LUAU_FASTINT(LuauVisitRecursionLimit)
LUAU_FASTFLAG(LuauBoundLazyTypes2)
LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution)
LUAU_FASTFLAG(DebugLuauReadWriteProperties)

namespace Luau
Expand Down Expand Up @@ -220,7 +221,21 @@ struct GenericTypeVisitor
traverse(btv->boundTo);
}
else if (auto ftv = get<FreeType>(ty))
visit(ty, *ftv);
{
if (FFlag::DebugLuauDeferredConstraintResolution)
{
if (visit(ty, *ftv))
{
LUAU_ASSERT(ftv->lowerBound);
traverse(ftv->lowerBound);

LUAU_ASSERT(ftv->upperBound);
traverse(ftv->upperBound);
}
}
else
visit(ty, *ftv);
}
else if (auto gtv = get<GenericType>(ty))
visit(ty, *gtv);
else if (auto etv = get<ErrorType>(ty))
Expand Down
29 changes: 9 additions & 20 deletions Analysis/src/Autocomplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,20 +282,8 @@ static void autocompleteProps(const Module& module, TypeArena* typeArena, NotNul
ParenthesesRecommendation parens =
indexType == PropIndexType::Key ? ParenthesesRecommendation::None : getParenRecommendation(type, nodes, typeCorrect);

result[name] = AutocompleteEntry{
AutocompleteEntryKind::Property,
type,
prop.deprecated,
isWrongIndexer(type),
typeCorrect,
containingClass,
&prop,
prop.documentationSymbol,
{},
parens,
{},
indexType == PropIndexType::Colon
};
result[name] = AutocompleteEntry{AutocompleteEntryKind::Property, type, prop.deprecated, isWrongIndexer(type), typeCorrect,
containingClass, &prop, prop.documentationSymbol, {}, parens, {}, indexType == PropIndexType::Colon};
}
}
};
Expand Down Expand Up @@ -606,7 +594,7 @@ std::optional<TypeId> getLocalTypeInScopeAt(const Module& module, Position posit
return {};
}

template <typename T>
template<typename T>
static std::optional<std::string> tryToStringDetailed(const ScopePtr& scope, T ty, bool functionTypeArguments)
{
ToStringOptions opts;
Expand Down Expand Up @@ -1418,7 +1406,7 @@ static std::string makeAnonymous(const ScopePtr& scope, const FunctionType& func
name = "a" + std::to_string(argIdx);

if (std::optional<Name> type = tryGetTypeNameInScope(scope, args[argIdx], true))
result += name + ": " + *type;
result += name + ": " + *type;
else
result += name;
}
Expand All @@ -1434,7 +1422,7 @@ static std::string makeAnonymous(const ScopePtr& scope, const FunctionType& func
if (std::optional<std::string> res = tryToStringDetailed(scope, pack->ty, true))
varArgType = std::move(res);
}

if (varArgType)
result += "...: " + *varArgType;
else
Expand All @@ -1461,7 +1449,8 @@ static std::string makeAnonymous(const ScopePtr& scope, const FunctionType& func
return result;
}

static std::optional<AutocompleteEntry> makeAnonymousAutofilled(const ModulePtr& module, Position position, const AstNode* node, const std::vector<AstNode*>& ancestry)
static std::optional<AutocompleteEntry> makeAnonymousAutofilled(
const ModulePtr& module, Position position, const AstNode* node, const std::vector<AstNode*>& ancestry)
{
const AstExprCall* call = node->as<AstExprCall>();
if (!call && ancestry.size() > 1)
Expand Down Expand Up @@ -1498,10 +1487,10 @@ static std::optional<AutocompleteEntry> makeAnonymousAutofilled(const ModulePtr&
auto [args, tail] = flatten(outerFunction->argTypes);
if (argument < args.size())
argType = args[argument];

if (!argType)
return std::nullopt;

TypeId followed = follow(*argType);
const FunctionType* type = get<FunctionType>(followed);
if (!type)
Expand Down
2 changes: 1 addition & 1 deletion Analysis/src/Clone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ void TypeCloner::operator()(const UnionType& t)
// We're just using this FreeType as a placeholder until we've finished
// cloning the parts of this union so it is okay that its bounds are
// nullptr. We'll never indirect them.
TypeId result = dest.addType(FreeType{nullptr, /*lowerBound*/nullptr, /*upperBound*/nullptr});
TypeId result = dest.addType(FreeType{nullptr, /*lowerBound*/ nullptr, /*upperBound*/ nullptr});
seenTypes[typeId] = result;

std::vector<TypeId> options;
Expand Down
22 changes: 11 additions & 11 deletions Analysis/src/ConstraintGraphBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,17 +420,17 @@ void ConstraintGraphBuilder::applyRefinements(const ScopePtr& scope, Location lo
{
switch (shouldSuppressErrors(normalizer, ty))
{
case ErrorSuppression::DoNotSuppress:
ty = simplifyIntersection(builtinTypes, arena, ty, dt).result;
break;
case ErrorSuppression::Suppress:
ty = simplifyIntersection(builtinTypes, arena, ty, dt).result;
ty = simplifyUnion(builtinTypes, arena, ty, builtinTypes->errorType).result;
break;
case ErrorSuppression::NormalizationFailed:
reportError(location, NormalizationTooComplex{});
ty = simplifyIntersection(builtinTypes, arena, ty, dt).result;
break;
case ErrorSuppression::DoNotSuppress:
ty = simplifyIntersection(builtinTypes, arena, ty, dt).result;
break;
case ErrorSuppression::Suppress:
ty = simplifyIntersection(builtinTypes, arena, ty, dt).result;
ty = simplifyUnion(builtinTypes, arena, ty, builtinTypes->errorType).result;
break;
case ErrorSuppression::NormalizationFailed:
reportError(location, NormalizationTooComplex{});
ty = simplifyIntersection(builtinTypes, arena, ty, dt).result;
break;
}
}
}
Expand Down
Loading

0 comments on commit d8b97f4

Please sign in to comment.