Skip to content

Commit e491128

Browse files
vegorov-rbxaatxehgoldsteinvrn-snVighnesh-V
authored
Sync to upstream/release/648 (#1477)
## What's new * Added `math.map` function to the standard library, based on https://rfcs.luau-lang.org/function-math-map.html * `FileResolver` can provide an implementation of `getRequireSuggestions` to provide auto-complete suggestions for require-by-string ## New Solver * In user-defined type functions, `readproperty` and `writeproperty` will return `nil` instead of erroring if property is not found * Fixed incorrect scope of variadic arguments in the data-flow graph * Fixed multiple assertion failures --- Internal Contributors: Co-authored-by: Aaron Weiss <[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]>
1 parent d7842e0 commit e491128

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1588
-522
lines changed

Analysis/include/Luau/Autocomplete.h

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum class AutocompleteEntryKind
3939
Type,
4040
Module,
4141
GeneratedFunction,
42+
RequirePath,
4243
};
4344

4445
enum class ParenthesesRecommendation

Analysis/include/Luau/BuiltinDefinitions.h

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
namespace Luau
1010
{
1111

12+
static constexpr char kRequireTagName[] = "require";
13+
1214
struct Frontend;
1315
struct GlobalTypes;
1416
struct TypeChecker;

Analysis/include/Luau/DataFlowGraph.h

+111-72
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ struct DataFlowGraph
6868
DenseHashMap<const AstExpr*, const Def*> compoundAssignDefs{nullptr};
6969

7070
DenseHashMap<const AstExpr*, const RefinementKey*> astRefinementKeys{nullptr};
71-
7271
friend struct DataFlowGraphBuilder;
7372
};
7473

@@ -83,6 +82,7 @@ struct DfgScope
8382

8483
DfgScope* parent;
8584
ScopeType scopeType;
85+
Location location;
8686

8787
using Bindings = DenseHashMap<Symbol, const Def*>;
8888
using Props = DenseHashMap<const Def*, std::unordered_map<std::string, const Def*>>;
@@ -105,10 +105,44 @@ struct DataFlowResult
105105
const RefinementKey* parent = nullptr;
106106
};
107107

