2022-06-04 06:15:45 +08:00
|
|
|
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "Luau/Ast.h"
|
2022-06-17 09:05:14 +08:00
|
|
|
#include "Luau/Constraint.h"
|
2023-03-18 03:20:37 +08:00
|
|
|
#include "Luau/ControlFlow.h"
|
2022-12-03 02:09:59 +08:00
|
|
|
#include "Luau/DataFlowGraph.h"
|
2023-10-21 09:10:30 +08:00
|
|
|
#include "Luau/InsertionOrderedMap.h"
|
2022-06-04 06:15:45 +08:00
|
|
|
#include "Luau/Module.h"
|
2022-09-02 07:14:03 +08:00
|
|
|
#include "Luau/ModuleResolver.h"
|
2023-10-21 09:10:30 +08:00
|
|
|
#include "Luau/Normalize.h"
|
2022-06-17 09:05:14 +08:00
|
|
|
#include "Luau/NotNull.h"
|
2023-03-18 03:20:37 +08:00
|
|
|
#include "Luau/Refinement.h"
|
2022-06-04 06:15:45 +08:00
|
|
|
#include "Luau/Symbol.h"
|
2023-10-21 09:10:30 +08:00
|
|
|
#include "Luau/TypeFwd.h"
|
2023-04-29 03:55:13 +08:00
|
|
|
#include "Luau/TypeUtils.h"
|
2022-06-04 06:15:45 +08:00
|
|
|
#include "Luau/Variant.h"
|
2023-10-21 09:10:30 +08:00
|
|
|
#include "Luau/Normalize.h"
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2022-10-22 01:54:01 +08:00
|
|
|
#include <memory>
|
|
|
|
#include <vector>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
2022-06-04 06:15:45 +08:00
|
|
|
namespace Luau
|
|
|
|
{
|
|
|
|
|
2022-07-29 12:24:07 +08:00
|
|
|
struct Scope;
|
|
|
|
using ScopePtr = std::shared_ptr<Scope>;
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2022-09-09 06:14:25 +08:00
|
|
|
struct DcrLogger;
|
|
|
|
|
2022-10-28 18:37:29 +08:00
|
|
|
struct Inference
|
|
|
|
{
|
|
|
|
TypeId ty = nullptr;
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
RefinementId refinement = nullptr;
|
2022-10-28 18:37:29 +08:00
|
|
|
|
|
|
|
Inference() = default;
|
|
|
|
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
explicit Inference(TypeId ty, RefinementId refinement = nullptr)
|
2022-10-28 18:37:29 +08:00
|
|
|
: ty(ty)
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
, refinement(refinement)
|
2022-10-28 18:37:29 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct InferencePack
|
|
|
|
{
|
|
|
|
TypePackId tp = nullptr;
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
std::vector<RefinementId> refinements;
|
2022-10-28 18:37:29 +08:00
|
|
|
|
|
|
|
InferencePack() = default;
|
|
|
|
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
explicit InferencePack(TypePackId tp, const std::vector<RefinementId>& refinements = {})
|
2022-10-28 18:37:29 +08:00
|
|
|
: tp(tp)
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
, refinements(refinements)
|
2022-10-28 18:37:29 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-11-04 07:45:04 +08:00
|
|
|
struct ConstraintGenerator
|
2022-06-04 06:15:45 +08:00
|
|
|
{
|
|
|
|
// A list of all the scopes in the module. This vector holds ownership of the
|
|
|
|
// scope pointers; the scopes themselves borrow pointers to other scopes to
|
|
|
|
// define the scope hierarchy.
|
2022-07-29 12:24:07 +08:00
|
|
|
std::vector<std::pair<Location, ScopePtr>> scopes;
|
2022-07-01 07:52:43 +08:00
|
|
|
|
2022-08-12 05:01:33 +08:00
|
|
|
ModulePtr module;
|
2023-01-05 04:53:17 +08:00
|
|
|
NotNull<BuiltinTypes> builtinTypes;
|
2022-07-01 07:52:43 +08:00
|
|
|
const NotNull<TypeArena> arena;
|
2022-06-04 06:15:45 +08:00
|
|
|
// The root scope of the module we're generating constraints for.
|
2023-11-04 07:45:04 +08:00
|
|
|
// This is null when the CG is initially constructed.
|
2022-07-29 12:24:07 +08:00
|
|
|
Scope* rootScope;
|
2022-11-11 06:53:13 +08:00
|
|
|
|
2023-10-21 09:10:30 +08:00
|
|
|
struct InferredBinding
|
|
|
|
{
|
|
|
|
Scope* scope;
|
|
|
|
Location location;
|
|
|
|
TypeIds types;
|
|
|
|
};
|
|
|
|
|
2023-11-18 02:46:18 +08:00
|
|
|
// Some locals have multiple type states. We wish for Scope::bindings to
|
|
|
|
// map each local name onto the union of every type that the local can have
|
|
|
|
// over its lifetime, so we use this map to accumulate the set of types it
|
|
|
|
// might have.
|
|
|
|
//
|
|
|
|
// See the functions recordInferredBinding and fillInInferredBindings.
|
|
|
|
DenseHashMap<Symbol, InferredBinding> inferredBindings{{}};
|
2023-10-14 04:20:12 +08:00
|
|
|
|
2022-11-11 06:53:13 +08:00
|
|
|
// Constraints that go straight to the solver.
|
|
|
|
std::vector<ConstraintPtr> constraints;
|
|
|
|
|
|
|
|
// Constraints that do not go to the solver right away. Other constraints
|
|
|
|
// will enqueue them during solving.
|
|
|
|
std::vector<ConstraintPtr> unqueuedConstraints;
|
|
|
|
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
// The private scope of type aliases for which the type parameters belong to.
|
2022-08-05 06:35:33 +08:00
|
|
|
DenseHashMap<const AstStatTypeAlias*, ScopePtr> astTypeAliasDefiningScopes{nullptr};
|
2022-12-10 03:57:01 +08:00
|
|
|
|
2022-10-22 01:54:01 +08:00
|
|
|
NotNull<const DataFlowGraph> dfg;
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
RefinementArena refinementArena;
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2022-07-01 07:52:43 +08:00
|
|
|
int recursionCount = 0;
|
|
|
|
|
|
|
|
// It is pretty uncommon for constraint generation to itself produce errors, but it can happen.
|
|
|
|
std::vector<TypeError> errors;
|
|
|
|
|
2023-08-05 03:18:54 +08:00
|
|
|
// Needed to be able to enable error-suppression preservation for immediate refinements.
|
|
|
|
NotNull<Normalizer> normalizer;
|
2022-09-02 07:14:03 +08:00
|
|
|
// Needed to resolve modules to make 'require' import types properly.
|
|
|
|
NotNull<ModuleResolver> moduleResolver;
|
2022-07-01 07:52:43 +08:00
|
|
|
// Occasionally constraint generation needs to produce an ICE.
|
|
|
|
const NotNull<InternalErrorReporter> ice;
|
|
|
|
|
2022-08-12 05:01:33 +08:00
|
|
|
ScopePtr globalScope;
|
2023-04-29 03:55:13 +08:00
|
|
|
|
|
|
|
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope;
|
2023-07-28 23:13:53 +08:00
|
|
|
std::vector<RequireCycle> requireCycles;
|
2023-04-29 03:55:13 +08:00
|
|
|
|
2022-09-09 06:14:25 +08:00
|
|
|
DcrLogger* logger;
|
2022-07-01 07:52:43 +08:00
|
|
|
|
2024-02-16 10:04:39 +08:00
|
|
|
ConstraintGenerator(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);
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2023-09-30 09:13:05 +08:00
|
|
|
/**
|
2023-11-04 07:45:04 +08:00
|
|
|
* The entry point to the ConstraintGenerator. This will construct a set
|
2023-09-30 09:13:05 +08:00
|
|
|
* of scopes, constraints, and free types that can be solved later.
|
|
|
|
* @param block the root block to generate constraints for.
|
|
|
|
*/
|
|
|
|
void visitModuleRoot(AstStatBlock* block);
|
|
|
|
|
|
|
|
private:
|
2024-02-24 04:08:34 +08:00
|
|
|
std::vector<std::vector<TypeId>> interiorTypes;
|
|
|
|
|
2022-06-04 06:15:45 +08:00
|
|
|
/**
|
|
|
|
* Fabricates a new free type belonging to a given scope.
|
2022-07-01 07:52:43 +08:00
|
|
|
* @param scope the scope the free type belongs to.
|
2022-06-04 06:15:45 +08:00
|
|
|
*/
|
2022-07-29 12:24:07 +08:00
|
|
|
TypeId freshType(const ScopePtr& scope);
|
2022-06-04 06:15:45 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fabricates a new free type pack belonging to a given scope.
|
2022-07-01 07:52:43 +08:00
|
|
|
* @param scope the scope the free type pack belongs to.
|
2022-06-04 06:15:45 +08:00
|
|
|
*/
|
2022-07-29 12:24:07 +08:00
|
|
|
TypePackId freshTypePack(const ScopePtr& scope);
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2024-02-03 05:32:42 +08:00
|
|
|
/**
|
|
|
|
* Allocate a new TypePack with the given head and tail.
|
|
|
|
*
|
|
|
|
* Avoids allocating 0-length type packs:
|
|
|
|
*
|
|
|
|
* If the head is non-empty, allocate and return a type pack with the given
|
|
|
|
* head and tail.
|
|
|
|
* If the head is empty and tail is non-empty, return *tail.
|
|
|
|
* If both the head and tail are empty, return an empty type pack.
|
|
|
|
*/
|
|
|
|
TypePackId addTypePack(std::vector<TypeId> head, std::optional<TypePackId> tail);
|
|
|
|
|
2022-06-04 06:15:45 +08:00
|
|
|
/**
|
|
|
|
* Fabricates a scope that is a child of another scope.
|
2022-08-19 05:32:08 +08:00
|
|
|
* @param node the lexical node that the scope belongs to.
|
2022-06-04 06:15:45 +08:00
|
|
|
* @param parent the parent scope of the new scope. Must not be null.
|
|
|
|
*/
|
2022-08-19 05:32:08 +08:00
|
|
|
ScopePtr childScope(AstNode* node, const ScopePtr& parent);
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2024-01-27 11:20:56 +08:00
|
|
|
std::optional<TypeId> lookup(const ScopePtr& scope, DefId def, bool prototype = true);
|
2023-11-11 05:10:07 +08:00
|
|
|
|
2022-06-04 06:15:45 +08:00
|
|
|
/**
|
|
|
|
* Adds a new constraint with no dependencies to a given scope.
|
2022-07-01 07:52:43 +08:00
|
|
|
* @param scope the scope to add the constraint to.
|
2022-06-04 06:15:45 +08:00
|
|
|
* @param cv the constraint variant to add.
|
2022-10-22 01:54:01 +08:00
|
|
|
* @return the pointer to the inserted constraint
|
2022-06-04 06:15:45 +08:00
|
|
|
*/
|
2022-10-22 01:54:01 +08:00
|
|
|
NotNull<Constraint> addConstraint(const ScopePtr& scope, const Location& location, ConstraintV cv);
|
2022-06-04 06:15:45 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a constraint to a given scope.
|
|
|
|
* @param scope the scope to add the constraint to. Must not be null.
|
|
|
|
* @param c the constraint to add.
|
2022-10-22 01:54:01 +08:00
|
|
|
* @return the pointer to the inserted constraint
|
2022-06-04 06:15:45 +08:00
|
|
|
*/
|
2022-10-22 01:54:01 +08:00
|
|
|
NotNull<Constraint> addConstraint(const ScopePtr& scope, std::unique_ptr<Constraint> c);
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2023-10-21 09:10:30 +08:00
|
|
|
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>;
|
2024-02-16 10:04:39 +08:00
|
|
|
void unionRefinements(const ScopePtr& scope, Location location, const RefinementContext& lhs, const RefinementContext& rhs,
|
|
|
|
RefinementContext& dest, std::vector<ConstraintV>* constraints);
|
|
|
|
void computeRefinement(const ScopePtr& scope, Location location, RefinementId refinement, RefinementContext* refis, bool sense, bool eq,
|
|
|
|
std::vector<ConstraintV>* constraints);
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
void applyRefinements(const ScopePtr& scope, Location location, RefinementId refinement);
|
2022-11-05 01:33:22 +08:00
|
|
|
|
2023-03-18 03:20:37 +08:00
|
|
|
ControlFlow visitBlockWithoutChildScope(const ScopePtr& scope, AstStatBlock* block);
|
|
|
|
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStat* stat);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatBlock* block);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatLocal* local);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatFor* for_);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatForIn* forIn);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatWhile* while_);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatRepeat* repeat);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatLocalFunction* function);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatFunction* function);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatReturn* ret);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatAssign* assign);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatCompoundAssign* assign);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatIf* ifStatement);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatTypeAlias* alias);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatDeclareGlobal* declareGlobal);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatDeclareClass* declareClass);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatDeclareFunction* declareFunction);
|
|
|
|
ControlFlow visit(const ScopePtr& scope, AstStatError* error);
|
2022-06-17 09:05:14 +08:00
|
|
|
|
2023-02-18 07:41:51 +08:00
|
|
|
InferencePack checkPack(const ScopePtr& scope, AstArray<AstExpr*> exprs, const std::vector<std::optional<TypeId>>& expectedTypes = {});
|
2023-09-30 09:13:05 +08:00
|
|
|
InferencePack checkPack(
|
|
|
|
const ScopePtr& scope, AstExpr* expr, const std::vector<std::optional<TypeId>>& expectedTypes = {}, bool generalize = true);
|
2022-10-28 18:37:29 +08:00
|
|
|
|
2023-02-18 07:41:51 +08:00
|
|
|
InferencePack checkPack(const ScopePtr& scope, AstExprCall* call);
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2022-06-17 09:05:14 +08:00
|
|
|
/**
|
|
|
|
* Checks an expression that is expected to evaluate to one type.
|
|
|
|
* @param scope the scope the expression is contained within.
|
|
|
|
* @param expr the expression to check.
|
2022-09-24 03:17:25 +08:00
|
|
|
* @param expectedType the type of the expression that is expected from its
|
|
|
|
* surrounding context. Used to implement bidirectional type checking.
|
2023-09-30 09:13:05 +08:00
|
|
|
* @param generalize If true, generalize any lambdas that are encountered.
|
2022-06-17 09:05:14 +08:00
|
|
|
* @return the type of the expression.
|
|
|
|
*/
|
2023-10-07 03:02:32 +08:00
|
|
|
Inference check(
|
|
|
|
const ScopePtr& scope, AstExpr* expr, std::optional<TypeId> expectedType = {}, bool forceSingleton = false, bool generalize = true);
|
2022-10-28 18:37:29 +08:00
|
|
|
|
2022-11-05 01:33:22 +08:00
|
|
|
Inference check(const ScopePtr& scope, AstExprConstantString* string, std::optional<TypeId> expectedType, bool forceSingleton);
|
|
|
|
Inference check(const ScopePtr& scope, AstExprConstantBool* bool_, std::optional<TypeId> expectedType, bool forceSingleton);
|
2023-10-07 03:02:32 +08:00
|
|
|
Inference check(const ScopePtr& scope, AstExprLocal* local);
|
2022-10-28 18:37:29 +08:00
|
|
|
Inference check(const ScopePtr& scope, AstExprGlobal* global);
|
2023-12-02 15:46:57 +08:00
|
|
|
Inference checkIndexName(const ScopePtr& scope, const RefinementKey* key, AstExpr* indexee, std::string index);
|
2022-10-28 18:37:29 +08:00
|
|
|
Inference check(const ScopePtr& scope, AstExprIndexName* indexName);
|
|
|
|
Inference check(const ScopePtr& scope, AstExprIndexExpr* indexExpr);
|
2023-09-30 09:13:05 +08:00
|
|
|
Inference check(const ScopePtr& scope, AstExprFunction* func, std::optional<TypeId> expectedType, bool generalize);
|
2022-10-28 18:37:29 +08:00
|
|
|
Inference check(const ScopePtr& scope, AstExprUnary* unary);
|
|
|
|
Inference check(const ScopePtr& scope, AstExprBinary* binary, std::optional<TypeId> expectedType);
|
|
|
|
Inference check(const ScopePtr& scope, AstExprIfElse* ifElse, std::optional<TypeId> expectedType);
|
|
|
|
Inference check(const ScopePtr& scope, AstExprTypeAssertion* typeAssert);
|
2023-01-28 06:28:31 +08:00
|
|
|
Inference check(const ScopePtr& scope, AstExprInterpString* interpString);
|
2022-10-28 18:37:29 +08:00
|
|
|
Inference check(const ScopePtr& scope, AstExprTable* expr, std::optional<TypeId> expectedType);
|
Sync to upstream/release/562 (#828)
* Fixed rare use-after-free in analysis during table unification
A lot of work these past months went into two new Luau components:
* A near full rewrite of the typechecker using a new deferred constraint
resolution system
* Native code generation for AoT/JiT compilation of VM bytecode into x64
(avx)/arm64 instructions
Both of these components are far from finished and we don't provide
documentation on building and using them at this point.
However, curious community members expressed interest in learning about
changes that go into these components each week, so we are now listing
them here in the 'sync' pull request descriptions.
---
New typechecker can be enabled by setting
DebugLuauDeferredConstraintResolution flag to 'true'.
It is considered unstable right now, so try it at your own risk.
Even though it already provides better type inference than the current
one in some cases, our main goal right now is to reach feature parity
with current typechecker.
Features which improve over the capabilities of the current typechecker
are marked as '(NEW)'.
Changes to new typechecker:
* Regular for loop index and parameters are now typechecked
* Invalid type annotations on local variables are ignored to improve
autocomplete
* Fixed missing autocomplete type suggestions for function arguments
* Type reduction is now performed to produce simpler types to be
presented to the user (error messages, custom LSPs)
* Internally, complex types like '((number | string) & ~(false?)) |
string' can be produced, which is just 'string | number' when simplified
* Fixed spots where support for unknown and never types was missing
* (NEW) Length operator '#' is now valid to use on top table type, this
type comes up when doing typeof(x) == "table" guards and isn't available
in current typechecker
---
Changes to native code generation:
* Additional math library fast calls are now lowered to x64: math.ldexp,
math.round, math.frexp, math.modf, math.sign and math.clamp
2023-02-04 03:26:13 +08:00
|
|
|
std::tuple<TypeId, TypeId, RefinementId> checkBinary(const ScopePtr& scope, AstExprBinary* binary, std::optional<TypeId> expectedType);
|
2022-10-22 01:54:01 +08:00
|
|
|
|
2023-11-04 07:45:04 +08:00
|
|
|
/**
|
|
|
|
* Generate constraints to assign assignedTy to the expression expr
|
|
|
|
* @returns the type of the expression. This may or may not be assignedTy itself.
|
|
|
|
*/
|
2024-01-20 02:04:46 +08:00
|
|
|
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExpr* expr, TypeId assignedTy, bool transform);
|
|
|
|
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExprLocal* local, TypeId assignedTy, bool transform);
|
2023-11-04 07:45:04 +08:00
|
|
|
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExprGlobal* global, TypeId assignedTy);
|
|
|
|
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExprIndexName* indexName, TypeId assignedTy);
|
|
|
|
std::optional<TypeId> checkLValue(const ScopePtr& scope, AstExprIndexExpr* indexExpr, TypeId assignedTy);
|
|
|
|
TypeId updateProperty(const ScopePtr& scope, AstExpr* expr, TypeId assignedTy);
|
2022-07-01 07:52:43 +08:00
|
|
|
|
|
|
|
struct FunctionSignature
|
|
|
|
{
|
|
|
|
// The type of the function.
|
|
|
|
TypeId signature;
|
|
|
|
// The scope that encompasses the function's signature. May be nullptr
|
|
|
|
// if there was no need for a signature scope (the function has no
|
|
|
|
// generics).
|
2022-07-29 12:24:07 +08:00
|
|
|
ScopePtr signatureScope;
|
2022-07-01 07:52:43 +08:00
|
|
|
// The scope that encompasses the function's body. Is a child scope of
|
|
|
|
// signatureScope, if present.
|
2022-07-29 12:24:07 +08:00
|
|
|
ScopePtr bodyScope;
|
2022-07-01 07:52:43 +08:00
|
|
|
};
|
|
|
|
|
2023-05-20 03:37:30 +08:00
|
|
|
FunctionSignature checkFunctionSignature(
|
|
|
|
const ScopePtr& parent, AstExprFunction* fn, std::optional<TypeId> expectedType = {}, std::optional<Location> originalName = {});
|
2022-06-17 09:05:14 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks the body of a function expression.
|
|
|
|
* @param scope the interior scope of the body of the function.
|
|
|
|
* @param fn the function expression to check.
|
|
|
|
*/
|
2022-07-29 12:24:07 +08:00
|
|
|
void checkFunctionBody(const ScopePtr& scope, AstExprFunction* fn);
|
2022-06-24 09:56:00 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolves a type from its AST annotation.
|
|
|
|
* @param scope the scope that the type annotation appears within.
|
|
|
|
* @param ty the AST annotation to resolve.
|
2023-01-21 04:27:03 +08:00
|
|
|
* @param inTypeArguments whether we are resolving a type that's contained within type arguments, `<...>`.
|
2022-06-24 09:56:00 +08:00
|
|
|
* @return the type of the AST annotation.
|
|
|
|
**/
|
2023-03-04 04:21:14 +08:00
|
|
|
TypeId resolveType(const ScopePtr& scope, AstType* ty, bool inTypeArguments, bool replaceErrorWithFresh = false);
|
2022-06-24 09:56:00 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolves a type pack from its AST annotation.
|
|
|
|
* @param scope the scope that the type annotation appears within.
|
|
|
|
* @param tp the AST annotation to resolve.
|
2023-01-21 04:27:03 +08:00
|
|
|
* @param inTypeArguments whether we are resolving a type that's contained within type arguments, `<...>`.
|
2022-06-24 09:56:00 +08:00
|
|
|
* @return the type pack of the AST annotation.
|
|
|
|
**/
|
2023-03-04 04:21:14 +08:00
|
|
|
TypePackId resolveTypePack(const ScopePtr& scope, AstTypePack* tp, bool inTypeArguments, bool replaceErrorWithFresh = false);
|
2022-07-01 07:52:43 +08:00
|
|
|
|
2023-01-21 04:27:03 +08:00
|
|
|
/**
|
|
|
|
* Resolves a type pack from its AST annotation.
|
|
|
|
* @param scope the scope that the type annotation appears within.
|
|
|
|
* @param list the AST annotation to resolve.
|
|
|
|
* @param inTypeArguments whether we are resolving a type that's contained within type arguments, `<...>`.
|
|
|
|
* @return the type pack of the AST annotation.
|
|
|
|
**/
|
2023-03-04 04:21:14 +08:00
|
|
|
TypePackId resolveTypePack(const ScopePtr& scope, const AstTypeList& list, bool inTypeArguments, bool replaceErrorWithFresh = false);
|
2022-07-01 07:52:43 +08:00
|
|
|
|
2023-02-25 05:49:38 +08:00
|
|
|
/**
|
|
|
|
* Creates generic types given a list of AST definitions, resolving default
|
|
|
|
* types as required.
|
|
|
|
* @param scope the scope that the generics should belong to.
|
|
|
|
* @param generics the AST generics to create types for.
|
|
|
|
* @param useCache whether to use the generic type cache for the given
|
|
|
|
* scope.
|
|
|
|
* @param addTypes whether to add the types to the scope's
|
|
|
|
* privateTypeBindings map.
|
|
|
|
**/
|
2023-02-18 07:41:51 +08:00
|
|
|
std::vector<std::pair<Name, GenericTypeDefinition>> createGenerics(
|
2023-02-25 05:49:38 +08:00
|
|
|
const ScopePtr& scope, AstArray<AstGenericType> generics, bool useCache = false, bool addTypes = true);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates generic type packs given a list of AST definitions, resolving
|
|
|
|
* default type packs as required.
|
|
|
|
* @param scope the scope that the generic packs should belong to.
|
|
|
|
* @param generics the AST generics to create type packs for.
|
|
|
|
* @param useCache whether to use the generic type pack cache for the given
|
|
|
|
* scope.
|
|
|
|
* @param addTypes whether to add the types to the scope's
|
|
|
|
* privateTypePackBindings map.
|
|
|
|
**/
|
2023-02-18 07:41:51 +08:00
|
|
|
std::vector<std::pair<Name, GenericTypePackDefinition>> createGenericPacks(
|
2023-02-25 05:49:38 +08:00
|
|
|
const ScopePtr& scope, AstArray<AstGenericTypePack> packs, bool useCache = false, bool addTypes = true);
|
2022-06-24 09:56:00 +08:00
|
|
|
|
2022-10-28 18:37:29 +08:00
|
|
|
Inference flattenPack(const ScopePtr& scope, Location location, InferencePack pack);
|
2022-07-01 07:52:43 +08:00
|
|
|
|
|
|
|
void reportError(Location location, TypeErrorData err);
|
|
|
|
void reportCodeTooComplex(Location location);
|
|
|
|
|
2024-01-27 11:20:56 +08:00
|
|
|
// make a union type family of these two types
|
|
|
|
TypeId makeUnion(const ScopePtr& scope, Location location, TypeId lhs, TypeId rhs);
|
|
|
|
// make an intersect type family of these two types
|
|
|
|
TypeId makeIntersect(const ScopePtr& scope, Location location, TypeId lhs, TypeId rhs);
|
|
|
|
|
2022-07-01 07:52:43 +08:00
|
|
|
/** Scan the program for global definitions.
|
|
|
|
*
|
2023-11-04 07:45:04 +08:00
|
|
|
* ConstraintGenerator needs to differentiate between globals and accesses to undefined symbols. Doing this "for
|
2022-07-01 07:52:43 +08:00
|
|
|
* real" in a general way is going to be pretty hard, so we are choosing not to tackle that yet. For now, we do an
|
|
|
|
* initial scan of the AST and note what globals are defined.
|
|
|
|
*/
|
2022-07-29 12:24:07 +08:00
|
|
|
void prepopulateGlobalScope(const ScopePtr& globalScope, AstStatBlock* program);
|
2023-03-04 04:21:14 +08:00
|
|
|
|
2023-11-18 02:46:18 +08:00
|
|
|
// Record the fact that a particular local has a particular type in at least
|
|
|
|
// one of its states.
|
|
|
|
void recordInferredBinding(AstLocal* local, TypeId ty);
|
|
|
|
|
2023-10-14 04:20:12 +08:00
|
|
|
void fillInInferredBindings(const ScopePtr& globalScope, AstStatBlock* block);
|
|
|
|
|
2023-03-04 04:21:14 +08:00
|
|
|
/** Given a function type annotation, return a vector describing the expected types of the calls to the function
|
|
|
|
* For example, calling a function with annotation ((number) -> string & ((string) -> number))
|
|
|
|
* yields a vector of size 1, with value: [number | string]
|
|
|
|
*/
|
|
|
|
std::vector<std::optional<TypeId>> getExpectedCallTypesForFunctionOverloads(const TypeId fnType);
|
2022-06-04 06:15:45 +08:00
|
|
|
};
|
|
|
|
|
2022-11-11 06:53:13 +08:00
|
|
|
/** Borrow a vector of pointers from a vector of owning pointers to constraints.
|
2022-06-17 09:05:14 +08:00
|
|
|
*/
|
2022-11-11 06:53:13 +08:00
|
|
|
std::vector<NotNull<Constraint>> borrowConstraints(const std::vector<ConstraintPtr>& constraints);
|
2022-06-04 06:15:45 +08:00
|
|
|
|
2023-03-04 04:21:14 +08:00
|
|
|
|
2022-06-04 06:15:45 +08:00
|
|
|
} // namespace Luau
|