mirror of
https://github.com/luau-lang/luau.git
synced 2025-04-19 03:03:49 +01:00
Hey folks, another week means another Luau release! This one features a number of bug fixes in the New Type Solver including improvements to user-defined type functions and a bunch of work to untangle some of the outstanding issues we've been seeing with constraint solving not completing in real world use. We're also continuing to make progress on crashes and other problems that affect the stability of fragment autocomplete, as we work towards delivering consistent, low-latency autocomplete for any editor environment. ## New Type Solver - Fix a bug in user-defined type functions where `print` would incorrectly insert `\1` a number of times. - Fix a bug where attempting to refine an optional generic with a type test will cause a false positive type error (fixes #1666) - Fix a bug where the `refine` type family would not skip over `*no-refine*` discriminants (partial resolution for #1424) - Fix a constraint solving bug where recursive function calls would consistently produce cyclic constraints leading to incomplete or inaccurate type inference. - Implement `readparent` and `writeparent` for class types in user-defined type functions, replacing the incorrectly included `parent` method. - Add initial groundwork (under a debug flag) for eager free type generalization, moving us towards further improvements to constraint solving incomplete errors. ## Fragment Autocomplete - Ease up some assertions to improve stability of mixed-mode use of the two type solvers (i.e. using Fragment Autocomplete on a type graph originally produced by the old type solver) - Resolve a bug with type compatibility checks causing internal compiler errors in autocomplete. ## Lexer and Parser - Improve the accuracy of the roundtrippable AST parsing mode by correctly placing closing parentheses on type groupings. - Add a getter for `offset` in the Lexer by @aduermael in #1688 - Add a second entry point to the parser to parse an expression, `parseExpr` ## Internal Contributors Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Ariel Weiss <aaronweiss@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com> Co-authored-by: James McNellis <jmcnellis@roblox.com> Co-authored-by: Talha Pathan <tpathan@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> --------- Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com> Co-authored-by: Varun Saini <61795485+vrn-sn@users.noreply.github.com> Co-authored-by: Alexander Youngblood <ayoungblood@roblox.com> Co-authored-by: Menarul Alam <malam@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Vighnesh <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
320 lines
12 KiB
C++
320 lines
12 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
#include "Luau/BuiltinDefinitions.h"
|
|
|
|
LUAU_FASTFLAGVARIABLE(LuauDebugInfoDefn)
|
|
|
|
namespace Luau
|
|
{
|
|
|
|
static const std::string kBuiltinDefinitionBaseSrc = R"BUILTIN_SRC(
|
|
|
|
@checked declare function require(target: any): any
|
|
|
|
@checked declare function getfenv(target: any): { [string]: any }
|
|
|
|
declare _G: any
|
|
declare _VERSION: string
|
|
|
|
declare function gcinfo(): number
|
|
|
|
declare function print<T...>(...: T...)
|
|
|
|
declare function type<T>(value: T): string
|
|
declare function typeof<T>(value: T): string
|
|
|
|
-- `assert` has a magic function attached that will give more detailed type information
|
|
declare function assert<T>(value: T, errorMessage: string?): T
|
|
declare function error<T>(message: T, level: number?): never
|
|
|
|
declare function tostring<T>(value: T): string
|
|
declare function tonumber<T>(value: T, radix: number?): number?
|
|
|
|
declare function rawequal<T1, T2>(a: T1, b: T2): boolean
|
|
declare function rawget<K, V>(tab: {[K]: V}, k: K): V
|
|
declare function rawset<K, V>(tab: {[K]: V}, k: K, v: V): {[K]: V}
|
|
declare function rawlen<K, V>(obj: {[K]: V} | string): number
|
|
|
|
declare function setfenv<T..., R...>(target: number | (T...) -> R..., env: {[string]: any}): ((T...) -> R...)?
|
|
|
|
declare function ipairs<V>(tab: {V}): (({V}, number) -> (number?, V), {V}, number)
|
|
|
|
declare function pcall<A..., R...>(f: (A...) -> R..., ...: A...): (boolean, R...)
|
|
|
|
-- FIXME: The actual type of `xpcall` is:
|
|
-- <E, A..., R1..., R2...>(f: (A...) -> R1..., err: (E) -> R2..., A...) -> (true, R1...) | (false, R2...)
|
|
-- Since we can't represent the return value, we use (boolean, R1...).
|
|
declare function xpcall<E, A..., R1..., R2...>(f: (A...) -> R1..., err: (E) -> R2..., ...: A...): (boolean, R1...)
|
|
|
|
-- `select` has a magic function attached to provide more detailed type information
|
|
declare function select<A...>(i: string | number, ...: A...): ...any
|
|
|
|
-- FIXME: This type is not entirely correct - `loadstring` returns a function or
|
|
-- (nil, string).
|
|
declare function loadstring<A...>(src: string, chunkname: string?): (((A...) -> any)?, string?)
|
|
|
|
@checked declare function newproxy(mt: boolean?): any
|
|
|
|
-- Cannot use `typeof` here because it will produce a polytype when we expect a monotype.
|
|
declare function unpack<V>(tab: {V}, i: number?, j: number?): ...V
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionBit32Src = R"BUILTIN_SRC(
|
|
|
|
declare bit32: {
|
|
band: @checked (...number) -> number,
|
|
bor: @checked (...number) -> number,
|
|
bxor: @checked (...number) -> number,
|
|
btest: @checked (number, ...number) -> boolean,
|
|
rrotate: @checked (x: number, disp: number) -> number,
|
|
lrotate: @checked (x: number, disp: number) -> number,
|
|
lshift: @checked (x: number, disp: number) -> number,
|
|
arshift: @checked (x: number, disp: number) -> number,
|
|
rshift: @checked (x: number, disp: number) -> number,
|
|
bnot: @checked (x: number) -> number,
|
|
extract: @checked (n: number, field: number, width: number?) -> number,
|
|
replace: @checked (n: number, v: number, field: number, width: number?) -> number,
|
|
countlz: @checked (n: number) -> number,
|
|
countrz: @checked (n: number) -> number,
|
|
byteswap: @checked (n: number) -> number,
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionMathSrc = R"BUILTIN_SRC(
|
|
|
|
declare math: {
|
|
frexp: @checked (n: number) -> (number, number),
|
|
ldexp: @checked (s: number, e: number) -> number,
|
|
fmod: @checked (x: number, y: number) -> number,
|
|
modf: @checked (n: number) -> (number, number),
|
|
pow: @checked (x: number, y: number) -> number,
|
|
exp: @checked (n: number) -> number,
|
|
|
|
ceil: @checked (n: number) -> number,
|
|
floor: @checked (n: number) -> number,
|
|
abs: @checked (n: number) -> number,
|
|
sqrt: @checked (n: number) -> number,
|
|
|
|
log: @checked (n: number, base: number?) -> number,
|
|
log10: @checked (n: number) -> number,
|
|
|
|
rad: @checked (n: number) -> number,
|
|
deg: @checked (n: number) -> number,
|
|
|
|
sin: @checked (n: number) -> number,
|
|
cos: @checked (n: number) -> number,
|
|
tan: @checked (n: number) -> number,
|
|
sinh: @checked (n: number) -> number,
|
|
cosh: @checked (n: number) -> number,
|
|
tanh: @checked (n: number) -> number,
|
|
atan: @checked (n: number) -> number,
|
|
acos: @checked (n: number) -> number,
|
|
asin: @checked (n: number) -> number,
|
|
atan2: @checked (y: number, x: number) -> number,
|
|
|
|
min: @checked (number, ...number) -> number,
|
|
max: @checked (number, ...number) -> number,
|
|
|
|
pi: number,
|
|
huge: number,
|
|
|
|
randomseed: @checked (seed: number) -> (),
|
|
random: @checked (number?, number?) -> number,
|
|
|
|
sign: @checked (n: number) -> number,
|
|
clamp: @checked (n: number, min: number, max: number) -> number,
|
|
noise: @checked (x: number, y: number?, z: number?) -> number,
|
|
round: @checked (n: number) -> number,
|
|
map: @checked (x: number, inmin: number, inmax: number, outmin: number, outmax: number) -> number,
|
|
lerp: @checked (a: number, b: number, t: number) -> number,
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionOsSrc = R"BUILTIN_SRC(
|
|
|
|
type DateTypeArg = {
|
|
year: number,
|
|
month: number,
|
|
day: number,
|
|
hour: number?,
|
|
min: number?,
|
|
sec: number?,
|
|
isdst: boolean?,
|
|
}
|
|
|
|
type DateTypeResult = {
|
|
year: number,
|
|
month: number,
|
|
wday: number,
|
|
yday: number,
|
|
day: number,
|
|
hour: number,
|
|
min: number,
|
|
sec: number,
|
|
isdst: boolean,
|
|
}
|
|
|
|
declare os: {
|
|
time: (time: DateTypeArg?) -> number,
|
|
date: ((formatString: "*t" | "!*t", time: number?) -> DateTypeResult) & ((formatString: string?, time: number?) -> string),
|
|
difftime: (t2: DateTypeResult | number, t1: DateTypeResult | number) -> number,
|
|
clock: () -> number,
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionCoroutineSrc = R"BUILTIN_SRC(
|
|
|
|
declare coroutine: {
|
|
create: <A..., R...>(f: (A...) -> R...) -> thread,
|
|
resume: <A..., R...>(co: thread, A...) -> (boolean, R...),
|
|
running: () -> thread,
|
|
status: @checked (co: thread) -> "dead" | "running" | "normal" | "suspended",
|
|
wrap: <A..., R...>(f: (A...) -> R...) -> ((A...) -> R...),
|
|
yield: <A..., R...>(A...) -> R...,
|
|
isyieldable: () -> boolean,
|
|
close: @checked (co: thread) -> (boolean, any)
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionTableSrc = R"BUILTIN_SRC(
|
|
|
|
declare table: {
|
|
concat: <V>(t: {V}, sep: string?, i: number?, j: number?) -> string,
|
|
insert: (<V>(t: {V}, value: V) -> ()) & (<V>(t: {V}, pos: number, value: V) -> ()),
|
|
maxn: <V>(t: {V}) -> number,
|
|
remove: <V>(t: {V}, number?) -> V?,
|
|
sort: <V>(t: {V}, comp: ((V, V) -> boolean)?) -> (),
|
|
create: <V>(count: number, value: V?) -> {V},
|
|
find: <V>(haystack: {V}, needle: V, init: number?) -> number?,
|
|
|
|
unpack: <V>(list: {V}, i: number?, j: number?) -> ...V,
|
|
pack: <V>(...V) -> { n: number, [number]: V },
|
|
|
|
getn: <V>(t: {V}) -> number,
|
|
foreach: <K, V>(t: {[K]: V}, f: (K, V) -> ()) -> (),
|
|
foreachi: <V>({V}, (number, V) -> ()) -> (),
|
|
|
|
move: <V>(src: {V}, a: number, b: number, t: number, dst: {V}?) -> {V},
|
|
clear: <K, V>(table: {[K]: V}) -> (),
|
|
|
|
isfrozen: <K, V>(t: {[K]: V}) -> boolean,
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionDebugSrc = R"BUILTIN_SRC(
|
|
|
|
declare debug: {
|
|
info: ((thread: thread, level: number, options: string) -> ...any) & ((level: number, options: string) -> ...any) & (<A..., R1...>(func: (A...) -> R1..., options: string) -> ...any),
|
|
traceback: ((message: string?, level: number?) -> string) & ((thread: thread, message: string?, level: number?) -> string),
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionDebugSrc_DEPRECATED = R"BUILTIN_SRC(
|
|
|
|
declare debug: {
|
|
info: (<R...>(thread: thread, level: number, options: string) -> R...) & (<R...>(level: number, options: string) -> R...) & (<A..., R1..., R2...>(func: (A...) -> R1..., options: string) -> R2...),
|
|
traceback: ((message: string?, level: number?) -> string) & ((thread: thread, message: string?, level: number?) -> string),
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionUtf8Src = R"BUILTIN_SRC(
|
|
|
|
declare utf8: {
|
|
char: @checked (...number) -> string,
|
|
charpattern: string,
|
|
codes: @checked (str: string) -> ((string, number) -> (number, number), string, number),
|
|
codepoint: @checked (str: string, i: number?, j: number?) -> ...number,
|
|
len: @checked (s: string, i: number?, j: number?) -> (number?, number?),
|
|
offset: @checked (s: string, n: number?, i: number?) -> number,
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionBufferSrc = R"BUILTIN_SRC(
|
|
--- Buffer API
|
|
declare buffer: {
|
|
create: @checked (size: number) -> buffer,
|
|
fromstring: @checked (str: string) -> buffer,
|
|
tostring: @checked (b: buffer) -> string,
|
|
len: @checked (b: buffer) -> number,
|
|
copy: @checked (target: buffer, targetOffset: number, source: buffer, sourceOffset: number?, count: number?) -> (),
|
|
fill: @checked (b: buffer, offset: number, value: number, count: number?) -> (),
|
|
readi8: @checked (b: buffer, offset: number) -> number,
|
|
readu8: @checked (b: buffer, offset: number) -> number,
|
|
readi16: @checked (b: buffer, offset: number) -> number,
|
|
readu16: @checked (b: buffer, offset: number) -> number,
|
|
readi32: @checked (b: buffer, offset: number) -> number,
|
|
readu32: @checked (b: buffer, offset: number) -> number,
|
|
readf32: @checked (b: buffer, offset: number) -> number,
|
|
readf64: @checked (b: buffer, offset: number) -> number,
|
|
writei8: @checked (b: buffer, offset: number, value: number) -> (),
|
|
writeu8: @checked (b: buffer, offset: number, value: number) -> (),
|
|
writei16: @checked (b: buffer, offset: number, value: number) -> (),
|
|
writeu16: @checked (b: buffer, offset: number, value: number) -> (),
|
|
writei32: @checked (b: buffer, offset: number, value: number) -> (),
|
|
writeu32: @checked (b: buffer, offset: number, value: number) -> (),
|
|
writef32: @checked (b: buffer, offset: number, value: number) -> (),
|
|
writef64: @checked (b: buffer, offset: number, value: number) -> (),
|
|
readstring: @checked (b: buffer, offset: number, count: number) -> string,
|
|
writestring: @checked (b: buffer, offset: number, value: string, count: number?) -> (),
|
|
readbits: @checked (b: buffer, bitOffset: number, bitCount: number) -> number,
|
|
writebits: @checked (b: buffer, bitOffset: number, bitCount: number, value: number) -> (),
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
static const std::string kBuiltinDefinitionVectorSrc = R"BUILTIN_SRC(
|
|
|
|
-- While vector would have been better represented as a built-in primitive type, type solver class handling covers most of the properties
|
|
declare class vector
|
|
x: number
|
|
y: number
|
|
z: number
|
|
end
|
|
|
|
declare vector: {
|
|
create: @checked (x: number, y: number, z: number?) -> vector,
|
|
magnitude: @checked (vec: vector) -> number,
|
|
normalize: @checked (vec: vector) -> vector,
|
|
cross: @checked (vec1: vector, vec2: vector) -> vector,
|
|
dot: @checked (vec1: vector, vec2: vector) -> number,
|
|
angle: @checked (vec1: vector, vec2: vector, axis: vector?) -> number,
|
|
floor: @checked (vec: vector) -> vector,
|
|
ceil: @checked (vec: vector) -> vector,
|
|
abs: @checked (vec: vector) -> vector,
|
|
sign: @checked (vec: vector) -> vector,
|
|
clamp: @checked (vec: vector, min: vector, max: vector) -> vector,
|
|
max: @checked (vector, ...vector) -> vector,
|
|
min: @checked (vector, ...vector) -> vector,
|
|
|
|
zero: vector,
|
|
one: vector,
|
|
}
|
|
|
|
)BUILTIN_SRC";
|
|
|
|
std::string getBuiltinDefinitionSource()
|
|
{
|
|
std::string result = kBuiltinDefinitionBaseSrc;
|
|
|
|
result += kBuiltinDefinitionBit32Src;
|
|
result += kBuiltinDefinitionMathSrc;
|
|
result += kBuiltinDefinitionOsSrc;
|
|
result += kBuiltinDefinitionCoroutineSrc;
|
|
result += kBuiltinDefinitionTableSrc;
|
|
result += FFlag::LuauDebugInfoDefn ? kBuiltinDefinitionDebugSrc : kBuiltinDefinitionDebugSrc_DEPRECATED;
|
|
result += kBuiltinDefinitionUtf8Src;
|
|
result += kBuiltinDefinitionBufferSrc;
|
|
result += kBuiltinDefinitionVectorSrc;
|
|
|
|
return result;
|
|
}
|
|
|
|
} // namespace Luau
|