108+
using ScopeStack = std::vector<DfgScope*>;
109+
108110
struct DataFlowGraphBuilder
109111
{
110112
static DataFlowGraph build(AstStatBlock* root, NotNull<struct InternalErrorReporter> handle);
111113

114+
/**
115+
* This method is identical to the build method above, but returns a pair of dfg, scopes as the data flow graph
116+
* here is intended to live on the module between runs of typechecking. Before, the DFG only needed to live as
117+
* long as the typecheck, but in a world with incremental typechecking, we need the information on the dfg to incrementally
118+
* typecheck small fragments of code.
119+
* @param block - pointer to the ast to build the dfg for
120+
* @param handle - for raising internal errors while building the dfg
121+
*/
122+
static std::pair<std::shared_ptr<DataFlowGraph>, std::vector<std::unique_ptr<DfgScope>>> buildShared(
123+
AstStatBlock* block,
124+
NotNull<InternalErrorReporter> handle
125+
);
126+
127+
/**
128+
* Takes a stale graph along with a list of scopes, a small fragment of the ast, and a cursor position
129+
* and constructs the DataFlowGraph for just that fragment. This method will fabricate defs in the final
130+
* DFG for things that have been referenced and exist in the stale dfg.
131+
* For example, the fragment local z = x + y will populate defs for x and y from the stale graph.
132+
* @param staleGraph - the old DFG
133+
* @param scopes - the old DfgScopes in the graph
134+
* @param fragment - the Ast Fragment to re-build the root for
135+
* @param cursorPos - the current location of the cursor - used to determine which scope we are currently in
136+
* @param handle - for internal compiler errors
137+
*/
138+
static DataFlowGraph updateGraph(
139+
const DataFlowGraph& staleGraph,
140+
const std::vector<std::unique_ptr<DfgScope>>& scopes,
141+
AstStatBlock* fragment,
142+
const Position& cursorPos,
143+
NotNull<InternalErrorReporter> handle
144+
);
145+
112146
private:
113147
DataFlowGraphBuilder() = default;
114148

@@ -120,10 +154,15 @@ struct DataFlowGraphBuilder
120154
NotNull<RefinementKeyArena> keyArena{&graph.keyArena};
121155

122156
struct InternalErrorReporter* handle = nullptr;
123-
DfgScope* moduleScope = nullptr;
124157

158+
/// The arena owning all of the scope allocations for the dataflow graph being built.
125159
std::vector<std::unique_ptr<DfgScope>> scopes;
126160

161+
/// A stack of scopes used by the visitor to see where we are.
162+
ScopeStack scopeStack;
163+
164+
DfgScope* currentScope();
165+
127166
struct FunctionCapture
128167
{
129168
std::vector<DefId> captureDefs;
@@ -134,81 +173,81 @@ struct DataFlowGraphBuilder
134173
DenseHashMap<Symbol, FunctionCapture> captures{Symbol{}};
135174
void resolveCaptures();
136175

137-
DfgScope* childScope(DfgScope* scope, DfgScope::ScopeType scopeType = DfgScope::Linear);
176+
DfgScope* makeChildScope(Location loc, DfgScope::ScopeType scopeType = DfgScope::Linear);
138177

139178
void join(DfgScope* p, DfgScope* a, DfgScope* b);
140179
void joinBindings(DfgScope* p, const DfgScope& a, const DfgScope& b);
141180
void joinProps(DfgScope* p, const DfgScope& a, const DfgScope& b);
142181

143-
DefId lookup(DfgScope* scope, Symbol symbol);
144-
DefId lookup(DfgScope* scope, DefId def, const std::string& key);
145-
146-
ControlFlow visit(DfgScope* scope, AstStatBlock* b);
147-
ControlFlow visitBlockWithoutChildScope(DfgScope* scope, AstStatBlock* b);
148-
149-
ControlFlow visit(DfgScope* scope, AstStat* s);
150-
ControlFlow visit(DfgScope* scope, AstStatIf* i);
151-
ControlFlow visit(DfgScope* scope, AstStatWhile* w);
152-
ControlFlow visit(DfgScope* scope, AstStatRepeat* r);
153-
ControlFlow visit(DfgScope* scope, AstStatBreak* b);
154-
ControlFlow visit(DfgScope* scope, AstStatContinue* c);
155-
ControlFlow visit(DfgScope* scope, AstStatReturn* r);
156-
ControlFlow visit(DfgScope* scope, AstStatExpr* e);
157-
ControlFlow visit(DfgScope* scope, AstStatLocal* l);
158-
ControlFlow visit(DfgScope* scope, AstStatFor* f);
159-
ControlFlow visit(DfgScope* scope, AstStatForIn* f);
160-
ControlFlow visit(DfgScope* scope, AstStatAssign* a);
161-
ControlFlow visit(DfgScope* scope, AstStatCompoundAssign* c);
162-
ControlFlow visit(DfgScope* scope, AstStatFunction* f);
163-
ControlFlow visit(DfgScope* scope, AstStatLocalFunction* l);
164-
ControlFlow visit(DfgScope* scope, AstStatTypeAlias* t);
165-
ControlFlow visit(DfgScope* scope, AstStatTypeFunction* f);
166-
ControlFlow visit(DfgScope* scope, AstStatDeclareGlobal* d);
167-
ControlFlow visit(DfgScope* scope, AstStatDeclareFunction* d);
168-
ControlFlow visit(DfgScope* scope, AstStatDeclareClass* d);
169-
ControlFlow visit(DfgScope* scope, AstStatError* error);
170-
171-
DataFlowResult visitExpr(DfgScope* scope, AstExpr* e);
172-
DataFlowResult visitExpr(DfgScope* scope, AstExprGroup* group);
173-
DataFlowResult visitExpr(DfgScope* scope, AstExprLocal* l);
174-
DataFlowResult visitExpr(DfgScope* scope, AstExprGlobal* g);
175-
DataFlowResult visitExpr(DfgScope* scope, AstExprCall* c);
176-
DataFlowResult visitExpr(DfgScope* scope, AstExprIndexName* i);
177-
DataFlowResult visitExpr(DfgScope* scope, AstExprIndexExpr* i);
178-
DataFlowResult visitExpr(DfgScope* scope, AstExprFunction* f);
179-
DataFlowResult visitExpr(DfgScope* scope, AstExprTable* t);
180-
DataFlowResult visitExpr(DfgScope* scope, AstExprUnary* u);
181-
DataFlowResult visitExpr(DfgScope* scope, AstExprBinary* b);
182-
DataFlowResult visitExpr(DfgScope* scope, AstExprTypeAssertion* t);
183-
DataFlowResult visitExpr(DfgScope* scope, AstExprIfElse* i);
184-
DataFlowResult visitExpr(DfgScope* scope, AstExprInterpString* i);
185-
DataFlowResult visitExpr(DfgScope* scope, AstExprError* error);
186-
187-
void visitLValue(DfgScope* scope, AstExpr* e, DefId incomingDef);
188-
DefId visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef);
189-
DefId visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef);
190-
DefId visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef);
191-
DefId visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef);
192-
DefId visitLValue(DfgScope* scope, AstExprError* e, DefId incomingDef);
193-
194-
void visitType(DfgScope* scope, AstType* t);
195-
void visitType(DfgScope* scope, AstTypeReference* r);
196-
void visitType(DfgScope* scope, AstTypeTable* t);
197-
void visitType(DfgScope* scope, AstTypeFunction* f);
198-
void visitType(DfgScope* scope, AstTypeTypeof* t);
199-
void visitType(DfgScope* scope, AstTypeUnion* u);
200-
void visitType(DfgScope* scope, AstTypeIntersection* i);
201-
void visitType(DfgScope* scope, AstTypeError* error);
202-
203-
void visitTypePack(DfgScope* scope, AstTypePack* p);
204-
void visitTypePack(DfgScope* scope, AstTypePackExplicit* e);
205-
void visitTypePack(DfgScope* scope, AstTypePackVariadic* v);
206-
void visitTypePack(DfgScope* scope, AstTypePackGeneric* g);
207-
208-
void visitTypeList(DfgScope* scope, AstTypeList l);
209-
210-
void visitGenerics(DfgScope* scope, AstArray<AstGenericType> g);
211-
void visitGenericPacks(DfgScope* scope, AstArray<AstGenericTypePack> g);
182+
DefId lookup(Symbol symbol);
183+
DefId lookup(DefId def, const std::string& key);
184+
185+
ControlFlow visit(AstStatBlock* b);
186+
ControlFlow visitBlockWithoutChildScope(AstStatBlock* b);
187+
188+
ControlFlow visit(AstStat* s);
189+
ControlFlow visit(AstStatIf* i);
190+
ControlFlow visit(AstStatWhile* w);
191+
ControlFlow visit(AstStatRepeat* r);
192+
ControlFlow visit(AstStatBreak* b);
193+
ControlFlow visit(AstStatContinue* c);
194+
ControlFlow visit(AstStatReturn* r);
195+
ControlFlow visit(AstStatExpr* e);
196+
ControlFlow visit(AstStatLocal* l);
197+
ControlFlow visit(AstStatFor* f);
198+
ControlFlow visit(AstStatForIn* f);
199+
ControlFlow visit(AstStatAssign* a);
200+
ControlFlow visit(AstStatCompoundAssign* c);
201+
ControlFlow visit(AstStatFunction* f);
202+
ControlFlow visit(AstStatLocalFunction* l);
203+
ControlFlow visit(AstStatTypeAlias* t);
204+
ControlFlow visit(AstStatTypeFunction* f);
205+
ControlFlow visit(AstStatDeclareGlobal* d);
206+
ControlFlow visit(AstStatDeclareFunction* d);
207+
ControlFlow visit(AstStatDeclareClass* d);
208+
ControlFlow visit(AstStatError* error);
209+
210+
DataFlowResult visitExpr(AstExpr* e);
211+
DataFlowResult visitExpr(AstExprGroup* group);
212+
DataFlowResult visitExpr(AstExprLocal* l);
213+
DataFlowResult visitExpr(AstExprGlobal* g);
214+
DataFlowResult visitExpr(AstExprCall* c);
215+
DataFlowResult visitExpr(AstExprIndexName* i);
216+
DataFlowResult visitExpr(AstExprIndexExpr* i);
217+
DataFlowResult visitExpr(AstExprFunction* f);
218+
DataFlowResult visitExpr(AstExprTable* t);
219+
DataFlowResult visitExpr(AstExprUnary* u);
220+
DataFlowResult visitExpr(AstExprBinary* b);
221+
DataFlowResult visitExpr(AstExprTypeAssertion* t);
222+
DataFlowResult visitExpr(AstExprIfElse* i);
223+
DataFlowResult visitExpr(AstExprInterpString* i);
224+
DataFlowResult visitExpr(AstExprError* error);
225+
226+
void visitLValue(AstExpr* e, DefId incomingDef);
227+
DefId visitLValue(AstExprLocal* l, DefId incomingDef);
228+
DefId visitLValue(AstExprGlobal* g, DefId incomingDef);
229+
DefId visitLValue(AstExprIndexName* i, DefId incomingDef);
230+
DefId visitLValue(AstExprIndexExpr* i, DefId incomingDef);
231+
DefId visitLValue(AstExprError* e, DefId incomingDef);
232+
233+
void visitType(AstType* t);
234+
void visitType(AstTypeReference* r);
235+
void visitType(AstTypeTable* t);
236+
void visitType(AstTypeFunction* f);
237+
void visitType(AstTypeTypeof* t);
238+
void visitType(AstTypeUnion* u);
239+
void visitType(AstTypeIntersection* i);
240+
void visitType(AstTypeError* error);
241+
242+
void visitTypePack(AstTypePack* p);
243+
void visitTypePack(AstTypePackExplicit* e);
244+
void visitTypePack(AstTypePackVariadic* v);
245+
void visitTypePack(AstTypePackGeneric* g);
246+
247+
void visitTypeList(AstTypeList l);
248+
249+
void visitGenerics(AstArray<AstGenericType> g);
250+
void visitGenericPacks(AstArray<AstGenericTypePack> g);
212251
};
213252

