-
Notifications
You must be signed in to change notification settings - Fork 73
Allow attributes to be used on types, variables, and table fields #147
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
gaymeowing
wants to merge
5
commits into
luau-lang:master
Choose a base branch
from
gaymeowing:attributes-everywhere
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.
+124
−0
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
124 changes: 124 additions & 0 deletions
124
docs/syntax-attributes-for-types-variables-table-fields.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,124 @@ | ||
| # Allow attributes to be used on types, variables, and table fields | ||
|
|
||
| ## Summary | ||
|
|
||
| Allows [Attributes](./syntax-attributes-functions.md) to be applied to types, variables, and table fields in Luau. | ||
|
|
||
| ## Motivation | ||
|
|
||
| Currently attributes can only be applied to functions, this means types cannot be marked as [`@deprecated`](./syntax-attribute-functions-deprecated.md). | ||
| Nor can variables or table fields be marked as [`@deprecated`](./syntax-attribute-functions-deprecated.md). | ||
|
|
||
| ## Design | ||
|
|
||
| Note: With this RFC the internals for attributes will be able to state they can be applied to only certain bits of syntax, so one can't apply [`@native`](./syntax-attribute-functions-native.md) to a type or variable and have it work. Although this RFC does not state how this would be done in luaus internals. | ||
|
|
||
| The following list proposes how attributes should be attached to each bit of syntax in luau (except functions and comments): | ||
|
|
||
| ### Variables | ||
|
|
||
| This exists as it could be useful for if for instance a constant is defined as a local variable and then exported: | ||
|
|
||
| ```luau | ||
| @[deprecated { use = "dog"}] | ||
| local puppy = "whimper" | ||
|
|
||
| return table.freeze({ | ||
| puppy = puppy, | ||
| dog = "woof", | ||
| }) | ||
| ``` | ||
|
|
||
| Although this will cause the return in the module to be linted, but this lint won't be passed on to consumers of the module: | ||
|
|
||
| Module: | ||
|
|
||
| ```luau | ||
| -- DeprecatedApi: Variable 'puppy' is deprecated, use 'dog' instead Luau(22) | ||
| return table.freeze({ | ||
| puppy = puppy, | ||
| dog = "woof", | ||
| }) | ||
| ``` | ||
|
|
||
| Consumer: | ||
|
|
||
| ```luau | ||
| -- No lint occurs on the import | ||
| local module = require("@module") | ||
|
|
||
| -- DeprecatedApi: Member 'puppy' is deprecated, use 'dog' instead Luau(22) | ||
| print(module.puppy) | ||
| ``` | ||
|
|
||
| ### Tables | ||
|
|
||
| ```luau | ||
| local pet_sounds = { | ||
| @deprecated cat = "meow" | ||
| } | ||
|
|
||
| @deprecated module.dog = "woof" | ||
|
|
||
| @deprecated | ||
| module.parrot = "cracker, now" | ||
|
|
||
| return table.freeze(pet_sounds) | ||
| ``` | ||
|
|
||
| If the value of a field has attributes, those will be merged with the attributes defined on the field. | ||
| With the attributes on the field having priority over the attributes on the value. | ||
| For example: if both the value and the field have a `@deprecated` attribute, the `@deprecated` attribute on the value will be ignored. | ||
| With the `@deprecated` attribute on the field being used instead. | ||
|
|
||
| ```luau | ||
| @[deprecated { reason = "cat is a more modern API"}] | ||
| local function get_cat_sound() | ||
| return "meow" | ||
| end | ||
|
|
||
| -- DeprecatedApi: Function 'get_cat_sound' is deprecated, cat is a more modern API Luau(22) | ||
| local bad_module = table.freeze({ | ||
| get_cat_sound = get_cat_sound, | ||
| }) | ||
|
|
||
| -- No lint occurs, because the @deprecated attribute of the 'get_cat_sound' function has been overridden | ||
| -- by the @deprecated attribute of the field 'get_cat_sound'. | ||
| local module = table.freeze({ | ||
| @[deprecated{ use = "cat" }] get_cat_sound = get_cat_sound, | ||
| cat = "meow" | ||
| }) | ||
|
|
||
| -- DeprecatedApi: Member 'get_cat_sound' is deprecated, use 'cat' instead Luau(22) | ||
| module.get_cat_sound() | ||
| ``` | ||
|
|
||
| ### Types | ||
|
|
||
| Types work similarly to [Variables](#variables) and [Tables](#tables), except being types. | ||
|
|
||
| ```luau | ||
| @deprecated | ||
| type Puppy = "whimper" | ||
|
|
||
| -- DeprecatedApi: Type 'Puppy' is deprecated Luau(22) | ||
| type CanineSounds = { | ||
| puppy: Puppy, | ||
| dog: "woof", | ||
| } | ||
|
|
||
| -- No lint occurs, because the @deprecated attribute of the type 'Puppy' has been overridden | ||
| -- by the @deprecated attribute of the field 'puppy'. | ||
| type PetSounds = { | ||
| -- Just like with tables, entries have their attributes merged with the values attributes. | ||
| @deprecated{ use = "dog" } puppy: Puppy, | ||
| dog: "bark", | ||
| cat: "mrrp", | ||
| } | ||
| ``` | ||
|
|
||
| Although type declarations can also have attributes directly after the `=`, | ||
|
|
||
| ## Drawbacks | ||
|
|
||
| Allowing attributes to be on types, variables, and table fields, would be added complexity to the language. Although would be more inline with what a user would expect/want, as its odd from the perspective of a user that currently types can't be marked as deprecated. | ||
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.
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.
Will probably end up not having it work like this, as this is just sorta weird behavior?
But variables I would like to keep, as I could imagine it being useful for those who were not doing best practices before.
Like in the case of someone writing their entire game in one script, where they want to deprecate a variable because they split out its logic to a different module. With find and replace being time consuming when they're likely to just be rewriting most of everything. So having the
@deprecatedattribute on the variable would work as a reminder to not use that variable as they refactor.But this is literally only good for this one somewhat niche usecase, so perhaps ditching variable support would be a good idea?