Repository navigation
Stabilize reserved prefixes #88140
Description
Activity
@rfcbot fcp merge
I propose that we stabilize reserved prefixes. Note that they will not be exposed to stable completely until Rust 2021 is stabilized.
Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged team members:
Concerns:
no-reference-PRresolved by Stabilize reserved prefixes #88140 (comment)
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
- addedproposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.This issue / PR is in PFCP or FCP with a disposition to merge it.
on Aug 18, 2021 @rfcbot concern no-reference-PR
We need to describe these changes in the Rust reference!
Edition used for procedural macro APIs
There are some procedural macro APIs that lex tokens from strings. Those APIs have not traditionally taken a span or other information from which an edition can be derived. Those APIs will be documented with the Edition that they use to do lexing. In the future we may wish to add new APIs that take a Span or other parameter and use that to derive the Edition.
proc_macro::TokenStream::from_strandproc_macro::Literal::from_strare affected, and now use the edition of the proc macro definition. (They use thecall_spanfor all tokens they produce, which carries the source location of the invocation, but the edition of the proc macro definition.)This affects
quote::quote!{}, which will have to be updated to Rust 2021 before you can use prefixed things with it. That's not relevant right now since all the prefixes are reserved anyway. (It becomes relevant once we add z"" or something.)This FCP needs to start today to make it in time for 1.56.
We need to describe these changes in the Rust reference!
@nikomatsakis I don't think that needs to block the start of the FCP, right? Can you resolve your concern? We can handle the reference while the FCP is in progress.
@rfcbot resolve no-reference-PR
I'm going to mark this as resolved for now but try to get this done ASAP
- addedfinal-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.In the final comment period and will be merged soon unless new substantive objections are raised.and removedproposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
on Aug 23, 2021 🔔 This is now entering its final comment period, as per the review above. 🔔
Reacted by Yosh- addedfinished-final-comment-periodThe final comment period is finished for this PR / Issue.The final comment period is finished for this PR / Issue.and removedfinal-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.In the final comment period and will be merged soon unless new substantive objections are raised.
on Sep 2, 2021 The final comment period, with a disposition to merge, as per the review above, is now complete.
As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
The RFC will be merged soon.
- addedto-announceAnnounce this issue on triage meetingAnnounce this issue on triage meeting
on Sep 2, 2021 - removedto-announceAnnounce this issue on triage meetingAnnounce this issue on triage meeting
on Sep 18, 2021 AFAICT this is done.
Reserved prefixes stabilization report
Links
Summary
any_identifier#,any_identifier"...", andany_identifier'...'are now reservedsyntax, and no longer tokenize.
quote!{ #a#b }is no longer accepted.match"..." {}is no longer accepted.#,", or'to avoid errors.
Details
To make space for new syntax in the future, we've decided to reserve syntax for prefixed identifiers and literals:
prefix#identifier,prefix"string",prefix'c', andprefix#123, whereprefixcan be any identifier. (Except those prefixes that already have a meaning, such asb'...'(byte strings) andr"..."(raw strings).)This provides syntax we can expand into in the future without requiring an edition boundary. We may use this for temporary syntax until the next edition, or for permanent syntax if appropriate.
Without an edition, this would be a breaking change, since macros can currently accept syntax such as
hello"world", which they will see as two separate tokens:helloand"world". The (automatic) fix is simple though: just insert a space:hello "world". Likewise,prefix#identshould becomeprefix #ident. Edition migrations will help with this fix.Other than turning these into a tokenization error, the RFC does not attach a meaning to any prefix yet. Assigning meaning to specific prefixes is left to future proposals, which will now—thanks to reserving these prefixes—not be breaking changes.
Some new prefixes you might potentially see in the future (though we haven't
committed to any of them yet):
k#keywordto allow writing keywords that don't exist yet in the current edition. For example, whileasyncis not a keyword in edition 2015, this prefix would've allowed us to acceptk#asyncin edition 2015 without having to wait for edition 2018 to reserveasyncas a keyword.f""as a short-hand for a format string. For example,f"hello {name}"as a short-hand for the equivalentformat!()invocation.s""forStringliterals.c""orz""for null-terminated C strings.How unresolved questions were resolved and other interesting developments
Where and how to enforce prefixes
The biggest question was where to enforce the prefixes and emit errors. We ultimately opted to emit errors in the lexer, which meant that the lexer had to become aware of the current edition. There was an alternative of using "jointness" and enforcing the conditions in the parser. The idea was to leverage the fact that Rust tokens (at least some subset of them) record not only their content but whether they are separated by whitespace from the next token. This was intended to enable compound operators like
<<to be parsed as two<tokens in some parts øf the parser (types) and as a single token elsewhere (expressions), without the lexer having to know what state the parser was in. This same approach could conceptually be used so that the lexer doesn't have to know the edition.As described in detail in this writeup, however, the jointness approach had several downsides. For example, it meant that lexing of literals was independent of prefix: we might like
f"{foo("bar")}"to be lexed a a string, but that is not possible unless the lexer knows that anfstring can contain embedded expressions. Similarly, which escape codes the lexer accepts depends on the prefix (e.g. \x for b""). (This is especially relevant for raw strings: whetherfr"\"is accepted or not depends on what meaning we assign tofr.) Jointness also had forwards compatbility hazards with macro arm ordering. Finally, the lexer-based approach can be converted to a jointness-based approach later, as it currently gives errors much earlier in the process.There were also advantages to jointness: it would allow more procedural macro prototyping, and it means that the lexer would remain independent of edition.
Edition used for procedural macro APIs
There are some procedural macro APIs that lex tokens from strings. Those APIs have not traditionally taken a span or other information from which an edition can be derived. Those APIs will be documented with the Edition that they use to do lexing. In the future we may wish to add new APIs that take a Span or other parameter and use that to derive the Edition.