214253
} // namespace Luau

Analysis/include/Luau/FileResolver.h

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <string>
55
#include <optional>
6+
#include <vector>
67

78
namespace Luau
89
{
@@ -31,6 +32,9 @@ struct ModuleInfo
3132
bool optional = false;
3233
};
3334

35+
using RequireSuggestion = std::string;
36+
using RequireSuggestions = std::vector<RequireSuggestion>;
37+
3438
struct FileResolver
3539
{
3640
virtual ~FileResolver() {}
@@ -51,6 +55,11 @@ struct FileResolver
5155
{
5256
return std::nullopt;
5357
}
58+
59+
virtual std::optional<RequireSuggestions> getRequireSuggestions(const ModuleName& requirer, const std::optional<std::string>& pathString) const
60+
{
61+
return std::nullopt;
62+
}
5463
};
5564

5665
struct NullFileResolver : FileResolver
+25-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
22
#pragma once
33

4-
#include "Luau/DenseHash.h"
54
#include "Luau/Ast.h"
5+
#include "Luau/Parser.h"
6+
#include "Luau/Autocomplete.h"
7+
#include "Luau/DenseHash.h"
8+
#include "Luau/Module.h"
69

10+
#include <memory>
711
#include <vector>
812

9-
1013
namespace Luau
1114
{
1215

@@ -15,9 +18,28 @@ struct FragmentAutocompleteAncestryResult
1518
DenseHashMap<AstName, AstLocal*> localMap{AstName()};
1619
std::vector<AstLocal*> localStack;
1720
std::vector<AstNode*> ancestry;
18-
AstStat* nearestStatement;
21+
AstStat* nearestStatement = nullptr;
22+
};
23+
24+
struct FragmentParseResult
25+
{
26+
std::string fragmentToParse;
27+
AstStatBlock* root = nullptr;
28+
std::vector<AstNode*> ancestry;
29+
std::unique_ptr<Allocator> alloc = std::make_unique<Allocator>();
1930
};
2031

