Skip to content

Commit 8cfdccf

Browse files
authored
Rollup merge of #118419 - compiler-errors:await-span2, r=cjgillot
Eagerly return `ExprKind::Err` on `yield`/`await` in wrong coroutine context This PR does 2 things: 1. Refuses to lower `.await` or `yield` when we are outside of the right coroutine context for the operator. Instead, we lower to `hir::ExprKind::Err`, to silence subsequent redundant errors. 2. Reworks a bit of the span tracking in `LoweringContext` to fix a bad span when we have something like `let x = [0; async_fn().await]` where the `await` is inside of an anon const. The span for the "item" still kinda sucks, since it overlaps with the `await` span, but at least it's accurate.
2 parents b7016ae + dd5abb5 commit 8cfdccf

File tree

11 files changed

+36
-85
lines changed

11 files changed

+36
-85
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
7272
let kind = match &e.kind {
7373
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
7474
ExprKind::ConstBlock(c) => {
75-
let c = self.with_new_scopes(|this| hir::ConstBlock {
75+
let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock {
7676
def_id: this.local_def_id(c.id),
7777
hir_id: this.lower_node_id(c.id),
7878
body: this.lower_const_body(c.value.span, Some(&c.value)),
@@ -189,7 +189,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
189189
None,
190190
e.span,
191191
hir::CoroutineSource::Block,
192-
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
192+
|this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)),
193193
),
194194
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
195195
ExprKind::Closure(box Closure {
@@ -323,7 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
323323
None,
324324
e.span,
325325
hir::CoroutineSource::Block,
326-
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
326+
|this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)),
327327
),
328328
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
329329
ExprKind::Err => hir::ExprKind::Err(
@@ -756,10 +756,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
756756
match self.coroutine_kind {
757757
Some(hir::CoroutineKind::Async(_)) => {}
758758
Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => {
759-
self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
759+
return hir::ExprKind::Err(self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
760760
await_kw_span,
761761
item_span: self.current_item,
762-
});
762+
}));
763763
}
764764
}
765765
let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None);
@@ -919,9 +919,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
919919
) -> hir::ExprKind<'hir> {
920920
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
921921

