mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 10:45:18 +00:00
Rollup merge of #68212 - csmoe:temp, r=estebank
Suggest to shorten temporary lifetime during method call inside generator Closes https://github.com/rust-lang/rust/issues/67376 ![image](https://user-images.githubusercontent.com/35686186/72364752-f6b1e400-3731-11ea-8ec9-8297ba4c6c77.png) r? @estebank cc @tmandry @nikomatsakis
This commit is contained in:
commit
ae1e75bf4e
@ -2479,19 +2479,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
eq
|
eq
|
||||||
})
|
})
|
||||||
.map(|ty::GeneratorInteriorTypeCause { span, scope_span, .. }| {
|
.map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
|
||||||
(span, source_map.span_to_snippet(*span), scope_span)
|
(span, source_map.span_to_snippet(*span), scope_span, expr)
|
||||||
});
|
});
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"maybe_note_obligation_cause_for_async_await: target_ty={:?} \
|
"maybe_note_obligation_cause_for_async_await: target_ty={:?} \
|
||||||
generator_interior_types={:?} target_span={:?}",
|
generator_interior_types={:?} target_span={:?}",
|
||||||
target_ty, tables.generator_interior_types, target_span
|
target_ty, tables.generator_interior_types, target_span
|
||||||
);
|
);
|
||||||
if let Some((target_span, Ok(snippet), scope_span)) = target_span {
|
if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
|
||||||
self.note_obligation_cause_for_async_await(
|
self.note_obligation_cause_for_async_await(
|
||||||
err,
|
err,
|
||||||
*target_span,
|
*target_span,
|
||||||
scope_span,
|
scope_span,
|
||||||
|
*expr,
|
||||||
snippet,
|
snippet,
|
||||||
generator_did,
|
generator_did,
|
||||||
last_generator,
|
last_generator,
|
||||||
@ -2514,6 +2516,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
target_span: Span,
|
target_span: Span,
|
||||||
scope_span: &Option<Span>,
|
scope_span: &Option<Span>,
|
||||||
|
expr: Option<hir::HirId>,
|
||||||
snippet: String,
|
snippet: String,
|
||||||
first_generator: DefId,
|
first_generator: DefId,
|
||||||
last_generator: Option<DefId>,
|
last_generator: Option<DefId>,
|
||||||
@ -2549,6 +2552,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
// not implemented.
|
// not implemented.
|
||||||
let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
|
let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
|
||||||
let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
|
let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
|
||||||
|
let hir = self.tcx.hir();
|
||||||
let trait_explanation = if is_send || is_sync {
|
let trait_explanation = if is_send || is_sync {
|
||||||
let (trait_name, trait_verb) =
|
let (trait_name, trait_verb) =
|
||||||
if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
|
if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
|
||||||
@ -2564,8 +2568,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
let message = if let Some(name) = last_generator
|
let message = if let Some(name) = last_generator
|
||||||
.and_then(|generator_did| self.tcx.parent(generator_did))
|
.and_then(|generator_did| self.tcx.parent(generator_did))
|
||||||
.and_then(|parent_did| self.tcx.hir().as_local_hir_id(parent_did))
|
.and_then(|parent_did| hir.as_local_hir_id(parent_did))
|
||||||
.and_then(|parent_hir_id| self.tcx.hir().opt_name(parent_hir_id))
|
.and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
|
||||||
{
|
{
|
||||||
format!("future returned by `{}` is not {}", name, trait_name)
|
format!("future returned by `{}` is not {}", name, trait_name)
|
||||||
} else {
|
} else {
|
||||||
@ -2581,7 +2585,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Look at the last interior type to get a span for the `.await`.
|
// Look at the last interior type to get a span for the `.await`.
|
||||||
let await_span = tables.generator_interior_types.iter().map(|i| i.span).last().unwrap();
|
let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
|
||||||
let mut span = MultiSpan::from_span(await_span);
|
let mut span = MultiSpan::from_span(await_span);
|
||||||
span.push_span_label(
|
span.push_span_label(
|
||||||
await_span,
|
await_span,
|
||||||
@ -2606,6 +2610,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if let Some(expr_id) = expr {
|
||||||
|
let expr = hir.expect_expr(expr_id);
|
||||||
|
let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
|
||||||
|
let parent = hir.get_parent_node(expr_id);
|
||||||
|
if let Some(hir::Node::Expr(e)) = hir.find(parent) {
|
||||||
|
let method_span = hir.span(parent);
|
||||||
|
if tables.is_method_call(e) && is_ref {
|
||||||
|
err.span_help(
|
||||||
|
method_span,
|
||||||
|
"consider moving this method call into a `let` \
|
||||||
|
binding to create a shorter lived borrow",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add a note for the item obligation that remains - normally a note pointing to the
|
// Add a note for the item obligation that remains - normally a note pointing to the
|
||||||
// bound that introduced the obligation (e.g. `T: Send`).
|
// bound that introduced the obligation (e.g. `T: Send`).
|
||||||
debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
|
debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
|
||||||
|
@ -81,6 +81,15 @@ pub struct Adjustment<'tcx> {
|
|||||||
pub target: Ty<'tcx>,
|
pub target: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Adjustment<'tcx> {
|
||||||
|
pub fn is_region_borrow(&self) -> bool {
|
||||||
|
match self.kind {
|
||||||
|
Adjust::Borrow(AutoBorrow::Ref(..)) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
|
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
|
||||||
pub enum Adjust<'tcx> {
|
pub enum Adjust<'tcx> {
|
||||||
/// Go from ! to any type.
|
/// Go from ! to any type.
|
||||||
|
@ -315,8 +315,7 @@ pub struct ResolvedOpaqueTy<'tcx> {
|
|||||||
///
|
///
|
||||||
/// Here, we would store the type `T`, the span of the value `x`, and the "scope-span" for
|
/// Here, we would store the type `T`, the span of the value `x`, and the "scope-span" for
|
||||||
/// the scope that contains `x`.
|
/// the scope that contains `x`.
|
||||||
#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
|
||||||
#[derive(HashStable, TypeFoldable)]
|
|
||||||
pub struct GeneratorInteriorTypeCause<'tcx> {
|
pub struct GeneratorInteriorTypeCause<'tcx> {
|
||||||
/// Type of the captured binding.
|
/// Type of the captured binding.
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
@ -324,6 +323,8 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// Span of the scope of the captured binding.
|
/// Span of the scope of the captured binding.
|
||||||
pub scope_span: Option<Span>,
|
pub scope_span: Option<Span>,
|
||||||
|
/// Expr which the type evaluated from.
|
||||||
|
pub expr: Option<hir::HirId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable, Debug)]
|
#[derive(RustcEncodable, RustcDecodable, Debug)]
|
||||||
@ -436,7 +437,7 @@ pub struct TypeckTables<'tcx> {
|
|||||||
/// entire variable.
|
/// entire variable.
|
||||||
pub upvar_list: ty::UpvarListMap,
|
pub upvar_list: ty::UpvarListMap,
|
||||||
|
|
||||||
/// Stores the type, span and optional scope span of all types
|
/// Stores the type, expression, span and optional scope span of all types
|
||||||
/// that are live across the yield of this generator (if a generator).
|
/// that are live across the yield of this generator (if a generator).
|
||||||
pub generator_interior_types: Vec<GeneratorInteriorTypeCause<'tcx>>,
|
pub generator_interior_types: Vec<GeneratorInteriorTypeCause<'tcx>>,
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
|||||||
span: source_span,
|
span: source_span,
|
||||||
ty: &ty,
|
ty: &ty,
|
||||||
scope_span,
|
scope_span,
|
||||||
|
expr: expr.map(|e| e.hir_id),
|
||||||
})
|
})
|
||||||
.or_insert(entries);
|
.or_insert(entries);
|
||||||
}
|
}
|
||||||
@ -164,17 +165,25 @@ pub fn resolve_interior<'a, 'tcx>(
|
|||||||
// which means that none of the regions inside relate to any other, even if
|
// which means that none of the regions inside relate to any other, even if
|
||||||
// typeck had previously found constraints that would cause them to be related.
|
// typeck had previously found constraints that would cause them to be related.
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
let types = fcx.tcx.fold_regions(&types, &mut false, |_, current_depth| {
|
let fold_types: Vec<_> = types.iter().map(|(t, _)| t.ty).collect();
|
||||||
|
let folded_types = fcx.tcx.fold_regions(&fold_types, &mut false, |_, current_depth| {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter)))
|
fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter)))
|
||||||
});
|
});
|
||||||
|
|
||||||
// Store the generator types and spans into the tables for this generator.
|
// Store the generator types and spans into the tables for this generator.
|
||||||
let interior_types = types.iter().map(|t| t.0.clone()).collect::<Vec<_>>();
|
let types = types
|
||||||
visitor.fcx.inh.tables.borrow_mut().generator_interior_types = interior_types;
|
.into_iter()
|
||||||
|
.zip(&folded_types)
|
||||||
|
.map(|((mut interior_cause, _), ty)| {
|
||||||
|
interior_cause.ty = ty;
|
||||||
|
interior_cause
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
visitor.fcx.inh.tables.borrow_mut().generator_interior_types = types;
|
||||||
|
|
||||||
// Extract type components
|
// Extract type components
|
||||||
let type_list = fcx.tcx.mk_type_list(types.into_iter().map(|t| (t.0).ty));
|
let type_list = fcx.tcx.mk_type_list(folded_types.iter());
|
||||||
|
|
||||||
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
|
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
|
||||||
|
|
||||||
|
@ -16,6 +16,11 @@ LL | let _x = get().await;
|
|||||||
...
|
...
|
||||||
LL | }
|
LL | }
|
||||||
| - `client` is later dropped here
|
| - `client` is later dropped here
|
||||||
|
help: consider moving this method call into a `let` binding to create a shorter lived borrow
|
||||||
|
--> $DIR/issue-64130-4-async-move.rs:19:15
|
||||||
|
|
|
||||||
|
LL | match client.status() {
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
= note: the return type of a function must have a statically known size
|
= note: the return type of a function must have a statically known size
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
@ -20,7 +20,7 @@ LL | fn assert_sync<T: Sync>(_: T) {}
|
|||||||
LL | assert_sync(|| {
|
LL | assert_sync(|| {
|
||||||
| ^^^^^^^^^^^ future returned by `main` is not `Sync`
|
| ^^^^^^^^^^^ future returned by `main` is not `Sync`
|
||||||
|
|
|
|
||||||
= help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
|
= help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, (), ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
|
||||||
note: future is not `Sync` as this value is used across an yield
|
note: future is not `Sync` as this value is used across an yield
|
||||||
--> $DIR/not-send-sync.rs:12:9
|
--> $DIR/not-send-sync.rs:12:9
|
||||||
|
|
|
|
||||||
|
@ -76,7 +76,7 @@ error[E0720]: opaque type expands to a recursive type
|
|||||||
LL | fn generator_capture() -> impl Sized {
|
LL | fn generator_capture() -> impl Sized {
|
||||||
| ^^^^^^^^^^ expands to a recursive type
|
| ^^^^^^^^^^ expands to a recursive type
|
||||||
|
|
|
|
||||||
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {()}]`
|
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {(), ()}]`
|
||||||
|
|
||||||
error[E0720]: opaque type expands to a recursive type
|
error[E0720]: opaque type expands to a recursive type
|
||||||
--> $DIR/recursive-impl-trait-type-indirect.rs:53:26
|
--> $DIR/recursive-impl-trait-type-indirect.rs:53:26
|
||||||
@ -92,7 +92,7 @@ error[E0720]: opaque type expands to a recursive type
|
|||||||
LL | fn generator_hold() -> impl Sized {
|
LL | fn generator_hold() -> impl Sized {
|
||||||
| ^^^^^^^^^^ expands to a recursive type
|
| ^^^^^^^^^^ expands to a recursive type
|
||||||
|
|
|
|
||||||
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, ()}]`
|
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, (), ()}]`
|
||||||
|
|
||||||
error[E0720]: opaque type expands to a recursive type
|
error[E0720]: opaque type expands to a recursive type
|
||||||
--> $DIR/recursive-impl-trait-type-indirect.rs:69:26
|
--> $DIR/recursive-impl-trait-type-indirect.rs:69:26
|
||||||
|
Loading…
Reference in New Issue
Block a user