2132
FragmentAutocompleteAncestryResult findAncestryForFragmentParse(AstStatBlock* root, const Position& cursorPos);
2233

34+
FragmentParseResult parseFragment(const SourceModule& srcModule, std::string_view src, const Position& cursorPos);
35+
36+
AutocompleteResult fragmentAutocomplete(
37+
Frontend& frontend,
38+
std::string_view src,
39+
const ModuleName& moduleName,
40+
Position& cursorPosition,
41+
StringCompletionCallback callback
42+
);
43+
44+
2345
} // namespace Luau

Analysis/include/Luau/Module.h

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "Luau/Scope.h"
1010
#include "Luau/TypeArena.h"
1111
#include "Luau/AnyTypeSummary.h"
12+
#include "Luau/DataFlowGraph.h"
1213

1314
#include <memory>
1415
#include <vector>
@@ -131,6 +132,9 @@ struct Module
131132

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

135139
bool hasModuleScope() const;
136140
ScopePtr getModuleScope() const;

Analysis/include/Luau/Type.h

+7
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,11 @@ struct AnyType
667667
{
668668
};
669669

670+
// A special, trivial type for the refinement system that is always eliminated from intersections.
671+
struct NoRefineType
672+
{
673+
};
674+
670675
// `T | U`
671676
struct UnionType
672677
{
@@ -755,6 +760,7 @@ using TypeVariant = Unifiable::Variant<
755760
UnknownType,
756761
NeverType,
757762
NegationType,
763+
NoRefineType,
758764
TypeFunctionInstanceType>;
759765

760766
struct Type final
@@ -949,6 +955,7 @@ struct BuiltinTypes
949955
const TypeId unknownType;
950956
const TypeId neverType;
951957
const TypeId errorType;
958+
const TypeId noRefineType;
952959
const TypeId falsyType;
953960
const TypeId truthyType;
954961

0 commit comments

Comments
 (0)