Skip to content

Commit 669e751

Browse files
committed
Auto merge of #104833 - Swatinem:async-identity-future, r=compiler-errors
Remove `identity_future` indirection This was previously needed because the indirection used to hide some unexplained lifetime errors, which it turned out were related to the `min_choice` algorithm. Removing the indirection also solves a couple of cycle errors, large moves and makes async blocks support the `#[track_caller]`annotation. Fixes #104826.
2 parents 0058748 + 9f03cfc commit 669e751

32 files changed

+145
-357
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+27-37
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
3232
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
3333
ensure_sufficient_stack(|| {
3434
match &e.kind {
35-
// Paranthesis expression does not have a HirId and is handled specially.
35+
// Parenthesis expression does not have a HirId and is handled specially.
3636
ExprKind::Paren(ex) => {
3737
let mut ex = self.lower_expr_mut(ex);
3838
// Include parens in span, but only if it is a super-span.
@@ -63,6 +63,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
6363
ExprKind::ForLoop(pat, head, body, opt_label) => {
6464
return self.lower_expr_for(e, pat, head, body, *opt_label);
6565
}
66+
// Similarly, async blocks do not use `e.id` but rather `closure_node_id`.
67+
ExprKind::Async(capture_clause, closure_node_id, block) => {
68+
let hir_id = self.lower_node_id(*closure_node_id);
69+
self.lower_attrs(hir_id, &e.attrs);
70+
return self.make_async_expr(
71+
*capture_clause,
72+
hir_id,
73+
*closure_node_id,
74+
None,
75+
e.span,
76+
hir::AsyncGeneratorKind::Block,
77+
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
78+
);
79+
}
6680
_ => (),
6781
}
6882

@@ -173,15 +187,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
173187
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
174188
hir::MatchSource::Normal,
175189
),
176-
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
177-
*capture_clause,
178-
hir_id,
179-
*closure_node_id,
180-
None,
181-
e.span,
182-
hir::AsyncGeneratorKind::Block,
183-
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
184-
),
185190
ExprKind::Await(expr) => {
186191
let dot_await_span = if expr.span.hi() < e.span.hi() {
187192
let span_with_whitespace = self
@@ -315,7 +320,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
315320
),
316321
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
317322

318-
ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
323+
ExprKind::Paren(_) | ExprKind::ForLoop(..) | ExprKind::Async(..) => {
324+
unreachable!("already handled")
325+
}
319326

320327
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
321328
};
@@ -577,9 +584,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
577584
/// This results in:
578585
///
579586
/// ```text
580-
/// std::future::identity_future(static move? |_task_context| -> <ret_ty> {
587+
/// static move? |_task_context| -> <ret_ty> {
581588
/// <body>
582-
/// })
589+
/// }
583590
/// ```
584591
pub(super) fn make_async_expr(
585592
&mut self,
@@ -590,7 +597,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
590597
span: Span,
591598
async_gen_kind: hir::AsyncGeneratorKind,
592599
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
593-
) -> hir::ExprKind<'hir> {
600+
) -> hir::Expr<'hir> {
594601
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
595602

596603
// Resume argument type: `ResumeTy`
@@ -655,13 +662,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
655662
};
656663

657664
let hir_id = self.lower_node_id(closure_node_id);
658-
let unstable_span =
659-
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
660-
661665
if self.tcx.features().closure_track_caller
662666
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
663667
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
664668
{
669+
let unstable_span =
670+
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
665671
self.lower_attrs(
666672
hir_id,
667673
&[Attribute {
@@ -680,22 +686,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
680686
);
681687
}
682688

683-
let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
684-
685-
// FIXME(swatinem):
686-
// For some reason, the async block needs to flow through *any*
687-
// call (like the identity function), as otherwise type and lifetime
688-
// inference have a hard time figuring things out.
689-
// Without this, we would get:
690-
// E0720 in tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
691-
// E0700 in tests/ui/self/self_lifetime-async.rs
692-
693-
// `future::identity_future`:
694-
let identity_future =
695-
self.expr_lang_item_path(unstable_span, hir::LangItem::IdentityFuture, None);
696-
697-
// `future::identity_future(generator)`:
698-
hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
689+
hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) }
699690
}
700691

701692
/// Desugar `<expr>.await` into:
@@ -1001,7 +992,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
1001992
}
1002993

