From 066486004bfd9c50d2ed9cb3b42b125cc7c7c8ce Mon Sep 17 00:00:00 2001 From: Tenebris Noctua <172976441+TenebrisNoctua@users.noreply.github.com> Date: Sat, 12 Apr 2025 04:24:22 +0300 Subject: [PATCH 1/5] Create support-for-type-packs-in-user-defined-type-functions.md --- ...pe-packs-in-user-defined-type-functions.md | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 docs/support-for-type-packs-in-user-defined-type-functions.md diff --git a/docs/support-for-type-packs-in-user-defined-type-functions.md b/docs/support-for-type-packs-in-user-defined-type-functions.md new file mode 100644 index 0000000..2d5b45c --- /dev/null +++ b/docs/support-for-type-packs-in-user-defined-type-functions.md @@ -0,0 +1,129 @@ +# Support for Type Packs in User-Defined Type Functions + +## Summary + +Add support for type packs in user defined type functions. + +## Motivation + +Currently, user-defined type functions are limited in terms of support for type packs. The only place where a type pack is represented as a runtime type, is within generic `type` instances, +where the instance can either be a generic type, or a generic type pack. Other kinds of packs such as variadic packs can only be created within 'tail' spots. + +This limits the usage for packs as they are used often in the language, and their creation and usage should be easier and more expanded upon. + +## Design + +We introduce a new runtime type called `pack` to extend the support of type packs within the type runtime. + +Packs will have a `kind` property that specifies the kind of the pack. A pack can either be a `list` kind or a `variadic` kind. + +For example, consider a variadic type pack (e.g `...number`), in the new pack type, it will be represented as a `pack` with a `variadic` kind. +Or for a normal type pack such as `(number, string)`, it will be represented as a `pack` with a `list` kind. + +`list` kind of packs will be able to contain other packs, or types more than one, whereas `variadic` type of packs will only contain *one* type. + +The user will be able to obtain the types within `pack`s using the `:unpack()` method, this method will return a table containing all the types or type packs within the pack. +In `variadic` kind of `pack`s, `:unpack()` will only return a table with one element. This is because variadic packs are essentially many elements of the same type. + +In user-defined type functions, type packs can be created by providing types or type packs that will be included within the pack. A pack will also be able to contain other packs, even packs of different kinds. + +### Examples + +Creating a type function that accepts type packs: + +```luau +type function f(arg: type) + if not arg:is("pack") then error("The given argument is not a type pack!") end + + local unpacked = arg:unpack() -- {string, number} + print(unpacked) +end + +type a = f<(string, number)> +``` + +Creating a type function that returns a function with a type pack: + +```luau +type function f() + local newListPack = types.pack({types.string, types.number}) + local newVariadicPack = types.pack({types.any}, true) + local newfunc = types.newfunction() + + newfunc:setparameters({newPack}, newVariadicPack) + newfunc:setreturns({newPack}, newVariadicPack) + + return newfunc +end + +type A = f<> -- (string, number, ...any) -> (string, number, ...any) +``` + +The pack type will also enable generic type packs to be provided to type functions from aliases in the type runtime. +Generic type pack arguments will pass the given type pack to the type function. + +```luau +type function createCallback(args: type, returns: type) -- args will be a list pack, returns will be a variadic pack. + local newTable = types.newtable() + + local newfunc = types.newfunction() + newfunc:setparameters({args}) + newfunc:setreturns({returns}) + + newTable:setproperty(types.singleton("f"), newfunc) + + return newTable +end + +type Callback = createCallback +type A = Callback<(number, string), ...number> +``` + +If variadic type functions were to be implemented, type packs could be retrieved like this: + +```luau +type function f(...) + local packed = {...} -- {type} + local firstPack = packed[1] -- type.kind: list + local secondPack = packed[2] -- type.kind: variadic +end + +type a = f<(string, number), ...number> +``` + +## Updates to the types library and type userdata + +### `types` Library + +| New/Update | Library Functions | Return Type | Description | +| ------------- | ------------- | ------------- | ------------- | +| New | `pack(packs: {type} isvariadic: boolean?)` | `type` | returns an immutable instance of a type pack; when `isvariadic` is true, `packs` table can only have one type. | +| Update | `newfunction(parameters: { head: {type}?, tail: type? }, returns: { head: {type}?, tail: type? }, generics: {type}?)` | `type` | `tail` arguments can now accept variadic packs. + +### `type` Instance + +| New/Update | Instance Properties | Type | Description | +| ------------- | ------------- | ------------- | ------------- | +| Update | `tag` | `"nil" \| "unknown" \| "never" \| "any" \| "boolean" \| "number" \| "string" \| "singleton" \| "negation" \| "union" \| "intersection" \| "table" \| "function" \| "class" \| "thread" \| "buffer" \| "generic" \| "pack"` | Added `pack` as a possible tag | + +#### Pack `type` instance + +| New/Update | Instance Methods | Type | Description | +| ------------- | ------------- | ------------- | ------------- | +| New | `kind` | `"list" \| "variadic"` | indicates the kind of the pack. | +| New | `unpack()` | `{type}` | returns the types contained within the pack, returns only one element if `kind` is `variadic`. | + +#### Function `type` instance + +| New/Update | Instance Methods | Return Type | Description | +| ------------- | ------------- | ------------- | ------------- | +| Update | `setparameters(head: {type}?, tail: type?)` | `()` | `tail` argument can now accept variadic packs. | +| Update | `setreturns(head: {type}?, tail: type?)` | `()` | `tail` argument can now accept variadic packs. | + +## Drawbacks + +This may bring additional complexity to type functions, and now variadic types will no longer have special meanings only in a tail spot. + +## Alternatives + +Do nothing and force type functions to only accept singular type parameters. From 05024b4a803f1adbae467a5523d905bbef82769f Mon Sep 17 00:00:00 2001 From: Tenebris Noctua <172976441+TenebrisNoctua@users.noreply.github.com> Date: Sat, 12 Apr 2025 06:18:44 +0300 Subject: [PATCH 2/5] Update support-for-type-packs-in-user-defined-type-functions.md --- docs/support-for-type-packs-in-user-defined-type-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/support-for-type-packs-in-user-defined-type-functions.md b/docs/support-for-type-packs-in-user-defined-type-functions.md index 2d5b45c..a45cb77 100644 --- a/docs/support-for-type-packs-in-user-defined-type-functions.md +++ b/docs/support-for-type-packs-in-user-defined-type-functions.md @@ -97,7 +97,7 @@ type a = f<(string, number), ...number> | New/Update | Library Functions | Return Type | Description | | ------------- | ------------- | ------------- | ------------- | -| New | `pack(packs: {type} isvariadic: boolean?)` | `type` | returns an immutable instance of a type pack; when `isvariadic` is true, `packs` table can only have one type. | +| New | `pack(types: {type} isvariadic: boolean?)` | `type` | returns an immutable instance of a type pack; when `isvariadic` is true, `packs` table can only have one type. | | Update | `newfunction(parameters: { head: {type}?, tail: type? }, returns: { head: {type}?, tail: type? }, generics: {type}?)` | `type` | `tail` arguments can now accept variadic packs. ### `type` Instance From 366cad1f6b7a0adad7845a7d074f8bded8c95c59 Mon Sep 17 00:00:00 2001 From: Tenebris Noctua <172976441+TenebrisNoctua@users.noreply.github.com> Date: Sat, 12 Apr 2025 06:19:08 +0300 Subject: [PATCH 3/5] Update support-for-type-packs-in-user-defined-type-functions.md --- docs/support-for-type-packs-in-user-defined-type-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/support-for-type-packs-in-user-defined-type-functions.md b/docs/support-for-type-packs-in-user-defined-type-functions.md index a45cb77..c268915 100644 --- a/docs/support-for-type-packs-in-user-defined-type-functions.md +++ b/docs/support-for-type-packs-in-user-defined-type-functions.md @@ -97,7 +97,7 @@ type a = f<(string, number), ...number> | New/Update | Library Functions | Return Type | Description | | ------------- | ------------- | ------------- | ------------- | -| New | `pack(types: {type} isvariadic: boolean?)` | `type` | returns an immutable instance of a type pack; when `isvariadic` is true, `packs` table can only have one type. | +| New | `pack(types: {type} isvariadic: boolean?)` | `type` | returns an immutable instance of a type pack; when `isvariadic` is true, `types` table can only have one type. | | Update | `newfunction(parameters: { head: {type}?, tail: type? }, returns: { head: {type}?, tail: type? }, generics: {type}?)` | `type` | `tail` arguments can now accept variadic packs. ### `type` Instance From 92024aeda4256fb97c25a66d38da5eff862366bd Mon Sep 17 00:00:00 2001 From: Tenebris Noctua <172976441+TenebrisNoctua@users.noreply.github.com> Date: Sat, 12 Apr 2025 15:39:53 +0300 Subject: [PATCH 4/5] Create variadic-user-defined-type-functions.md --- docs/variadic-user-defined-type-functions.md | 54 ++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 docs/variadic-user-defined-type-functions.md diff --git a/docs/variadic-user-defined-type-functions.md b/docs/variadic-user-defined-type-functions.md new file mode 100644 index 0000000..d613cc2 --- /dev/null +++ b/docs/variadic-user-defined-type-functions.md @@ -0,0 +1,54 @@ +# Variadic User-Defined Type Functions + +## Summary + +Add support for variadic arguments for user-defined type functions. + +## Motivation + +Today, user-defined type functions can only take a pre-defined set of parameters. This limits the usage in a way that makes it not possible to make the function variadic, where the user can supply +the function as many arguments as provided. + +By adding support for variadic functions, we allow users to call user-defined type functions with as many arguments as they wish, providing a more dynamic system. + +## Design + +The syntax for variadic type functions would be exactly the same as normal variadic functions where `...` can only be legal as the last argument of the function. +Utilizing either `table.pack(...)` method or `{...}`, the user would recieve a table of `type`s to use within their code. + +### Examples + +Creating a variadic type function: + +```luau +type function f(...) + local packed = {...} -- {type} + for _, type in packed do + -- Use the provided types. + end +end + +type a = f +``` + +Calling a variadic type function from a type alias: + +```luau +type function f(...) + local packed = {...} + local firstArg = packed[1] -- tag: string + local secondArg = packed[2] -- tag: number + local thirdArg = packed[3] -- tag: table +end + +type a = f +type b = a +``` + +## Drawbacks + +It's unclear if this proposal has any drawbacks. + +## Alternatives + +Do nothing, and force type functions to only take pre-defined set of parameters. From a583a4f7073d096921a8bdbf52b43b679bc5dd36 Mon Sep 17 00:00:00 2001 From: Tenebris Noctua <172976441+TenebrisNoctua@users.noreply.github.com> Date: Sat, 12 Apr 2025 17:02:47 +0300 Subject: [PATCH 5/5] Delete docs/variadic-user-defined-type-functions.md --- docs/variadic-user-defined-type-functions.md | 54 -------------------- 1 file changed, 54 deletions(-) delete mode 100644 docs/variadic-user-defined-type-functions.md diff --git a/docs/variadic-user-defined-type-functions.md b/docs/variadic-user-defined-type-functions.md deleted file mode 100644 index d613cc2..0000000 --- a/docs/variadic-user-defined-type-functions.md +++ /dev/null @@ -1,54 +0,0 @@ -# Variadic User-Defined Type Functions - -## Summary - -Add support for variadic arguments for user-defined type functions. - -## Motivation - -Today, user-defined type functions can only take a pre-defined set of parameters. This limits the usage in a way that makes it not possible to make the function variadic, where the user can supply -the function as many arguments as provided. - -By adding support for variadic functions, we allow users to call user-defined type functions with as many arguments as they wish, providing a more dynamic system. - -## Design - -The syntax for variadic type functions would be exactly the same as normal variadic functions where `...` can only be legal as the last argument of the function. -Utilizing either `table.pack(...)` method or `{...}`, the user would recieve a table of `type`s to use within their code. - -### Examples - -Creating a variadic type function: - -```luau -type function f(...) - local packed = {...} -- {type} - for _, type in packed do - -- Use the provided types. - end -end - -type a = f -``` - -Calling a variadic type function from a type alias: - -```luau -type function f(...) - local packed = {...} - local firstArg = packed[1] -- tag: string - local secondArg = packed[2] -- tag: number - local thirdArg = packed[3] -- tag: table -end - -type a = f -type b = a -``` - -## Drawbacks - -It's unclear if this proposal has any drawbacks. - -## Alternatives - -Do nothing, and force type functions to only take pre-defined set of parameters.