diff options
| author | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2023-10-05 11:30:55 +0000 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2023-10-26 06:49:17 +0000 |
| commit | a61cf673cd10ed24394c3403e03d8f7cf1f50170 (patch) | |
| tree | dbf3c9adb68cb079695fc7b2e6999f162aeb42dd | |
| parent | ccb160d3432dff025ab62696a82e576bf08aa006 (diff) | |
| download | rust-a61cf673cd10ed24394c3403e03d8f7cf1f50170.tar.gz rust-a61cf673cd10ed24394c3403e03d8f7cf1f50170.zip | |
Reserve `gen` keyword for `gen {}` blocks and `gen fn` in 2024 edition
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/token.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_parse/messages.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 6 | ||||
| -rw-r--r-- | tests/ui/coroutine/gen_block.e2024.stderr | 10 | ||||
| -rw-r--r-- | tests/ui/coroutine/gen_block.none.stderr | 29 | ||||
| -rw-r--r-- | tests/ui/coroutine/gen_block.rs | 13 | ||||
| -rw-r--r-- | tests/ui/coroutine/gen_fn.e2024.stderr | 10 | ||||
| -rw-r--r-- | tests/ui/coroutine/gen_fn.none.stderr | 8 | ||||
| -rw-r--r-- | tests/ui/coroutine/gen_fn.rs | 8 |
14 files changed, 138 insertions, 4 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e94e26a63bc..543c528db44 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2357,6 +2357,12 @@ pub enum Async { No, } +#[derive(Copy, Clone, Encodable, Decodable, Debug)] +pub enum Gen { + Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId }, + No, +} + impl Async { pub fn is_async(self) -> bool { matches!(self, Async::Yes { .. }) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index dd879a14567..914c97a14ac 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -197,6 +197,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool { kw::Continue, kw::False, kw::For, + kw::Gen, kw::If, kw::Let, kw::Loop, diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index e0778f72bfe..9bedd7b8a33 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -278,6 +278,9 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}` parse_function_body_equals_expr = function body cannot be `= expression;` .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;` +parse_gen_block = `gen` blocks are not yet implemented + .help = only the keyword is reserved for now + parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index aeb4fd0a304..c0e94d15da0 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -521,6 +521,14 @@ pub(crate) struct CatchAfterTry { } #[derive(Diagnostic)] +#[diag(parse_gen_block)] +#[help] +pub(crate) struct GenBlock { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(parse_comma_after_base_struct)] #[note] pub(crate) struct CommaAfterBaseStruct { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 5157106f4e2..e59076acf4c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1422,6 +1422,9 @@ impl<'a> Parser<'a> { } else if this.is_try_block() { this.expect_keyword(kw::Try)?; this.parse_try_block(lo) + } else if this.is_gen_block() { + this.expect_keyword(kw::Gen)?; + this.parse_gen_block(lo) } else if this.eat_keyword(kw::Return) { this.parse_expr_return() } else if this.eat_keyword(kw::Continue) { @@ -3040,6 +3043,14 @@ impl<'a> Parser<'a> { } } + /// Parses a `gen {...}` expression (`gen` token already eaten). + fn parse_gen_block(&mut self, _span_lo: Span) -> PResult<'a, P<Expr>> { + let (_attrs, _body) = self.parse_inner_attrs_and_block()?; + + Err(errors::GenBlock { span: self.prev_token.span } + .into_diagnostic(&self.sess.span_diagnostic)) + } + fn is_do_catch_block(&self) -> bool { self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Catch]) @@ -3059,6 +3070,13 @@ impl<'a> Parser<'a> { && self.token.uninterpolated_span().at_least_rust_2018() } + fn is_gen_block(&self) -> bool { + self.token.is_keyword(kw::Gen) + && self + .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()) + && self.token.uninterpolated_span().at_least_rust_2024() + } + /// Parses an `async move? {...}` expression. fn parse_async_block(&mut self) -> PResult<'a, P<Expr>> { let lo = self.token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 982f601c0d5..4c76ade0139 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2297,9 +2297,9 @@ impl<'a> Parser<'a> { // `pub` is added in case users got confused with the ordering like `async pub fn`, // only if it wasn't preceded by `default` as `default pub` is invalid. let quals: &[Symbol] = if check_pub { - &[kw::Pub, kw::Const, kw::Async, kw::Unsafe, kw::Extern] + &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern] } else { - &[kw::Const, kw::Async, kw::Unsafe, kw::Extern] + &[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern] }; self.check_keyword_case(kw::Fn, case) // Definitely an `fn`. // `$qual fn` or `$qual $qual`: @@ -2353,6 +2353,9 @@ impl<'a> Parser<'a> { let async_start_sp = self.token.span; let asyncness = self.parse_asyncness(case); + let _gen_start_sp = self.token.span; + let genness = self.parse_genness(case); + let unsafe_start_sp = self.token.span; let unsafety = self.parse_unsafety(case); @@ -2368,6 +2371,10 @@ impl<'a> Parser<'a> { } } + if let Gen::Yes { span, .. } = genness { + self.sess.emit_err(errors::GenBlock { span }); + } + if !self.eat_keyword_case(kw::Fn, case) { // It is possible for `expect_one_of` to recover given the contents of // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 597303cae73..53c6d8acff1 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -11,6 +11,7 @@ mod stmt; mod ty; use crate::lexer::UnmatchedDelim; +use ast::Gen; pub use attr_wrapper::AttrWrapper; pub use diagnostics::AttemptLocalParseRecovery; pub(crate) use expr::ForbiddenLetReason; @@ -1126,6 +1127,16 @@ impl<'a> Parser<'a> { } } + /// Parses genness: `gen` or nothing. + fn parse_genness(&mut self, case: Case) -> Gen { + if self.token.span.at_least_rust_2024() && self.eat_keyword_case(kw::Gen, case) { + let span = self.prev_token.uninterpolated_span(); + Gen::Yes { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID } + } else { + Gen::No + } + } + /// Parses unsafety: `unsafe` or nothing. fn parse_unsafety(&mut self, case: Case) -> Unsafe { if self.eat_keyword_case(kw::Unsafe, case) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ff61143a12b..8ef16ed0dbf 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -98,6 +98,7 @@ symbols! { Builtin: "builtin", Catch: "catch", Default: "default", + Gen: "gen", MacroRules: "macro_rules", Raw: "raw", Union: "union", @@ -2188,8 +2189,9 @@ impl Symbol { self >= kw::Abstract && self <= kw::Yield } - fn is_unused_keyword_conditional(self, edition: impl FnOnce() -> Edition) -> bool { - self == kw::Try && edition() >= Edition::Edition2018 + fn is_unused_keyword_conditional(self, edition: impl Copy + FnOnce() -> Edition) -> bool { + self == kw::Try && edition().at_least_rust_2018() + || self == kw::Gen && edition().at_least_rust_2024() } pub fn is_reserved(self, edition: impl Copy + FnOnce() -> Edition) -> bool { diff --git a/tests/ui/coroutine/gen_block.e2024.stderr b/tests/ui/coroutine/gen_block.e2024.stderr new file mode 100644 index 00000000000..099a9d13cee --- /dev/null +++ b/tests/ui/coroutine/gen_block.e2024.stderr @@ -0,0 +1,10 @@ +error: `gen` blocks are not yet implemented + --> $DIR/gen_block.rs:5:18 + | +LL | let x = gen {}; + | ^ + | + = help: only the keyword is reserved for now + +error: aborting due to previous error + diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr new file mode 100644 index 00000000000..1cdd5d070ee --- /dev/null +++ b/tests/ui/coroutine/gen_block.none.stderr @@ -0,0 +1,29 @@ +error: expected identifier, found reserved keyword `yield` + --> $DIR/gen_block.rs:8:19 + | +LL | let y = gen { yield 42 }; + | --- ^^^^^ expected identifier, found reserved keyword + | | + | while parsing this struct + +error[E0422]: cannot find struct, variant or union type `gen` in this scope + --> $DIR/gen_block.rs:5:13 + | +LL | let x = gen {}; + | ^^^ not found in this scope + +error[E0422]: cannot find struct, variant or union type `gen` in this scope + --> $DIR/gen_block.rs:8:13 + | +LL | let y = gen { yield 42 }; + | ^^^ not found in this scope + +error[E0422]: cannot find struct, variant or union type `gen` in this scope + --> $DIR/gen_block.rs:11:5 + | +LL | gen {}; + | ^^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/coroutine/gen_block.rs b/tests/ui/coroutine/gen_block.rs new file mode 100644 index 00000000000..5c0db5b3d38 --- /dev/null +++ b/tests/ui/coroutine/gen_block.rs @@ -0,0 +1,13 @@ +// revisions: e2024 none +//[e2024] compile-flags: --edition 2024 -Zunstable-options + +fn main() { + let x = gen {}; + //[none]~^ ERROR: cannot find + //[e2024]~^^ ERROR: `gen` blocks are not yet implemented + let y = gen { yield 42 }; + //[none]~^ ERROR: found reserved keyword `yield` + //[none]~| ERROR: cannot find + gen {}; + //[none]~^ ERROR: cannot find +} diff --git a/tests/ui/coroutine/gen_fn.e2024.stderr b/tests/ui/coroutine/gen_fn.e2024.stderr new file mode 100644 index 00000000000..41bd04d9769 --- /dev/null +++ b/tests/ui/coroutine/gen_fn.e2024.stderr @@ -0,0 +1,10 @@ +error: `gen` blocks are not yet implemented + --> $DIR/gen_fn.rs:4:1 + | +LL | gen fn foo() {} + | ^^^ + | + = help: only the keyword is reserved for now + +error: aborting due to previous error + diff --git a/tests/ui/coroutine/gen_fn.none.stderr b/tests/ui/coroutine/gen_fn.none.stderr new file mode 100644 index 00000000000..5e7bd9d8bbf --- /dev/null +++ b/tests/ui/coroutine/gen_fn.none.stderr @@ -0,0 +1,8 @@ +error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen` + --> $DIR/gen_fn.rs:4:1 + | +LL | gen fn foo() {} + | ^^^ expected one of 9 possible tokens + +error: aborting due to previous error + diff --git a/tests/ui/coroutine/gen_fn.rs b/tests/ui/coroutine/gen_fn.rs new file mode 100644 index 00000000000..9566660dfb5 --- /dev/null +++ b/tests/ui/coroutine/gen_fn.rs @@ -0,0 +1,8 @@ +// revisions: e2024 none +//[e2024] compile-flags: --edition 2024 -Zunstable-options + +gen fn foo() {} +//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen` +//[e2024]~^^ ERROR: `gen` blocks are not yet implemented + +fn main() {} |
