From a76d2e1fd13b69b81b05560d727c000df5c44581 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 28 Nov 2023 18:35:59 +0000 Subject: [PATCH 1/3] Eagerly return ExprKind::Err on yield/await in wrong coroutine context --- compiler/rustc_ast_lowering/src/expr.rs | 6 +++--- tests/ui/async-await/issue-70594.rs | 3 --- tests/ui/async-await/issues/issue-62009-1.rs | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 180459efef920..b62e647164415 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -778,10 +778,10 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.coroutine_kind { Some(hir::CoroutineKind::Async(_)) => {} Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => { - self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { + return hir::ExprKind::Err(self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { await_kw_span, item_span: self.current_item, - }); + })); } } let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None); @@ -1500,7 +1500,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.coroutine_kind { Some(hir::CoroutineKind::Gen(_)) => {} Some(hir::CoroutineKind::Async(_)) => { - self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }); + return hir::ExprKind::Err(self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span })); } Some(hir::CoroutineKind::Coroutine) | None => { if !self.tcx.features().coroutines { diff --git a/tests/ui/async-await/issue-70594.rs b/tests/ui/async-await/issue-70594.rs index 9e7c5847b3b2e..4c8209348b37a 100644 --- a/tests/ui/async-await/issue-70594.rs +++ b/tests/ui/async-await/issue-70594.rs @@ -3,9 +3,6 @@ async fn fun() { [1; ().await]; //~^ error: `await` is only allowed inside `async` functions and blocks - //~| error: `.await` is not allowed in a `const` - //~| error: `.await` is not allowed in a `const` - //~| error: `()` is not a future } fn main() {} diff --git a/tests/ui/async-await/issues/issue-62009-1.rs b/tests/ui/async-await/issues/issue-62009-1.rs index 40ccf25712e2b..51d216408d7ee 100644 --- a/tests/ui/async-await/issues/issue-62009-1.rs +++ b/tests/ui/async-await/issues/issue-62009-1.rs @@ -11,5 +11,4 @@ fn main() { //~^ ERROR `await` is only allowed inside `async` functions and blocks (|_| 2333).await; //~^ ERROR `await` is only allowed inside `async` functions and blocks - //~| ERROR is not a future } From f2c500bb434427f693cb9f6b02d675673808b6f9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 28 Nov 2023 19:06:23 +0000 Subject: [PATCH 2/3] Fix spans for bad await in inline const --- compiler/rustc_ast_lowering/src/expr.rs | 19 +++++----- compiler/rustc_ast_lowering/src/item.rs | 5 +-- compiler/rustc_ast_lowering/src/lib.rs | 11 ++++-- tests/ui/async-await/issue-70594.stderr | 37 +++---------------- .../async-await/issues/issue-62009-1.stderr | 18 +-------- 5 files changed, 26 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b62e647164415..43b345292c8b3 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -72,7 +72,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), ExprKind::ConstBlock(c) => { - let c = self.with_new_scopes(|this| hir::ConstBlock { + let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), @@ -189,7 +189,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None, e.span, hir::CoroutineSource::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), ), ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), ExprKind::Closure(box Closure { @@ -323,7 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None, e.span, hir::CoroutineSource::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), ), ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err => hir::ExprKind::Err( @@ -941,9 +941,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); - let (body_id, coroutine_option) = self.with_new_scopes(move |this| { - let prev = this.current_item; - this.current_item = Some(fn_decl_span); + let (body_id, coroutine_option) = self.with_new_scopes(fn_decl_span, move |this| { let mut coroutine_kind = None; let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr_mut(body); @@ -952,7 +950,6 @@ impl<'hir> LoweringContext<'_, 'hir> { }); let coroutine_option = this.coroutine_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); - this.current_item = prev; (body_id, coroutine_option) }); @@ -1038,7 +1035,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let outer_decl = FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - let body = self.with_new_scopes(|this| { + let body = self.with_new_scopes(fn_decl_span, |this| { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); @@ -1060,7 +1057,7 @@ impl<'hir> LoweringContext<'_, 'hir> { async_ret_ty, body.span, hir::CoroutineSource::Closure, - |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), + |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), ); let hir_id = this.lower_node_id(inner_closure_id); this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); @@ -1500,7 +1497,9 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.coroutine_kind { Some(hir::CoroutineKind::Gen(_)) => {} Some(hir::CoroutineKind::Async(_)) => { - return hir::ExprKind::Err(self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span })); + return hir::ExprKind::Err( + self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }), + ); } Some(hir::CoroutineKind::Coroutine) | None => { if !self.tcx.features().coroutines { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index fb75471ede3bc..5c42012c1dfad 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -268,9 +268,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body, .. }) => { - self.with_new_scopes(|this| { - this.current_item = Some(ident.span); - + self.with_new_scopes(ident.span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future` here because lower_body // only cares about the input argument patterns in the function @@ -867,7 +865,6 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ), AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => { - self.current_item = Some(i.span); let asyncness = sig.header.asyncness; let body_id = self.lower_maybe_async_body( i.span, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4c7b9b4155fdf..11e980370b863 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -839,7 +839,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { result } - fn with_new_scopes(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + fn with_new_scopes(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T { + let current_item = self.current_item; + self.current_item = Some(scope_span); + let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; @@ -851,6 +854,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.is_in_loop_condition = was_in_loop_condition; + self.current_item = current_item; + ret } @@ -1200,7 +1205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }; - let ct = self.with_new_scopes(|this| hir::AnonConst { + let ct = self.with_new_scopes(span, |this| hir::AnonConst { def_id, hir_id: this.lower_node_id(node_id), body: this.lower_const_body(path_expr.span, Some(&path_expr)), @@ -2207,7 +2212,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { - self.with_new_scopes(|this| hir::AnonConst { + self.with_new_scopes(c.value.span, |this| hir::AnonConst { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), diff --git a/tests/ui/async-await/issue-70594.stderr b/tests/ui/async-await/issue-70594.stderr index 9866e00bb83a9..aed99ec3f1f08 100644 --- a/tests/ui/async-await/issue-70594.stderr +++ b/tests/ui/async-await/issue-70594.stderr @@ -1,37 +1,12 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-70594.rs:4:12 | -LL | async fn fun() { - | --- this is not `async` LL | [1; ().await]; - | ^^^^^ only allowed inside `async` functions and blocks + | ---^^^^^ + | | | + | | only allowed inside `async` functions and blocks + | this is not `async` -error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:9 - | -LL | [1; ().await]; - | ^^^^^^^^ - -error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:12 - | -LL | [1; ().await]; - | ^^^^^ - -error[E0277]: `()` is not a future - --> $DIR/issue-70594.rs:4:12 - | -LL | [1; ().await]; - | -^^^^^ - | || - | |`()` is not a future - | help: remove the `.await` - | - = help: the trait `Future` is not implemented for `()` - = note: () must be a future or must implement `IntoFuture` to be awaited - = note: required for `()` to implement `IntoFuture` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0728, E0744. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-62009-1.stderr b/tests/ui/async-await/issues/issue-62009-1.stderr index bb617d09076f0..02933f4f2f233 100644 --- a/tests/ui/async-await/issues/issue-62009-1.stderr +++ b/tests/ui/async-await/issues/issue-62009-1.stderr @@ -24,20 +24,6 @@ LL | fn main() { LL | (|_| 2333).await; | ^^^^^ only allowed inside `async` functions and blocks -error[E0277]: `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future - --> $DIR/issue-62009-1.rs:12:16 - | -LL | (|_| 2333).await; - | -^^^^^ - | || - | |`{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future - | help: remove the `.await` - | - = help: the trait `Future` is not implemented for closure `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` - = note: {closure@$DIR/issue-62009-1.rs:12:6: 12:9} must be a future or must implement `IntoFuture` to be awaited - = note: required for `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` to implement `IntoFuture` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0728. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0728`. From dd5abb50cc08a212d23be1fb8482ae166e9bc738 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 28 Nov 2023 20:40:38 +0000 Subject: [PATCH 3/3] Yeet E0744 --- compiler/rustc_error_codes/src/error_codes.rs | 1 + compiler/rustc_error_codes/src/error_codes/E0744.md | 4 +++- compiler/rustc_passes/src/check_const.rs | 9 ++++----- compiler/rustc_passes/src/errors.rs | 9 --------- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 6680e8875c3e3..1028d43f9c5ba 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -653,3 +653,4 @@ E0795: include_str!("./error_codes/E0795.md"), // E0721, // `await` keyword // E0723, // unstable feature in `const` context // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. +// E0744, // merged into E0728 diff --git a/compiler/rustc_error_codes/src/error_codes/E0744.md b/compiler/rustc_error_codes/src/error_codes/E0744.md index 9a8ef3b840dff..e56c45db1766e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0744.md +++ b/compiler/rustc_error_codes/src/error_codes/E0744.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + An unsupported expression was used inside a const context. Erroneous code example: -```compile_fail,edition2018,E0744 +```ignore (removed error code) const _: i32 = { async { 0 }.await }; diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index de96746e215c1..76c7467346d37 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::{sym, Span, Symbol}; -use crate::errors::{ExprNotAllowedInContext, SkippingConstChecks}; +use crate::errors::SkippingConstChecks; /// An expression that is not *always* legal in a const context. #[derive(Clone, Copy)] @@ -138,11 +138,10 @@ impl<'tcx> CheckConstVisitor<'tcx> { match missing_gates.as_slice() { [] => { - tcx.sess.emit_err(ExprNotAllowedInContext { + span_bug!( span, - expr: expr.name(), - context: const_kind.keyword_name(), - }); + "we should not have reached this point, since `.await` is denied earlier" + ); } [missing_primary, ref missing_secondary @ ..] => { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 411c9410195f1..5812744532280 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1005,15 +1005,6 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> { pub prev_declared: &'b str, } -#[derive(Diagnostic)] -#[diag(passes_expr_not_allowed_in_context, code = "E0744")] -pub struct ExprNotAllowedInContext<'a> { - #[primary_span] - pub span: Span, - pub expr: String, - pub context: &'a str, -} - pub struct BreakNonLoop<'a> { pub span: Span, pub head: Option,