Skip to content

Commit d95a776

Browse files
committed
don't record all intermediate adjustment types
That's way more than is needed, and winds up recording types that will never appear in MIR.
1 parent dece573 commit d95a776

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

src/librustc_typeck/check/generator_interior.rs

+27-6
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,34 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
181181

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

184-
// Record the unadjusted type
184+
// If there are adjustments, then record the final type --
185+
// this is the actual value that is being produced.
186+
if let Some(adjusted_ty) = self.fcx.tables.borrow().expr_ty_adjusted_opt(expr) {
187+
self.record(adjusted_ty, scope, Some(expr), expr.span);
188+
}
189+
190+
// Also record the unadjusted type (which is the only type if
191+
// there are no adjustments). The reason for this is that the
192+
// unadjusted value is sometimes a "temporary" that would wind
193+
// up in a MIR temporary.
194+
//
195+
// As an example, consider an expression like `vec![].push()`.
196+
// Here, the `vec![]` would wind up MIR stored into a
197+
// temporary variable `t` which we can borrow to invoke
198+
// `<Vec<_>>::push(&mut t)`.
199+
//
200+
// Note that an expression can have many adjustments, and we
201+
// are just ignoring those intermediate types. This is because
202+
// those intermediate values are always linearly "consumed" by
203+
// the other adjustments, and hence would never be directly
204+
// captured in the MIR.
205+
//
206+
// (Note that this partly relies on the fact that the `Deref`
207+
// traits always return references, which means their content
208+
// can be reborrowed without needing to spill to a temporary.
209+
// If this were not the case, then we could conceivably have
210+
// to create intermediate temporaries.)
185211
let ty = self.fcx.tables.borrow().expr_ty(expr);
186212
self.record(ty, scope, Some(expr), expr.span);
187-
188-
// Also include the adjusted types, since these can result in MIR locals
189-
for adjustment in self.fcx.tables.borrow().expr_adjustments(expr) {
190-
self.record(adjustment.target, scope, Some(expr), expr.span);
191-
}
192213
}
193214
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Regression test for #64477.
2+
//
3+
// We were incorrectly claiming that the `f(x).await` future captured
4+
// a value of type `T`, and hence that `T: Send` would have to hold.
5+
//
6+
// check-pass
7+
// edition:2018
8+
9+
use std::future::Future;
10+
use std::pin::Pin;
11+
12+
fn f<T>(_: &T) -> Pin<Box<dyn Future<Output = ()> + Send>> {
13+
unimplemented!()
14+
}
15+
16+
pub fn g<T: Sync>(x: &'static T) -> impl Future<Output = ()> + Send {
17+
async move { f(x).await }
18+
}
19+
20+
fn main() { }

0 commit comments

Comments
 (0)