Skip to content

Commit

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

- Improve readability of unions and intersections by limiting the number
of elements of those types that can be presented on a single line (gated
under `FFlag::LuauToStringSimpleCompositeTypesSingleLine`)
- Adds a new option to the compiler `--record-stats` to record and
output compilation statistics
- `if...then...else` expressions are now optimized into `AND/OR` form
when possible.

### VM

- Add a new `buffer` type to Luau based on the [buffer
RFC](luau-lang/luau#739) and additional C API
functions to work with it; this release does not include the library.
- Internal C API to work with string buffers has been updated to align
with Lua version more closely

### Native Codegen

- Added support for new X64 instruction (rev) and new A64 instruction
(bswap) in the assembler
- Simplified the way numerical loop condition is translated to IR

### New Type Solver

- Operator inference now handled by type families
- Created a new system called `Type Paths` to explain why subtyping
tests fail in order to improve the quality of error messages.
- Systematic changes to implement Data Flow analysis in the new solver
(`Breadcrumb` removed and replaced with `RefinementKey`)

---
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: Vighnesh Vijay <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>

---------

Co-authored-by: Arseny Kapoulkine <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Lily Brown <[email protected]>
Co-authored-by: Aaron Weiss <[email protected]>
Co-authored-by: Alexander McCord <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
  • Loading branch information
8 people authored Oct 21, 2023
1 parent f318745 commit 113dd61
Show file tree
Hide file tree
Showing 128 changed files with 4,707 additions and 1,461 deletions.
4 changes: 2 additions & 2 deletions Analysis/include/Luau/Anyification.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "Luau/NotNull.h"
#include "Luau/Substitution.h"
#include "Luau/Type.h"
#include "Luau/TypeFwd.h"

#include <memory>

Expand Down Expand Up @@ -39,4 +39,4 @@ struct Anyification : Substitution
bool ignoreChildren(TypePackId ty) override;
};

} // namespace Luau
} // namespace Luau
2 changes: 1 addition & 1 deletion Analysis/include/Luau/ApplyTypeFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include "Luau/Substitution.h"
#include "Luau/TxnLog.h"
#include "Luau/Type.h"
#include "Luau/TypeFwd.h"

namespace Luau
{
Expand Down
4 changes: 1 addition & 3 deletions Analysis/include/Luau/AstQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "Luau/Ast.h"
#include "Luau/Documentation.h"
#include "Luau/TypeFwd.h"

#include <memory>

Expand All @@ -13,9 +14,6 @@ struct Binding;
struct SourceModule;
struct Module;

struct Type;
using TypeId = const Type*;

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

struct ExprOrLocal
Expand Down
75 changes: 0 additions & 75 deletions Analysis/include/Luau/Breadcrumb.h

This file was deleted.

56 changes: 20 additions & 36 deletions Analysis/include/Luau/Constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#include "Luau/Ast.h" // Used for some of the enumerations
#include "Luau/DenseHash.h"
#include "Luau/NotNull.h"
#include "Luau/Type.h"
#include "Luau/Variant.h"
#include "Luau/TypeFwd.h"

#include <string>
#include <memory>
Expand All @@ -16,12 +16,6 @@ namespace Luau

struct Scope;

struct Type;
using TypeId = const Type*;

struct TypePackVar;
using TypePackId = const TypePackVar*;

// subType <: superType
struct SubtypeConstraint
{
Expand Down Expand Up @@ -55,31 +49,6 @@ struct InstantiationConstraint
TypeId superType;
};

struct UnaryConstraint
{
AstExprUnary::Op op;
TypeId operandType;
TypeId resultType;
};

// let L : leftType
// let R : rightType
// in
// L op R : resultType
struct BinaryConstraint
{
AstExprBinary::Op op;
TypeId leftType;
TypeId rightType;
TypeId resultType;

// When we dispatch this constraint, we update the key at this map to record
// the overload that we selected.
const AstNode* astFragment;
DenseHashMap<const AstNode*, TypeId>* astOriginalCallTypes;
DenseHashMap<const AstNode*, TypeId>* astOverloadResolvedTypes;
};

// iteratee is iterable
// iterators is the iteration types.
struct IterableConstraint
Expand Down Expand Up @@ -241,6 +210,22 @@ struct RefineConstraint
TypeId discriminant;
};

// resultType ~ T0 op T1 op ... op TN
//
// op is either union or intersection. If any of the input types are blocked,
// this constraint will block unless forced.
struct SetOpConstraint
{
enum
{
Intersection,
Union
} mode;

TypeId resultType;
std::vector<TypeId> types;
};

// ty ~ reduce ty
//
// Try to reduce ty, if it is a TypeFamilyInstanceType. Otherwise, do nothing.
Expand All @@ -257,10 +242,9 @@ struct ReducePackConstraint
TypePackId tp;
};

