Skip to content

Commit

Permalink
don't record all intermediate adjustment types
Browse files Browse the repository at this point in the history
That's way more than is needed, and winds up recording types
that will never appear in MIR.
  • Loading branch information
nikomatsakis committed Sep 18, 2019
1 parent dece573 commit d95a776
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
33 changes: 27 additions & 6 deletions src/librustc_typeck/check/generator_interior.rs
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.)
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);
}
}
}
20 changes: 20 additions & 0 deletions src/test/ui/async-await/issues/issue-64477.rs
@@ -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() { }

0 comments on commit d95a776

Please sign in to comment.