-
Notifications
You must be signed in to change notification settings - Fork 715
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
Update keyword list #5681
Update keyword list #5681
Conversation
Visit the preview URL for this PR (updated for commit 7ce95ab): |
|
||
The following table lists the words | ||
that the Dart language reserves for its own use. | ||
Don't use these terms as identifiers unless the term notes an exception. |
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.
I think some form of the original guidance is appropriate here. It's almost never good style to use any of these as identifiers. So maybe say something like "These words cannot be used as identifiers unless otherwise noted. Even when allowed, using keywords as identifiers is confusing and should be avoided."?
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.
I don't see a reason to discourage the user of, fx, show
and hide
as variable or method names. Sometimes they are precisely what you want to use, and they work.
The thing users need to know are the actual restrictions: reserved words that cannot be used as a name, ever, and built-in identifiers that cannot be used as a type or prefix name.
The rest are not really important.
Or that many: hide
, show
, async
, sync
and on
. Now possibly also type
.
These are identifiers that can be used as names, even for types or prefixes (but as lower case, they shouldn't be names of types or extensions), but which also occur in a few specific places not as a name to be resolved, but as a keyword of a syntactic construct.
If this is a list of every word that occurs as a "keyword" (managing: not as a resolvable name) anywhere in the grammar, then those words should be included, and linked to the descriptions of the constructs where the word can occur.
That's a fine index, if someone sees a word they don't understand, they can look it up, and see what it means in the context where they found it.
That index can also double as the list of restrictions, saying which words are restricted words and built-in identifiers, wish it's useful information. It can even mention that type
cannot be the name of an extension
, as a unique restriction.
I don't think being on the list as a contextual keyword should imply that the word should not be used as a name.
(And await
and yield
should be listed as restricted words, with a comment that they're not reserved everywhere, because users should refrain from using them as names everywhere. Unlike show
or sync
, which are perfectly fine names.)
Trying to audit the changes that were made here (very hard to see in the diff), it looks like the changes are:
Is that a correct summary of the changes? @lrhn @munificent does that seem right to you? |
Without having checked everything, that does look like the changes that stand out. I don't think The And |
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.
I added some comments. Note that several words are used in the grammar as a structural part (e.g., hide
is a structural part of import 'x.dart' hide x;
, it isn't a name which is looked up in the scope), and yet there are no restrictions on these words as identifiers at all. For example, hide
can be the name of a variable, a parameter, a class, anything.
So they aren't contextual keywords (or contextual anything), they are just identifiers that happen to be recognized as structural elements in a few situations.
I suggested using the category nothing
for those words because there's nothing special about them as identifiers.
I also suggested several other changes for words whose classification is different than indicated in keywords.yml.
{{bii}} These keywords can't be used as class names, type names, | ||
or import prefixes. They can be used as identifiers in all other | ||
circumstances. |
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.
'Class names' is a subset of 'type names', and we may also want to mention a few other kinds of type names. Perhaps:
{{bii}} These keywords can't be used as class names, type names, | |
or import prefixes. They can be used as identifiers in all other | |
circumstances. | |
{{bii}} This keyword can't be used as the name of a type (a class, a | |
mixin, an enum, an extension type, or a type alias), or the name of | |
an extension, or as an import prefix. It can be used as an identifier | |
in all other circumstances. |
extension
declarations are singled out because that kind of declaration doesn't introduce a type. You could also include that into '(a class, a mixin, an enum, an extension, an extension type, or a type alias)' if it's considered overly pedantic to mention it separately. ;-)
I'm using a singular form because it makes everything in this paragraph a bit more straightforward and unambiguous, and also because a reader would often arrive at this paragraph because they want to know more about one specific identifier that they were looking at.
{{ckw}} These keywords can be used as an identifier | ||
depending on **context**. |
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.
Using a singlar form for consistency with lines 35-37:
{{ckw}} These keywords can be used as an identifier | |
depending on **context**. | |
{{ckw}} This keyword can be used as an identifier | |
depending on **context**. |
Also, 'these keywords' can be used as 'an identifier' isn't quite congruent.
type: reserved | ||
- term: 'async' | ||
link: /language/async | ||
type: context |
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.
async
is one of those identifiers that occur verbatim in a grammar rule, but there are no restrictions on the use of this identifier (it can be the name of a variable, a type, an import prefix, anything).
We need a separate category for these identifiers. I'll use nothing
as a strawman here, because there's nothing special about these words. They will be recognized as being a structural part of certain syntactic forms, not just as the name of a declared entity (like other identifiers).
type: context | |
type: nothing |
I'm using the same type
in several cases below, for the same reason.
type: context | ||
- term: 'base' | ||
link: /language/class-modifiers#base | ||
type: bit |
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.
type: bit | |
type: nothing |
type: reserved | ||
- term: 'covariant' | ||
link: /guides/language/sound-problems#the-covariant-keyword | ||
type: context |
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.
covariant
is a built-in identifier
type: context | |
type: bit |
type: reserved | ||
- term: 'sealed' | ||
link: /language/class-modifiers#sealed | ||
type: bit |
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.
type: bit | |
type: nothing |
type: bit | ||
- term: 'show' | ||
link: /language/libraries#importing-only-part-of-a-library | ||
type: context |
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.
type: context | |
type: nothing |
type: reserved | ||
- term: 'sync' | ||
link: /language/functions#generators | ||
type: context |
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.
type: context | |
type: nothing |
type: reserved | ||
- term: 'type' | ||
link: /language/extension-types | ||
type: reserved |
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.
This one is really tricky. I couldn't convince the language team to make it a built-in identifier, so it isn't. But it is just like a built-in identifier in that it cannot be the name of "some" kinds of declarations, except that it is only forbidden for an extension
declaration to have the name type
. That's again because it is confusing if extension type ...
can be an extension
whose name is 'type' rather than an extension type
. So let's call it a built-in identifier. It's almost true.
type: reserved | |
type: bit |
type: reserved | ||
- term: 'when' | ||
link: /language/branches#when | ||
type: reserved |
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.
type: reserved | |
type: nothing |
That might be a terminology difference, because that's precisely how I would define a "contextual keyword": As a word that has a meaning entirely based on the syntactic context it occcurs in, independently of how the same identifier may be used elsewhere. The reserved word The reserved word |
The word "keyword" isn't defined in our specification documents, we have only used it informally. It is quite useful in some situations to have an informal term that we can use in order to avoid being overly specific about some detailed distinctions. So I would actually prefer to avoid defining "contextual keyword" in the first place, because "keyword" is informal. But it does make sense to take context dependencies into account for specific words: We have three words that the parser can accept as an The third one is No other word has the ability to be an This is useful to know because it explains why I suggested that these words should be classified as Returning to In particular, such a word is never a contextually reserved word because it's never a reserved word, period.
The word The choice of reserved words is somewhat arbitrary, we just need to have enough of them to ensure that the grammar is parseable (using the kind of parsing technology that we want to use). For example, So there's nothing deep or "meaningful" about which words are reserved words and which ones are not, it's all a matter of restricting which words can occur as an However, it is a hugely breaking change to add new words to the set of reserved words, so we don't do that. The set of reserved words is a historical fact that just happens to suffice (as long as we're really careful whenever new syntax is introduced). The set of built-in identifiers is similar, though much less restrictive: They can be the name of everything which isn't a type or an import prefix. That's enough to remove a lot of ambiguity in some other parsing situations. We do add a new built-in identifier now and then. In any case, being a reserved word or a built-in identifier is a property of a word, not a property of a position in a syntactic construct. It serves no other purpose than preventing that word from being parsed as an So it's a The only modification of the status of a word that we have is the ability of those specific three words (
I'll buy that one. ;-) |
@eernstg @lrhn I'm not sure this discussion is really useful for this venue. We have a specification where we can and should be extremely precise about this, but the goal here is just to tell users what words they can't/shouldn't use as identifiers, with a bit of extra color for the ones that they can if they really have to. Are we in agreement about the set of corrections necessary here or should we schedule something to discuss? |
@leafpetersen @lrhn @eernstg : I am merging with @eernstg approval. We can always revisit. |
Fixes #3322
Fixes #4663
Staged: https://dart-dev--pr5681-fix-3322-h23qa9i6.web.app/language/keywords