Conversation
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Implement forced keywords (`k#`)
This comment has been minimized.
This comment has been minimized.
| /// Traits for function pointers and items | ||
| (unstable, fn_static, "CURRENT_RUSTC_VERSION", Some(148768)), | ||
| /// Allows using forced keywords `k#fn`. | ||
| (unstable, forced_keywords, "CURRENT_RUSTC_VERSION", Some(153839)), |
There was a problem hiding this comment.
I've intentionally not marked it internal even though this feature is only backed by a T-compiler MCP and not by a T-lang RFC or in-tree experiment:
I would find it a bit weird if we (in a hypothetical future) told users to "please try out" "k#only bounds" or "&k#own types & exprs" (features that would obviously be non-internal) but they'd have to enable an internal feature in tandem (could be perceived as off-putting).
However, I'm okay with switching it to incomplete or even internal if requested.
| @@ -103,6 +104,26 @@ impl ToInternal<tk::LitKind> for LitKind { | |||
| } | |||
| } | |||
|
|
|||
There was a problem hiding this comment.
We can't test the roundtripping in the current form of this PR because I haven't added any k#-exclusive weak keywords where it'd be observable if we accidentally dropped k# during encoding&decoding.
I have however tested locally that it works by introducing a new dummy keyword. A hypothetical UI test would have a setup like
use proc_macro::TokenStream;
#[proc_macro]
pub fn perform(_: TokenStream) -> TokenStream {
let stream: TokenStream = "const _: Option<k#never> = None;").parse().unwrap(); // positive
//let stream: TokenStream = "fn k#branded() {}").parse().unwrap(); // negative
stream.into_iter().collect() // forces encoding+decoding
}
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (4eb8eac): comparison URL. Overall result: ✅ improvements - no action neededBenchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up. @rustbot label: -S-waiting-on-perf -perf-regression Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -3.0%, secondary 1.1%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 2.1%, secondary -1.4%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary 0.0%, secondary -0.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 477.576s -> 469.017s (-1.79%) |
This comment has been minimized.
This comment has been minimized.
9e590de to
1de8681
Compare
k#)k#)
|
Ready for review. Caution Only review the commits created after ------------------------- BRANCH SEPARATOR -------------------------. Best reviewed commit by commit. |
|
Some changes occurred in compiler/rustc_builtin_macros/src/autodiff.rs cc @ZuseZ4
cc @rust-lang/rust-analyzer |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
||
| /// Returns `true` if this symbol can be a forced keyword. | ||
| pub fn can_be_forced_keyword(self) -> bool { | ||
| self.is_reserved(|| Edition::EditionFuture) || self.is_weak() |
There was a problem hiding this comment.
Either in this PR or in a follow-up PR I'll do something less hazardous than blindly using is_weak wrt. stability:
Let's assume forced_keywords was stable, then we certainly wouldn't want to insta-stabilize k#WEAK if somebody introduced an unstable keyword WEAK but that's what would happen in the current implementation as we'd immediately start accepting #[cfg(false)] M!(k#WEAK);.
(On main, declaring a weak keyword in symbol.rs doesn't have any semantic consequences, it just defines a new interned symbol for which is_weak (only used in diagnostics & tools atm) returns true. It's more of a convention, so you can write things like .is_keyword(kw::Weak) instead of .is_keyword(sym::weak) in the parser.)
Anyways, I plan on splitting splitting weak keywords into two categories, "stable" and "non-committal" (…). For the latter category, I'm either gonna issue a feature gate in lexer/mod.rs if forced with k# or I'm just not gonna allow using k# until stabilization. Emitting a feature gate for the token, too, means we'd start emitting two feature gates for unstable syntax (one in the lexer, one in the parser) which most likely wouldn't get deduplicated by our diagnostic infra since the spans will differ. There might be some tricks for avoiding it though. Will think about that some other time.
…rochenkov Move parse error recovery for expression operators "out of line" & refactor in the area **Background**: While we do have 3k-line module `rustc_parse/src/parser/diagnostics.rs`[^1] dedicated to syntax error diagnostics & parse error recovery, the rest of the parser is still "littered" or "interwoven" through and through with complex or verbose diagnostic code. We support numerous recoveries from syntaxes found in other languages right next to code that actually decides what is and what isn't part of Rust syntactically. This makes the parser code very messy, illegible, bug prone and otherwise hard to maintain. So my long-term plan is to push all this diagnostic & recovery code "out of line", namely into new `rustc_parse/src/parser/$fragment/diagnostics.rs` files, to keep the "inline code" of parsing routines in `$fragment.rs` focused on actually parsing Rust code. Why not just use the pre-existing `parser/diagnostics.rs` module? Well, making diagnostic code for expressions, patterns, types etc. share the same module is the definition of a hodgepodge. Moreover, moving all diagnostic code there would make the file way too large. Of course, for common code (if any) `parser/diagnostics.rs` would remain suitable. Best reviewed commit by commit. Commit [Refactor check_assoc_op to make it more legible](rust-lang@66311aa) was cherry-picked from my PR rust-lang#161775. <sub>(No LLM was or will be used by me during the entire creation process of this PR)</sub> [^1]: Not to be confused with `rustc_parse/src/diagnostics.rs` which holds diagnostic structs.
…rochenkov Move parse error recovery for expression operators "out of line" & refactor in the area **Background**: While we do have 3k-line module `rustc_parse/src/parser/diagnostics.rs`[^1] dedicated to syntax error diagnostics & parse error recovery, the rest of the parser is still "littered" or "interwoven" through and through with complex or verbose diagnostic code. We support numerous recoveries from syntaxes found in other languages right next to code that actually decides what is and what isn't part of Rust syntactically. This makes the parser code very messy, illegible, bug prone and otherwise hard to maintain. So my long-term plan is to push all this diagnostic & recovery code "out of line", namely into new `rustc_parse/src/parser/$fragment/diagnostics.rs` files, to keep the "inline code" of parsing routines in `$fragment.rs` focused on actually parsing Rust code. Why not just use the pre-existing `parser/diagnostics.rs` module? Well, making diagnostic code for expressions, patterns, types etc. share the same module is the definition of a hodgepodge. Moreover, moving all diagnostic code there would make the file way too large. Of course, for common code (if any) `parser/diagnostics.rs` would remain suitable. Best reviewed commit by commit. Commit [Refactor check_assoc_op to make it more legible](rust-lang@66311aa) was cherry-picked from my PR rust-lang#161775. <sub>(No LLM was or will be used by me during the entire creation process of this PR)</sub> [^1]: Not to be confused with `rustc_parse/src/diagnostics.rs` which holds diagnostic structs.
…rochenkov Move parse error recovery for expression operators "out of line" & refactor in the area **Background**: While we do have 3k-line module `rustc_parse/src/parser/diagnostics.rs`[^1] dedicated to syntax error diagnostics & parse error recovery, the rest of the parser is still "littered" or "interwoven" through and through with complex or verbose diagnostic code. We support numerous recoveries from syntaxes found in other languages right next to code that actually decides what is and what isn't part of Rust syntactically. This makes the parser code very messy, illegible, bug prone and otherwise hard to maintain. So my long-term plan is to push all this diagnostic & recovery code "out of line", namely into new `rustc_parse/src/parser/$fragment/diagnostics.rs` files, to keep the "inline code" of parsing routines in `$fragment.rs` focused on actually parsing Rust code. Why not just use the pre-existing `parser/diagnostics.rs` module? Well, making diagnostic code for expressions, patterns, types etc. share the same module is the definition of a hodgepodge. Moreover, moving all diagnostic code there would make the file way too large. Of course, for common code (if any) `parser/diagnostics.rs` would remain suitable. Best reviewed commit by commit. Commit [Refactor check_assoc_op to make it more legible](rust-lang@66311aa) was cherry-picked from my PR rust-lang#161775. <sub>(No LLM was or will be used by me during the entire creation process of this PR)</sub> [^1]: Not to be confused with `rustc_parse/src/diagnostics.rs` which holds diagnostic structs.
…rochenkov Move parse error recovery for expression operators "out of line" & refactor in the area **Background**: While we do have 3k-line module `rustc_parse/src/parser/diagnostics.rs`[^1] dedicated to syntax error diagnostics & parse error recovery, the rest of the parser is still "littered" or "interwoven" through and through with complex or verbose diagnostic code. We support numerous recoveries from syntaxes found in other languages right next to code that actually decides what is and what isn't part of Rust syntactically. This makes the parser code very messy, illegible, bug prone and otherwise hard to maintain. So my long-term plan is to push all this diagnostic & recovery code "out of line", namely into new `rustc_parse/src/parser/$fragment/diagnostics.rs` files, to keep the "inline code" of parsing routines in `$fragment.rs` focused on actually parsing Rust code. Why not just use the pre-existing `parser/diagnostics.rs` module? Well, making diagnostic code for expressions, patterns, types etc. share the same module is the definition of a hodgepodge. Moreover, moving all diagnostic code there would make the file way too large. Of course, for common code (if any) `parser/diagnostics.rs` would remain suitable. Best reviewed commit by commit. Commit [Refactor check_assoc_op to make it more legible](rust-lang@66311aa) was cherry-picked from my PR rust-lang#161775. <sub>(No LLM was or will be used by me during the entire creation process of this PR)</sub> [^1]: Not to be confused with `rustc_parse/src/diagnostics.rs` which holds diagnostic structs.
Rollup merge of #162591 - fmease:out-of-line-recovery, r=petrochenkov Move parse error recovery for expression operators "out of line" & refactor in the area **Background**: While we do have 3k-line module `rustc_parse/src/parser/diagnostics.rs`[^1] dedicated to syntax error diagnostics & parse error recovery, the rest of the parser is still "littered" or "interwoven" through and through with complex or verbose diagnostic code. We support numerous recoveries from syntaxes found in other languages right next to code that actually decides what is and what isn't part of Rust syntactically. This makes the parser code very messy, illegible, bug prone and otherwise hard to maintain. So my long-term plan is to push all this diagnostic & recovery code "out of line", namely into new `rustc_parse/src/parser/$fragment/diagnostics.rs` files, to keep the "inline code" of parsing routines in `$fragment.rs` focused on actually parsing Rust code. Why not just use the pre-existing `parser/diagnostics.rs` module? Well, making diagnostic code for expressions, patterns, types etc. share the same module is the definition of a hodgepodge. Moreover, moving all diagnostic code there would make the file way too large. Of course, for common code (if any) `parser/diagnostics.rs` would remain suitable. Best reviewed commit by commit. Commit [Refactor check_assoc_op to make it more legible](66311aa) was cherry-picked from my PR #161775. <sub>(No LLM was or will be used by me during the entire creation process of this PR)</sub> [^1]: Not to be confused with `rustc_parse/src/diagnostics.rs` which holds diagnostic structs.
This comment has been minimized.
This comment has been minimized.
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
Move parse error recovery for expression operators "out of line" & refactor in the area **Background**: While we do have 3k-line module `rustc_parse/src/parser/diagnostics.rs`[^1] dedicated to syntax error diagnostics & parse error recovery, the rest of the parser is still "littered" or "interwoven" through and through with complex or verbose diagnostic code. We support numerous recoveries from syntaxes found in other languages right next to code that actually decides what is and what isn't part of Rust syntactically. This makes the parser code very messy, illegible, bug prone and otherwise hard to maintain. So my long-term plan is to push all this diagnostic & recovery code "out of line", namely into new `rustc_parse/src/parser/$fragment/diagnostics.rs` files, to keep the "inline code" of parsing routines in `$fragment.rs` focused on actually parsing Rust code. Why not just use the pre-existing `parser/diagnostics.rs` module? Well, making diagnostic code for expressions, patterns, types etc. share the same module is the definition of a hodgepodge. Moreover, moving all diagnostic code there would make the file way too large. Of course, for common code (if any) `parser/diagnostics.rs` would remain suitable. Best reviewed commit by commit. Commit [Refactor check_assoc_op to make it more legible](rust-lang/rust@66311aa) was cherry-picked from my PR rust-lang/rust#161775. <sub>(No LLM was or will be used by me during the entire creation process of this PR)</sub> [^1]: Not to be confused with `rustc_parse/src/diagnostics.rs` which holds diagnostic structs.
|
☔ The latest upstream changes (presumably #163043) made this pull request unmergeable. Please resolve the merge conflicts by rebasing. |
View all comments
Part of #153839. CC @dianne
Introduces a new token kind to Rust >=2021 that looks like
k#identand that is called forced keyword (identifier). This is gated behind a new unstable feature calledforced_keywords. This is backed by compiler MCP 945.The
identink#identmust be a keyword (from any edition) or a weak/contextual keyword for the token to be valid.What won't be done in this PR:
'k#static)builtin # $ident($($tt)*)/ introducingk#-exclusive (weak) keywordsbuiltin #withk##162232 insteadgenanyway IINM)unionis only "active" if it's followed by a non-reserved identifier and under this PR the same rules apply tok#unioneven though that's not necessary; changing it would result in better diagnostics (e.g., fork#union struct {}:error: expected item, found `k#union`=>expected identifier, found keyword `struct`) and maybe also allow for disambiguation for other context-dependent keywordsproc_macro::IdentAPI to allow users to programmatically create forced keywords (might never be added)(No LLM was or will be used by me during the entire creation process of this PR)