Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove identity_future indirection #104833

Merged
merged 1 commit into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 27 additions & 37 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
ensure_sufficient_stack(|| {
match &e.kind {
// Paranthesis expression does not have a HirId and is handled specially.
// Parenthesis expression does not have a HirId and is handled specially.
ExprKind::Paren(ex) => {
let mut ex = self.lower_expr_mut(ex);
// Include parens in span, but only if it is a super-span.
Expand Down Expand Up @@ -63,6 +63,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::ForLoop(pat, head, body, opt_label) => {
return self.lower_expr_for(e, pat, head, body, *opt_label);
}
// Similarly, async blocks do not use `e.id` but rather `closure_node_id`.
ExprKind::Async(capture_clause, closure_node_id, block) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just remove the closure_node_id from the AST, and keep the previous logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried that here: Swatinem@f62aa02
But I was struggling with some HIR errors related to that. I might revisit that idea at some point.

let hir_id = self.lower_node_id(*closure_node_id);
self.lower_attrs(hir_id, &e.attrs);
return self.make_async_expr(
*capture_clause,
hir_id,
*closure_node_id,
None,
e.span,
hir::AsyncGeneratorKind::Block,
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
);
}
_ => (),
}

Expand Down Expand Up @@ -182,15 +196,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
hir::MatchSource::Normal,
),
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
*capture_clause,
hir_id,
*closure_node_id,
None,
e.span,
hir::AsyncGeneratorKind::Block,
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
),
ExprKind::Await(expr) => {
let dot_await_span = if expr.span.hi() < e.span.hi() {
let span_with_whitespace = self
Expand Down Expand Up @@ -324,7 +329,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
),
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),

ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
ExprKind::Paren(_) | ExprKind::ForLoop(..) | ExprKind::Async(..) => {
unreachable!("already handled")
}

ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
};
Expand Down Expand Up @@ -586,9 +593,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// This results in:
///
/// ```text
/// std::future::identity_future(static move? |_task_context| -> <ret_ty> {
/// static move? |_task_context| -> <ret_ty> {
/// <body>
/// })
/// }
/// ```
pub(super) fn make_async_expr(
&mut self,
Expand All @@ -599,7 +606,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span,
async_gen_kind: hir::AsyncGeneratorKind,
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
) -> hir::ExprKind<'hir> {
) -> hir::Expr<'hir> {
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));

// Resume argument type: `ResumeTy`
Expand Down Expand Up @@ -664,13 +671,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
};

let hir_id = self.lower_node_id(closure_node_id);
let unstable_span =
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());

if self.tcx.features().closure_track_caller
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
{
let unstable_span =
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
self.lower_attrs(
hir_id,
&[Attribute {
Expand All @@ -689,22 +695,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
}

let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };

// FIXME(swatinem):
// For some reason, the async block needs to flow through *any*
// call (like the identity function), as otherwise type and lifetime
// inference have a hard time figuring things out.
// Without this, we would get:
// E0720 in tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
// E0700 in tests/ui/self/self_lifetime-async.rs

// `future::identity_future`:
let identity_future =
self.expr_lang_item_path(unstable_span, hir::LangItem::IdentityFuture, None);

// `future::identity_future(generator)`:
hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) }
}

/// Desugar `<expr>.await` into:
Expand Down Expand Up @@ -1010,7 +1001,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}

// Transform `async |x: u8| -> X { ... }` into
// `|x: u8| identity_future(|| -> X { ... })`.
// `|x: u8| || -> X { ... }`.
let body_id = this.lower_fn_body(&outer_decl, |this| {
let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
Expand All @@ -1019,16 +1010,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
None
};

let async_body = this.make_async_expr(
this.make_async_expr(
capture_clause,
closure_hir_id,
inner_closure_id,
async_ret_ty,
body.span,
hir::AsyncGeneratorKind::Closure,
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
);
this.expr(fn_decl_span, async_body)
)
});
body_id
});
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
},
);