using ConstraintV = Variant<SubtypeConstraint, PackSubtypeConstraint, GeneralizationConstraint, InstantiationConstraint, UnaryConstraint,
BinaryConstraint, IterableConstraint, NameConstraint, TypeAliasExpansionConstraint, FunctionCallConstraint, PrimitiveTypeConstraint,
HasPropConstraint, SetPropConstraint, SetIndexerConstraint, SingletonOrTopTypeConstraint, UnpackConstraint, RefineConstraint, ReduceConstraint,
ReducePackConstraint>;
using ConstraintV = Variant<SubtypeConstraint, PackSubtypeConstraint, GeneralizationConstraint, InstantiationConstraint, IterableConstraint,
NameConstraint, TypeAliasExpansionConstraint, FunctionCallConstraint, PrimitiveTypeConstraint, HasPropConstraint, SetPropConstraint,
SetIndexerConstraint, SingletonOrTopTypeConstraint, UnpackConstraint, RefineConstraint, SetOpConstraint, ReduceConstraint, ReducePackConstraint>;

struct Constraint
{
Expand Down
43 changes: 33 additions & 10 deletions Analysis/include/Luau/ConstraintGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
#include "Luau/Constraint.h"
#include "Luau/ControlFlow.h"
#include "Luau/DataFlowGraph.h"
#include "Luau/InsertionOrderedMap.h"
#include "Luau/Module.h"
#include "Luau/ModuleResolver.h"
#include "Luau/Normalize.h"
#include "Luau/NotNull.h"
#include "Luau/Refinement.h"
#include "Luau/Symbol.h"
#include "Luau/Type.h"
#include "Luau/TypeFwd.h"
#include "Luau/TypeUtils.h"
#include "Luau/Variant.h"
#include "Normalize.h"
#include "Luau/Normalize.h"

#include <memory>
#include <vector>
Expand Down Expand Up @@ -69,11 +71,18 @@ struct ConstraintGraphBuilder
// This is null when the CGB is initially constructed.
Scope* rootScope;

struct InferredBinding
{
Scope* scope;
Location location;
TypeIds types;
};

// During constraint generation, we only populate the Scope::bindings
// property for annotated symbols. Unannotated symbols must be handled in a
// postprocessing step because we do not yet have the full breadcrumb graph.
// We queue them up here.
std::vector<std::tuple<Scope*, Symbol, BreadcrumbId>> inferredBindings;
// postprocessing step because we have not yet allocated the types that will
// be assigned to those unannotated symbols, so we queue them up here.
std::map<Symbol, InferredBinding> inferredBindings;

// Constraints that go straight to the solver.
std::vector<ConstraintPtr> constraints;
Expand Down Expand Up @@ -155,6 +164,18 @@ struct ConstraintGraphBuilder
*/
NotNull<Constraint> addConstraint(const ScopePtr& scope, std::unique_ptr<Constraint> c);

struct RefinementPartition
{
// Types that we want to intersect against the type of the expression.
std::vector<TypeId> discriminantTypes;

// Sometimes the type we're discriminating against is implicitly nil.
bool shouldAppendNilType = false;
};

using RefinementContext = InsertionOrderedMap<DefId, RefinementPartition>;
void unionRefinements(const RefinementContext& lhs, const RefinementContext& rhs, RefinementContext& dest, std::vector<ConstraintV>* constraints);
void computeRefinement(const ScopePtr& scope, RefinementId refinement, RefinementContext* refis, bool sense, bool eq, std::vector<ConstraintV>* constraints);
void applyRefinements(const ScopePtr& scope, Location location, RefinementId refinement);

ControlFlow visitBlockWithoutChildScope(const ScopePtr& scope, AstStatBlock* block);
Expand Down Expand Up @@ -211,13 +232,15 @@ struct ConstraintGraphBuilder
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);

TypeId checkLValue(const ScopePtr& scope, AstExpr* expr);
TypeId checkLValue(const ScopePtr& scope, AstExprLocal* local);
TypeId checkLValue(const ScopePtr& scope, AstExprGlobal* global);
TypeId checkLValue(const ScopePtr& scope, AstExprIndexName* indexName);
TypeId checkLValue(const ScopePtr& scope, AstExprIndexExpr* indexExpr);
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExpr* expr);
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExprLocal* local);
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExprGlobal* global);
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExprIndexName* indexName);
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExprIndexExpr* indexExpr);
TypeId updateProperty(const ScopePtr& scope, AstExpr* expr);

void updateLValueType(AstExpr* lvalue, TypeId ty);

struct FunctionSignature
{
// The type of the function.
Expand Down
3 changes: 1 addition & 2 deletions Analysis/include/Luau/ConstraintSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ struct ConstraintSolver
bool tryDispatch(const PackSubtypeConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const GeneralizationConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const InstantiationConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const UnaryConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const BinaryConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const NameConstraint& c, NotNull<const Constraint> constraint);
bool tryDispatch(const TypeAliasExpansionConstraint& c, NotNull<const Constraint> constraint);
Expand All @@ -124,6 +122,7 @@ struct ConstraintSolver
bool tryDispatch(const SingletonOrTopTypeConstraint& c, NotNull<const Constraint> constraint);
bool tryDispatch(const UnpackConstraint& c, NotNull<const Constraint> constraint);
bool tryDispatch(const RefineConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const SetOpConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const ReduceConstraint& c, NotNull<const Constraint> constraint, bool force);
bool tryDispatch(const ReducePackConstraint& c, NotNull<const Constraint> constraint, bool force);

Expand Down
Loading

0 comments on commit 113dd61

Please sign in to comment.