-
Notifications
You must be signed in to change notification settings - Fork 89
[RFC] Amend Global Type Functions to Accomodate Read & Write Keys #165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
hardlyardi
wants to merge
1
commit into
luau-lang:master
Choose a base branch
from
hardlyardi:amend-global-type-functions-to-accomodate-readwrite-indexing
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
68 changes: 68 additions & 0 deletions
68
docs/amend-global-type-functions-to-accomodate-readwrite-indexing.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| # Amend Global Type Functions to Accomodate Read/Write Indexing | ||
|
|
||
| This RFC supersedes [PR 162](https://github.com/hardlyardi/rfcs/blob/newindex-and-rawset-type-functions/docs/type-functions-newindex-and-rawset.md) | ||
|
|
||
| ## Summary | ||
|
|
||
| Amend some global type functions (`keyof`, `rawkeyof`, `index`, `rawget`) to take in an optional trailing argument, | ||
| limiting their use to the "read" or "write" types of a table. | ||
|
|
||
| ## Motivation | ||
|
|
||
| Currently, there are no built-in type functions with functionality to access the read/write variants of keys in a | ||
| table-like type. Additionally, `rawget` and `rawset` are currently typed unsafely, so this RFC improves the soundness | ||
| of existing globals. | ||
|
|
||
| ## Design | ||
|
|
||
| The following existing type functions: | ||
|
|
||
| - `keyof<TableLike>` | ||
| - `rawkeyof<TableLike>` | ||
| - `index<TableLike, Key>` | ||
| - `rawget<TableLike, Key>` | ||
|
|
||
| Do not support table-like types with differing read and write types; including, but not limited to | ||
| [read-only properties](https://rfcs.luau.org/property-readonly.html). This RFC proposes adding an optional trailing | ||
| argument, a string literal type, to each. The current type expression `keyof<TableLike>` will become equivalent to the | ||
| expression `keyof<TableLike, "read"> | keyof<TableLike, "write">`. | ||
|
|
||
| Similarly for other global type functions: | ||
|
|
||
| ```luau | ||
| type Meow = { | ||
| read purr: true, | ||
| } | ||
| -- Write Key 'purr' does not exist in type | ||
| type Mrrp = index<Meow, "purr", "write"> | ||
| -- 'true' | ||
| type Mrrp = index<Meow, "purr", "read"> | ||
|
Comment on lines
+33
to
+39
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. type T = index<{ write p: number }, "p">Ugh, |
||
| ``` | ||
|
|
||
| Accessing a field which does not exist in a table should emit a type error to prevent mistakes as always. | ||
|
|
||
| Since global type functions can be called within user-defined type functions as globals, it might be helpful to ensure | ||
| that the global can accept strings as well as canon stringletons. | ||
|
|
||
| ## Drawbacks | ||
|
|
||
| - This proposal relies on an optional stringleton in a type function. Generally, type functions should probably operate | ||
| on types, and in this case we are treating one as a runtime value in an API. | ||
|
|
||
| ## Alternatives | ||
|
|
||
| - Do nothing. User-defined type functions can compute this behavior - but this isn't desired due to human error, | ||
| fragmentation of common behavior, and time to implement. We should strive to make the language easy to use. | ||
| - Do not error when indexing a field which does not exist. This would silently send out an 'unknown' in a place where a | ||
| user is likely doing something wrong. However, this alternative makes things easier to work with unions in table-like | ||
| types & keys. | ||
| - Add new global type functions (`newindex`, `rawset`, `newkeyof`, `rawsetkeyof`), for a total collection of: | ||
| `index`, | ||
| `rawget`, | ||
| `newindex`, | ||
| `rawset`, | ||
| `keyof`, | ||
| `rawkeyof`, | ||
| `newkeyof`, | ||
| `rawsetkeyof`. | ||
| Horrifying. **No.** | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you just do composition?
keyof<readonly<T>>andkeyof<writeonly<T>>wherereadonlyremoves thewritemodifier, and converselywriteonlywithreadmodifier.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how would that work with extern types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generic type functions sound like the better option here. I don't think there should be any support for extern types since trying to normalize them seems impossible, e.g.
readonly<vector>would have to resolve to something wacky likevector & ~{write x: number, write y: number, write z: number}to work. If someone really needs that then they can just use UDTFs.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it isn't unrealistic to normalize the read/write access of extern types, it is unrealistic to normalize the extern types themselves. That's what I'm addressing.
Additionally, there are many examples of the dissonance between extern types and table types being harmful to ease-of-use, as well as the development of the language. I think if it can be avoided, you shouldn't need to use a UDTF to get the
read/writekeys of an extern type. That's a very reasonable use-case for keyof IMO.