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

record fewer adjustment types in generator witnesses, avoid spurious drops in MIR construction #64584

Merged
33 changes: 27 additions & 6 deletions src/librustc_typeck/check/generator_interior.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,34 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {

let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);

// Record the unadjusted type
// If there are adjustments, then record the final type --
// this is the actual value that is being produced.
if let Some(adjusted_ty) = self.fcx.tables.borrow().expr_ty_adjusted_opt(expr) {
self.record(adjusted_ty, scope, Some(expr), expr.span);
}

// Also record the unadjusted type (which is the only type if
// there are no adjustments). The reason for this is that the
// unadjusted value is sometimes a "temporary" that would wind
// up in a MIR temporary.
//
// As an example, consider an expression like `vec![].push()`.
// Here, the `vec![]` would wind up MIR stored into a
// temporary variable `t` which we can borrow to invoke
// `<Vec<_>>::push(&mut t)`.
//
// Note that an expression can have many adjustments, and we
// are just ignoring those intermediate types. This is because
// those intermediate values are always linearly "consumed" by
// the other adjustments, and hence would never be directly
// captured in the MIR.
//
// (Note that this partly relies on the fact that the `Deref`
// traits always return references, which means their content
// can be reborrowed without needing to spill to a temporary.
// If this were not the case, then we could conceivably have
// to create intermediate temporaries.)
Copy link
Contributor

Choose a reason for hiding this comment

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

I ❤️ these comments!

let ty = self.fcx.tables.borrow().expr_ty(expr);
self.record(ty, scope, Some(expr), expr.span);

// Also include the adjusted types, since these can result in MIR locals
for adjustment in self.fcx.tables.borrow().expr_adjustments(expr) {
self.record(adjustment.target, scope, Some(expr), expr.span);
}
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
}
}
20 changes: 20 additions & 0 deletions src/test/ui/async-await/issues/issue-64477.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Regression test for #64477.
//
// We were incorrectly claiming that the `f(x).await` future captured
// a value of type `T`, and hence that `T: Send` would have to hold.
//
// check-pass
// edition:2018

use std::future::Future;
use std::pin::Pin;

fn f<T>(_: &T) -> Pin<Box<dyn Future<Output = ()> + Send>> {
unimplemented!()
}

pub fn g<T: Sync>(x: &'static T) -> impl Future<Output = ()> + Send {
async move { f(x).await }
}

fn main() { }