Skip to content

Commit

Permalink
Sync to upstream/release/653 (#1541)
Browse files Browse the repository at this point in the history
## What's Changed?

* Optimized the vector dot product by up to 24%
* Allow for x/y/z/X/Y/Z vector field access by registering a `vector`
metatable
with an `__index` method (Fixes #1521)
* Fixed a bug preventing consistent recovery from parse errors in table
types.
* Optimized `k*n` and `k+n` when types are known
* Allow fragment autocomplete to handle cases like the automatic
insertion of
parens, keywords, strings, etc., while maintaining a correct relative
positioning

### New Solver

* Allow for `nil` assignment to tables and classes with indexers

---------

Co-authored-by: Aaron Weiss <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Vighnesh Vijay <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
  • Loading branch information
8 people authored Nov 22, 2024
1 parent 7a6142e commit d19a5f0
Show file tree
Hide file tree
Showing 67 changed files with 783 additions and 407 deletions.
16 changes: 15 additions & 1 deletion Analysis/include/Luau/ConstraintGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,25 @@ struct ConstraintGenerator
Inference check(const ScopePtr& scope, AstExprFunction* func, std::optional<TypeId> expectedType, bool generalize);
Inference check(const ScopePtr& scope, AstExprUnary* unary);
Inference check(const ScopePtr& scope, AstExprBinary* binary, std::optional<TypeId> expectedType);
Inference checkAstExprBinary(
const ScopePtr& scope,
const Location& location,
AstExprBinary::Op op,
AstExpr* left,
AstExpr* right,
std::optional<TypeId> expectedType
);
Inference check(const ScopePtr& scope, AstExprIfElse* ifElse, std::optional<TypeId> expectedType);
Inference check(const ScopePtr& scope, AstExprTypeAssertion* typeAssert);
Inference check(const ScopePtr& scope, AstExprInterpString* interpString);
Inference check(const ScopePtr& scope, AstExprTable* expr, std::optional<TypeId> expectedType);
std::tuple<TypeId, TypeId, RefinementId> checkBinary(const ScopePtr& scope, AstExprBinary* binary, std::optional<TypeId> expectedType);
std::tuple<TypeId, TypeId, RefinementId> checkBinary(
const ScopePtr& scope,
AstExprBinary::Op op,
AstExpr* left,
AstExpr* right,
std::optional<TypeId> expectedType
);

void visitLValue(const ScopePtr& scope, AstExpr* expr, TypeId rhsType);
void visitLValue(const ScopePtr& scope, AstExprLocal* local, TypeId rhsType);
Expand Down
24 changes: 22 additions & 2 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,25 @@ struct HashInstantiationSignature
size_t operator()(const InstantiationSignature& signature) const;
};


struct TablePropLookupResult
{
// What types are we blocked on for determining this type?
std::vector<TypeId> blockedTypes;
// The type of the property (if we were able to determine it).
std::optional<TypeId> propType;
// Whether or not this is _definitely_ derived as the result of an indexer.
// We use this to determine whether or not code like:
//
// t.lol = nil;
//
// ... is legal. If `t: { [string]: ~nil }` then this is legal as
// there's no guarantee on whether "lol" specifically exists.
// However, if `t: { lol: ~nil }`, then we cannot allow assignment as
// that would remove "lol" from the table entirely.
bool isIndex = false;
};

struct ConstraintSolver
{
NotNull<TypeArena> arena;
Expand Down Expand Up @@ -211,15 +230,16 @@ struct ConstraintSolver
// for a, ... in next_function, t, ... do
bool tryDispatchIterableFunction(TypeId nextTy, TypeId tableTy, const IterableConstraint& c, NotNull<const Constraint> constraint);

std::pair<std::vector<TypeId>, std::optional<TypeId>> lookupTableProp(
TablePropLookupResult lookupTableProp(
NotNull<const Constraint> constraint,
TypeId subjectType,
const std::string& propName,
ValueContext context,
bool inConditional = false,
bool suppressSimplification = false
);
std::pair<std::vector<TypeId>, std::optional<TypeId>> lookupTableProp(

TablePropLookupResult lookupTableProp(
NotNull<const Constraint> constraint,
TypeId subjectType,
const std::string& propName,
Expand Down
3 changes: 1 addition & 2 deletions Analysis/include/Luau/DataFlowGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ struct DfgScope

DfgScope* parent;
ScopeType scopeType;
Location location;

using Bindings = DenseHashMap<Symbol, const Def*>;
using Props = DenseHashMap<const Def*, std::unordered_map<std::string, const Def*>>;
Expand Down Expand Up @@ -156,7 +155,7 @@ struct DataFlowGraphBuilder
DenseHashMap<Symbol, FunctionCapture> captures{Symbol{}};
void resolveCaptures();

DfgScope* makeChildScope(Location loc, DfgScope::ScopeType scopeType = DfgScope::Linear);
DfgScope* makeChildScope(DfgScope::ScopeType scopeType = DfgScope::Linear);

void join(DfgScope* p, DfgScope* a, DfgScope* b);
void joinBindings(DfgScope* p, const DfgScope& a, const DfgScope& b);
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/Instantiation2.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct Replacer : Substitution
};

// A substitution which replaces generic functions by monomorphic functions
struct Instantiation2 : Substitution
struct Instantiation2 final : Substitution
{
// Mapping from generic types to free types to be used in instantiation.
DenseHashMap<TypeId, TypeId> genericSubstitutions{nullptr};
Expand Down
3 changes: 0 additions & 3 deletions Analysis/include/Luau/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ struct Module

TypePackId returnType = nullptr;
std::unordered_map<Name, TypeFun> exportedTypeBindings;
// We also need to keep DFG data alive between runs
std::shared_ptr<DataFlowGraph> dataFlowGraph = nullptr;
std::vector<std::unique_ptr<DfgScope>> dfgScopes;

bool hasModuleScope() const;
ScopePtr getModuleScope() const;
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ struct NegationType
TypeId ty;
};

using ErrorType = Unifiable::Error;
using ErrorType = Unifiable::Error<TypeId>;

using TypeVariant = Unifiable::Variant<
TypeId,
Expand Down
2 changes: 1 addition & 1 deletion Analysis/include/Luau/TypePack.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct GenericTypePack
};

using BoundTypePack = Unifiable::Bound<TypePackId>;
using ErrorTypePack = Unifiable::Error;
using ErrorTypePack = Unifiable::Error<TypePackId>;

using TypePackVariant =
Unifiable::Variant<TypePackId, FreeTypePack, GenericTypePack, TypePack, VariadicTypePack, BlockedTypePack, TypeFunctionInstanceTypePack>;
Expand Down
15 changes: 13 additions & 2 deletions Analysis/include/Luau/Unifiable.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "Luau/Variant.h"

#include <optional>
#include <string>

namespace Luau
Expand Down Expand Up @@ -94,19 +95,29 @@ struct Bound
Id boundTo;
};

template<typename Id>
struct Error
{
// This constructor has to be public, since it's used in Type and TypePack,
// but shouldn't be called directly. Please use errorRecoveryType() instead.
Error();
explicit Error();

explicit Error(Id synthetic)
: synthetic{synthetic}
{
}

int index;

// This is used to create an error that can be rendered out using this field
// as appropriate metadata for communicating it to the user.
std::optional<Id> synthetic;

private:
static int nextIndex;
};

template<typename Id, typename... Value>
using Variant = Luau::Variant<Bound<Id>, Error, Value...>;
using Variant = Luau::Variant<Bound<Id>, Error<Id>, Value...>;

} // namespace Luau::Unifiable
5 changes: 2 additions & 3 deletions Analysis/include/Luau/VisitType.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "Type.h"

LUAU_FASTINT(LuauVisitRecursionLimit)
LUAU_FASTFLAG(LuauBoundLazyTypes2)
LUAU_FASTFLAG(LuauSolverV2)

namespace Luau
Expand Down Expand Up @@ -190,7 +189,7 @@ struct GenericTypeVisitor
{
return visit(tp);
}
virtual bool visit(TypePackId tp, const Unifiable::Error& etp)
virtual bool visit(TypePackId tp, const ErrorTypePack& etp)
{
return visit(tp);
}
Expand Down Expand Up @@ -461,7 +460,7 @@ struct GenericTypeVisitor
else if (auto gtv = get<GenericTypePack>(tp))
visit(tp, *gtv);

else if (auto etv = get<Unifiable::Error>(tp))
else if (auto etv = get<ErrorTypePack>(tp))
visit(tp, *etv);

else if (auto pack = get<TypePack>(tp))
Expand Down
8 changes: 6 additions & 2 deletions Analysis/src/Clone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,7 @@ class TypeCloner
LUAU_ASSERT(!"Item holds neither TypeId nor TypePackId when enqueuing its children?");
}

// ErrorType and ErrorTypePack is an alias to this type.
void cloneChildren(Unifiable::Error* t)
void cloneChildren(ErrorType* t)
{
// noop.
}
Expand Down Expand Up @@ -428,6 +427,11 @@ class TypeCloner
t->boundTo = shallowClone(t->boundTo);
}

void cloneChildren(ErrorTypePack* t)
{
// noop.
}

void cloneChildren(VariadicTypePack* t)
{
t->ty = shallowClone(t->ty);
Expand Down
Loading

0 comments on commit d19a5f0

Please sign in to comment.