922-
let (body_id, coroutine_option) = self.with_new_scopes(move |this| {
923-
let prev = this.current_item;
924-
this.current_item = Some(fn_decl_span);
922+
let (body_id, coroutine_option) = self.with_new_scopes(fn_decl_span, move |this| {
925923
let mut coroutine_kind = None;
926924
let body_id = this.lower_fn_body(decl, |this| {
927925
let e = this.lower_expr_mut(body);
@@ -930,7 +928,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
930928
});
931929
let coroutine_option =
932930
this.coroutine_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
933-
this.current_item = prev;
934931
(body_id, coroutine_option)
935932
});
936933

@@ -1016,7 +1013,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10161013
let outer_decl =
10171014
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
10181015

1019-
let body = self.with_new_scopes(|this| {
1016+
let body = self.with_new_scopes(fn_decl_span, |this| {
10201017
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
10211018
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
10221019
this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span });
@@ -1038,7 +1035,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10381035
async_ret_ty,
10391036
body.span,
10401037
hir::CoroutineSource::Closure,
1041-
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
1038+
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
10421039
);
10431040
let hir_id = this.lower_node_id(inner_closure_id);
10441041
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
@@ -1478,7 +1475,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
14781475
match self.coroutine_kind {
14791476
Some(hir::CoroutineKind::Gen(_)) => {}
14801477
Some(hir::CoroutineKind::Async(_)) => {
1481-
self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span });
1478+
return hir::ExprKind::Err(
1479+
self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }),
1480+
);
14821481
}
14831482
Some(hir::CoroutineKind::Coroutine) | None => {
14841483
if !self.tcx.features().coroutines {

compiler/rustc_ast_lowering/src/item.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
268268
body,
269269
..
270270
}) => {
271-
self.with_new_scopes(|this| {
272-
this.current_item = Some(ident.span);
273-
271+
self.with_new_scopes(ident.span, |this| {
274272
// Note: we don't need to change the return type from `T` to
275273
// `impl Future<Output = T>` here because lower_body
276274
// only cares about the input argument patterns in the function
@@ -867,7 +865,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
867865
},
868866
),
869867
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
870-
self.current_item = Some(i.span);
871868
let asyncness = sig.header.asyncness;
872869
let body_id = self.lower_maybe_async_body(
873870
i.span,

compiler/rustc_ast_lowering/src/lib.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
839839
result
840840
}
841841

842-
fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
842+
fn with_new_scopes<T>(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T {
843+
let current_item = self.current_item;
844+
self.current_item = Some(scope_span);
845+
843846
let was_in_loop_condition = self.is_in_loop_condition;
844847
self.is_in_loop_condition = false;
845848

@@ -851,6 +854,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
851854

852855
self.is_in_loop_condition = was_in_loop_condition;
853856

857+
self.current_item = current_item;
858+
854859
ret
855860
}
856861

@@ -1200,7 +1205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12001205
tokens: None,
12011206
};
12021207

1203-
let ct = self.with_new_scopes(|this| hir::AnonConst {
1208+
let ct = self.with_new_scopes(span, |this| hir::AnonConst {
12041209
def_id,
12051210
hir_id: this.lower_node_id(node_id),
12061211
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
@@ -2207,7 +2212,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22072212
}
22082213

22092214
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
2210-
self.with_new_scopes(|this| hir::AnonConst {
2215+
self.with_new_scopes(c.value.span, |this| hir::AnonConst {
22112216
def_id: this.local_def_id(c.id),
22122217
hir_id: this.lower_node_id(c.id),
22132218
body: this.lower_const_body(c.value.span, Some(&c.value)),

compiler/rustc_error_codes/src/error_codes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -653,3 +653,4 @@ E0795: include_str!("./error_codes/E0795.md"),
653653
// E0721, // `await` keyword
654654
// E0723, // unstable feature in `const` context
655655
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
656+
// E0744, // merged into E0728

compiler/rustc_error_codes/src/error_codes/E0744.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
An unsupported expression was used inside a const context.
24

35
Erroneous code example:
46

5-
```compile_fail,edition2018,E0744
7+
```ignore (removed error code)
68
const _: i32 = {
79
async { 0 }.await
810
};

compiler/rustc_passes/src/check_const.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_middle::ty::TyCtxt;
1717
use rustc_session::parse::feature_err;
1818
use rustc_span::{sym, Span, Symbol};
1919

20-
use crate::errors::{ExprNotAllowedInContext, SkippingConstChecks};
20+
use crate::errors::SkippingConstChecks;
2121

2222
/// An expression that is not *always* legal in a const context.
2323
#[derive(Clone, Copy)]
@@ -138,11 +138,10 @@ impl<'tcx> CheckConstVisitor<'tcx> {
138138

139139
match missing_gates.as_slice() {
140140
[] => {
141-
tcx.sess.emit_err(ExprNotAllowedInContext {
141+
span_bug!(
142142
span,
143-
expr: expr.name(),
144-
context: const_kind.keyword_name(),
145-
});
143+
"we should not have reached this point, since `.await` is denied earlier"
144+
);
146145
}
147146

148147
[missing_primary, ref missing_secondary @ ..] => {

compiler/rustc_passes/src/errors.rs

-9
Original file line numberDiff line numberDiff line change
@@ -1005,15 +1005,6 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> {
10051005
pub prev_declared: &'b str,
10061006
}
10071007

1008-
#[derive(Diagnostic)]
1009-
#[diag(passes_expr_not_allowed_in_context, code = "E0744")]
1010-
pub struct ExprNotAllowedInContext<'a> {
1011-
#[primary_span]
1012-
pub span: Span,
1013-
pub expr: String,
1014-
pub context: &'a str,
1015-
}
1016-
10171008
pub struct BreakNonLoop<'a> {
10181009
pub span: Span,
10191010
pub head: Option<Span>,

tests/ui/async-await/issue-70594.rs

-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
async fn fun() {
44
[1; ().await];
55
//~^ error: `await` is only allowed inside `async` functions and blocks
6-
//~| error: `.await` is not allowed in a `const`
7-
//~| error: `.await` is not allowed in a `const`
8-
//~| error: `()` is not a future
96
}
107

118
fn main() {}
+6-31
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,12 @@
11
error[E0728]: `await` is only allowed inside `async` functions and blocks
22
--> $DIR/issue-70594.rs:4:12
33
|
4-
LL | async fn fun() {
5-
| --- this is not `async`
64
LL | [1; ().await];
7-
| ^^^^^ only allowed inside `async` functions and blocks
5+
| ---^^^^^
6+
| | |
7+
| | only allowed inside `async` functions and blocks
8+
| this is not `async`
89

9-
error[E0744]: `.await` is not allowed in a `const`
10-
--> $DIR/issue-70594.rs:4:9
11-
|
12-
LL | [1; ().await];
13-
| ^^^^^^^^
14-
15-
error[E0744]: `.await` is not allowed in a `const`
16-
--> $DIR/issue-70594.rs:4:12
17-
|
18-
LL | [1; ().await];
19-
| ^^^^^
20-
21-
error[E0277]: `()` is not a future
22-
--> $DIR/issue-70594.rs:4:12
23-
|
24-
LL | [1; ().await];
25-
| -^^^^^
26-
| ||
27-
| |`()` is not a future
28-
| help: remove the `.await`
29-
|
30-
= help: the trait `Future` is not implemented for `()`
31-
= note: () must be a future or must implement `IntoFuture` to be awaited
32-
= note: required for `()` to implement `IntoFuture`
33-
34-
error: aborting due to 4 previous errors
10+
error: aborting due to 1 previous error
3511

36-
Some errors have detailed explanations: E0277, E0728, E0744.
37-
For more information about an error, try `rustc --explain E0277`.
12+
For more information about this error, try `rustc --explain E0728`.

tests/ui/async-await/issues/issue-62009-1.rs

-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,4 @@ fn main() {
1111
//~^ ERROR `await` is only allowed inside `async` functions and blocks
1212
(|_| 2333).await;
1313
//~^ ERROR `await` is only allowed inside `async` functions and blocks
14-
//~| ERROR is not a future
1514
}

tests/ui/async-await/issues/issue-62009-1.stderr

+2-16
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,6 @@ LL | fn main() {
2424
LL | (|_| 2333).await;
2525
| ^^^^^ only allowed inside `async` functions and blocks
2626

27-
error[E0277]: `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future
28-
--> $DIR/issue-62009-1.rs:12:16
29-
|
30-
LL | (|_| 2333).await;
31-
| -^^^^^
32-
| ||
33-
| |`{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future
34-
| help: remove the `.await`
35-
|
36-
= help: the trait `Future` is not implemented for closure `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}`
37-
= note: {closure@$DIR/issue-62009-1.rs:12:6: 12:9} must be a future or must implement `IntoFuture` to be awaited
38-
= note: required for `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` to implement `IntoFuture`
39-
40-
error: aborting due to 4 previous errors
27+
error: aborting due to 3 previous errors
4128

42-
Some errors have detailed explanations: E0277, E0728.
43-
For more information about an error, try `rustc --explain E0277`.
29+
For more information about this error, try `rustc --explain E0728`.

0 commit comments

Comments
 (0)