1003994
// Transform `async |x: u8| -> X { ... }` into
1004-
// `|x: u8| identity_future(|| -> X { ... })`.
995+
// `|x: u8| || -> X { ... }`.
1005996
let body_id = this.lower_fn_body(&outer_decl, |this| {
1006997
let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
1007998
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
@@ -1010,16 +1001,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
10101001
None
10111002
};
10121003

1013-
let async_body = this.make_async_expr(
1004+
this.make_async_expr(
10141005
capture_clause,
10151006
closure_hir_id,
10161007
inner_closure_id,
10171008
async_ret_ty,
10181009
body.span,
10191010
hir::AsyncGeneratorKind::Closure,
10201011
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
1021-
);
1022-
this.expr(fn_decl_span, async_body)
1012+
)
10231013
});
10241014
body_id
10251015
});

compiler/rustc_ast_lowering/src/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11801180
},
11811181
);
11821182

1183-
(this.arena.alloc_from_iter(parameters), this.expr(body.span, async_expr))
1183+
(this.arena.alloc_from_iter(parameters), async_expr)
11841184
})
11851185
}
11861186

compiler/rustc_hir/src/lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,6 @@ language_item_table! {
296296
// FIXME(swatinem): the following lang items are used for async lowering and
297297
// should become obsolete eventually.
298298
ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
299-
IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
300299
GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
301300

302301
Context, sym::Context, context, Target::Struct, GenericRequirement::None;

compiler/rustc_hir_typeck/src/callee.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
311311
let fn_decl_span = if hir.body(body).generator_kind
312312
== Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure))
313313
{
314-
// Actually need to unwrap a few more layers of HIR to get to
314+
// Actually need to unwrap one more layer of HIR to get to
315315
// the _real_ closure...
316-
let async_closure = hir.parent_id(hir.parent_id(parent_hir_id));
316+
let async_closure = hir.parent_id(parent_hir_id);
317317
if let hir::Node::Expr(hir::Expr {
318318
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
319319
..

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -924,12 +924,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
924924
hir_id,
925925
kind: hir::ExprKind::Closure(..),
926926
..
927-
}) if let Some(Node::Expr(&hir::Expr {
928-
hir_id,
929-
kind: hir::ExprKind::Call(..),
930-
..
931-
})) = self.tcx.hir().find_parent(hir_id) &&
932-
let Some(Node::Item(&hir::Item {
927+
}) if let Some(Node::Item(&hir::Item {
933928
ident,
934929
kind: hir::ItemKind::Fn(ref sig, ..),
935930
..

compiler/rustc_span/src/symbol.rs

-1
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,6 @@ symbols! {
792792
i64,
793793
i8,
794794
ident,
795-
identity_future,
796795
if_let,
797796
if_let_guard,
798797
if_while_or_patterns,

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -3033,8 +3033,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30333033
}
30343034
};
30353035

3036-
let identity_future = tcx.require_lang_item(LangItem::IdentityFuture, None);
3037-
30383036
// Don't print the tuple of capture types
30393037
'print: {
30403038
if !is_upvar_tys_infer_tuple {
@@ -3047,12 +3045,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30473045
None => err.note(&msg),
30483046
},
30493047
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
3050-
// Avoid printing the future from `core::future::identity_future`, it's not helpful
3051-
if tcx.parent(*def_id) == identity_future {
3052-
break 'print;
3053-
}
3054-
3055-
// If the previous type is `identity_future`, this is the future generated by the body of an async function.
3048+
// If the previous type is async fn, this is the future generated by the body of an async function.
30563049
// Avoid printing it twice (it was already printed in the `ty::Generator` arm below).
30573050
let is_future = tcx.ty_is_opaque_future(ty);
30583051
debug!(

library/core/src/future/mod.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
6767
unsafe { &mut *cx.0.as_ptr().cast() }
6868
}
6969

70-
// FIXME(swatinem): This fn is currently needed to work around shortcomings
71-
// in type and lifetime inference.
72-
// See the comment at the bottom of `LoweringContext::make_async_expr` and
73-
// <https://github.com/rust-lang/rust/issues/104826>.
7470
#[doc(hidden)]
7571
#[unstable(feature = "gen_future", issue = "50547")]
7672
#[inline]
77-
#[lang = "identity_future"]
73+
#[cfg_attr(bootstrap, lang = "identity_future")]
7874
pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
7975
f
8076
}

src/tools/clippy/clippy_lints/src/manual_async_fn.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2-
use clippy_utils::match_function_call_with_def_id;
32
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
43
use if_chain::if_chain;
54
use rustc_errors::Applicability;
@@ -175,16 +174,10 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
175174
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
176175
if_chain! {
177176
if let Some(block_expr) = block.expr;
178-
if let Some(args) = cx
179-
.tcx
180-
.lang_items()
181-
.identity_future_fn()
182-
.and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
183-
if args.len() == 1;
184177
if let Expr {
185178
kind: ExprKind::Closure(&Closure { body, .. }),
186179
..
187-
} = args[0];
180+
} = block_expr;
188181
let closure_body = cx.tcx.hir().body(body);
189182
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
190183
then {

src/tools/clippy/clippy_utils/src/lib.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -1904,16 +1904,7 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool {
19041904

19051905
/// Peels away all the compiler generated code surrounding the body of an async function,
19061906
pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
1907-
if let ExprKind::Call(
1908-
_,
1909-
&[
1910-
Expr {
1911-
kind: ExprKind::Closure(&Closure { body, .. }),
1912-
..
1913-
},
1914-
],
1915-
) = body.value.kind
1916-
{
1907+
if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind {
19171908
if let ExprKind::Block(
19181909
Block {
19191910
stmts: [],

src/tools/clippy/tests/ui/author/blocks.stdout

+1-5
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,7 @@ if let ExprKind::Block(block, None) = expr.kind
4343
if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind
4444
&& let FnRetTy::DefaultReturn(_) = fn_decl.output
4545
&& expr1 = &cx.tcx.hir().body(body_id).value
46-
&& let ExprKind::Call(func, args) = expr1.kind
47-
&& let ExprKind::Path(ref qpath) = func.kind
48-
&& matches!(qpath, QPath::LangItem(LangItem::IdentityFuture, _))
49-
&& args.len() == 1
50-
&& let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
46+
&& let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind
5147
&& let FnRetTy::DefaultReturn(_) = fn_decl1.output
5248
&& expr2 = &cx.tcx.hir().body(body_id1).value
5349
&& let ExprKind::Block(block, None) = expr2.kind

tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
_0: GeneratorSavedTy {
55
ty: impl std::future::Future<Output = ()>,
66
source_info: SourceInfo {
7-
span: $DIR/async_await.rs:15:8: 15:14 (#9),
7+
span: $DIR/async_await.rs:15:8: 15:14 (#8),
88
scope: scope[0],
99
},
1010
ignore_for_traits: false,
1111
},
1212
_1: GeneratorSavedTy {
1313
ty: impl std::future::Future<Output = ()>,
1414
source_info: SourceInfo {
15-
span: $DIR/async_await.rs:16:8: 16:14 (#12),
15+
span: $DIR/async_await.rs:16:8: 16:14 (#11),
1616
scope: scope[0],
1717
},
1818
ignore_for_traits: false,

tests/ui/async-await/generator-desc.stderr

+8-6
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ error[E0308]: mismatched types
22
--> $DIR/generator-desc.rs:10:19
33
|
44
LL | fun(async {}, async {});
5-
| -------- ^^^^^^^^
6-
| | |
7-
| | expected `async` block, found a different `async` block
8-
| | arguments to this function are incorrect
9-
| the expected `async` block
5+
| --- -------- ^^^^^^^^ expected `async` block, found a different `async` block
6+
| | |
7+
| | the expected `async` block
8+
| arguments to this function are incorrect
109
|
1110
= note: expected `async` block `[async block@$DIR/generator-desc.rs:10:9: 10:17]`
1211
found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
1312
note: function defined here
14-
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
13+
--> $DIR/generator-desc.rs:8:4
14+
|
15+
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
16+
| ^^^ -----
1517

1618
error[E0308]: mismatched types
1719
--> $DIR/generator-desc.rs:12:16
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
error: moving 10024 bytes
2-
--> $DIR/large_moves.rs:13:13
2+
--> $DIR/large_moves.rs:19:14
33
|
4-
LL | let x = async {
5-
| _____________^
6-
LL | | let y = [0; 9999];
7-
LL | | dbg!(y);
8-
LL | | thing(&y).await;
9-
LL | | dbg!(y);
10-
LL | | };
11-
| |_____^ value moved from here
4+
LL | let z = (x, 42);
5+
| ^ value moved from here
126
|
137
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
148
note: the lint level is defined here
@@ -17,14 +11,6 @@ note: the lint level is defined here
1711
LL | #![deny(large_assignments)]
1812
| ^^^^^^^^^^^^^^^^^
1913

20-
error: moving 10024 bytes
21-
--> $DIR/large_moves.rs:19:14
22-
|
23-
LL | let z = (x, 42);
24-
| ^ value moved from here
25-
|
26-
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
27-
2814
error: moving 10024 bytes
2915
--> $DIR/large_moves.rs:19:13
3016
|
@@ -41,5 +27,5 @@ LL | let a = z.0;
4127
|
4228
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
4329

44-
error: aborting due to 4 previous errors
30+
error: aborting due to 3 previous errors
4531

0 commit comments

Comments
 (0)