(this.arena.alloc_from_iter(parameters), this.expr(body.span, async_expr))
(this.arena.alloc_from_iter(parameters), async_expr)
})
}

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ language_item_table! {
// FIXME(swatinem): the following lang items are used for async lowering and
// should become obsolete eventually.
ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;

Context, sym::Context, context, Target::Struct, GenericRequirement::None;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let fn_decl_span = if hir.body(body).generator_kind
== Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure))
{
// Actually need to unwrap a few more layers of HIR to get to
// Actually need to unwrap one more layer of HIR to get to
// the _real_ closure...
let async_closure = hir.parent_id(hir.parent_id(parent_hir_id));
let async_closure = hir.parent_id(parent_hir_id);
if let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
..
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -928,12 +928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir_id,
kind: hir::ExprKind::Closure(..),
..
}) if let Some(Node::Expr(&hir::Expr {
hir_id,
kind: hir::ExprKind::Call(..),
..
})) = self.tcx.hir().find_parent(hir_id) &&
let Some(Node::Item(&hir::Item {
}) if let Some(Node::Item(&hir::Item {
ident,
kind: hir::ItemKind::Fn(ref sig, ..),
..
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,6 @@ symbols! {
i64,
i8,
ident,
identity_future,
if_let,
if_let_guard,
if_while_or_patterns,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3025,8 +3025,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
};

let identity_future = tcx.require_lang_item(LangItem::IdentityFuture, None);

// Don't print the tuple of capture types
'print: {
if !is_upvar_tys_infer_tuple {
Expand All @@ -3039,12 +3037,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
None => err.note(&msg),
},
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
// Avoid printing the future from `core::future::identity_future`, it's not helpful
if tcx.parent(*def_id) == identity_future {
break 'print;
}

// If the previous type is `identity_future`, this is the future generated by the body of an async function.
// If the previous type is async fn, this is the future generated by the body of an async function.
// Avoid printing it twice (it was already printed in the `ty::Generator` arm below).
let is_future = tcx.ty_is_opaque_future(ty);
debug!(
Expand Down
6 changes: 1 addition & 5 deletions library/core/src/future/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
unsafe { &mut *cx.0.as_ptr().cast() }
}

// FIXME(swatinem): This fn is currently needed to work around shortcomings
// in type and lifetime inference.
// See the comment at the bottom of `LoweringContext::make_async_expr` and
// <https://github.com/rust-lang/rust/issues/104826>.
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[inline]
#[lang = "identity_future"]
#[cfg_attr(bootstrap, lang = "identity_future")]
pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
f
}
9 changes: 1 addition & 8 deletions src/tools/clippy/clippy_lints/src/manual_async_fn.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::match_function_call_with_def_id;
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
use if_chain::if_chain;
use rustc_errors::Applicability;
Expand Down Expand Up @@ -175,16 +174,10 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
if_chain! {
if let Some(block_expr) = block.expr;
if let Some(args) = cx
.tcx
.lang_items()
.identity_future_fn()
.and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
if args.len() == 1;
if let Expr {
kind: ExprKind::Closure(&Closure { body, .. }),
..
} = args[0];
} = block_expr;
let closure_body = cx.tcx.hir().body(body);
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
then {
Expand Down
11 changes: 1 addition & 10 deletions src/tools/clippy/clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1904,16 +1904,7 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool {

/// Peels away all the compiler generated code surrounding the body of an async function,
pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
if let ExprKind::Call(
_,
&[
Expr {
kind: ExprKind::Closure(&Closure { body, .. }),
..
},
],
) = body.value.kind
{
if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind {
if let ExprKind::Block(
Block {
stmts: [],
Expand Down
6 changes: 1 addition & 5 deletions src/tools/clippy/tests/ui/author/blocks.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ if let ExprKind::Block(block, None) = expr.kind
if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind
&& let FnRetTy::DefaultReturn(_) = fn_decl.output
&& expr1 = &cx.tcx.hir().body(body_id).value
&& let ExprKind::Call(func, args) = expr1.kind
&& let ExprKind::Path(ref qpath) = func.kind
&& matches!(qpath, QPath::LangItem(LangItem::IdentityFuture, _))
&& args.len() == 1
&& let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
&& let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind
&& let FnRetTy::DefaultReturn(_) = fn_decl1.output
&& expr2 = &cx.tcx.hir().body(body_id1).value
&& let ExprKind::Block(block, None) = expr2.kind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
_0: GeneratorSavedTy {
ty: impl std::future::Future<Output = ()>,
source_info: SourceInfo {
span: $DIR/async_await.rs:15:8: 15:14 (#9),
span: $DIR/async_await.rs:15:8: 15:14 (#8),
scope: scope[0],
},
ignore_for_traits: false,
},
_1: GeneratorSavedTy {
ty: impl std::future::Future<Output = ()>,
source_info: SourceInfo {
span: $DIR/async_await.rs:16:8: 16:14 (#12),
span: $DIR/async_await.rs:16:8: 16:14 (#11),
scope: scope[0],
},
ignore_for_traits: false,
Expand Down
14 changes: 8 additions & 6 deletions tests/ui/async-await/generator-desc.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ error[E0308]: mismatched types
--> $DIR/generator-desc.rs:10:19
|
LL | fun(async {}, async {});
| -------- ^^^^^^^^
| | |
| | expected `async` block, found a different `async` block
| | arguments to this function are incorrect
| the expected `async` block
| --- -------- ^^^^^^^^ expected `async` block, found a different `async` block
| | |
| | the expected `async` block
| arguments to this function are incorrect
|
= note: expected `async` block `[async block@$DIR/generator-desc.rs:10:9: 10:17]`
found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
note: function defined here
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
--> $DIR/generator-desc.rs:8:4
|
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
| ^^^ -----

error[E0308]: mismatched types
--> $DIR/generator-desc.rs:12:16
Expand Down
22 changes: 4 additions & 18 deletions tests/ui/async-await/large_moves.attribute.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
error: moving 10024 bytes
--> $DIR/large_moves.rs:13:13
--> $DIR/large_moves.rs:19:14
|
LL | let x = async {
| _____________^
LL | | let y = [0; 9999];
LL | | dbg!(y);
LL | | thing(&y).await;
LL | | dbg!(y);
LL | | };
| |_____^ value moved from here
LL | let z = (x, 42);
| ^ value moved from here
|
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
note: the lint level is defined here
Expand All @@ -17,14 +11,6 @@ note: the lint level is defined here
LL | #![deny(large_assignments)]
| ^^^^^^^^^^^^^^^^^

error: moving 10024 bytes
--> $DIR/large_moves.rs:19:14
|
LL | let z = (x, 42);
| ^ value moved from here
|
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`

error: moving 10024 bytes
--> $DIR/large_moves.rs:19:13
|
Expand All @@ -41,5 +27,5 @@ LL | let a = z.0;
|
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

Loading