Rollup merge of #65277 - csmoe:fix-move, r=estebank
Query generator kind for error reporting Fixes https://github.com/rust-lang/rust/pull/65166#discussion_r333114545 r? @estebank cc @cramertj
This commit is contained in:
commit
60482be070
4 changed files with 55 additions and 26 deletions
|
@ -1366,6 +1366,10 @@ impl Body {
|
|||
hir_id: self.value.hir_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generator_kind(&self) -> Option<GeneratorKind> {
|
||||
self.generator_kind
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of source expression that caused this generator to be created.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::{AsyncGeneratorKind, GeneratorKind};
|
||||
use rustc::mir::{
|
||||
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local,
|
||||
LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue,
|
||||
|
@ -788,7 +789,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
..
|
||||
},
|
||||
) if borrow_spans.for_closure() => self.report_escaping_closure_capture(
|
||||
borrow_spans.args_or_use(),
|
||||
borrow_spans,
|
||||
borrow_span,
|
||||
region_name,
|
||||
category,
|
||||
|
@ -806,7 +807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
},
|
||||
|
||||
) if borrow_spans.for_generator() => self.report_escaping_closure_capture(
|
||||
borrow_spans.args_or_use(),
|
||||
borrow_spans,
|
||||
borrow_span,
|
||||
region_name,
|
||||
category,
|
||||
|
@ -1195,7 +1196,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
fn report_escaping_closure_capture(
|
||||
&mut self,
|
||||
args_span: Span,
|
||||
use_span: UseSpans,
|
||||
var_span: Span,
|
||||
fr_name: &RegionName,
|
||||
category: ConstraintCategory,
|
||||
|
@ -1203,7 +1204,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
captured_var: &str,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let args_span = use_span.args_or_use();
|
||||
let mut err = self.cannot_capture_in_long_lived_closure(
|
||||
args_span,
|
||||
captured_var,
|
||||
|
@ -1223,12 +1224,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
},
|
||||
Err(_) => "move |<args>| <body>".to_string()
|
||||
};
|
||||
|
||||
let kind = match use_span.generator_kind() {
|
||||
Some(generator_kind) => match generator_kind {
|
||||
GeneratorKind::Async(async_kind) => match async_kind {
|
||||
AsyncGeneratorKind::Block => "async block",
|
||||
AsyncGeneratorKind::Closure => "async closure",
|
||||
_ => bug!("async block/closure expected, but async funtion found."),
|
||||
},
|
||||
GeneratorKind::Gen => "generator",
|
||||
}
|
||||
None => "closure",
|
||||
};
|
||||
err.span_suggestion(
|
||||
args_span,
|
||||
&format!("to force the closure to take ownership of {} (and any \
|
||||
&format!(
|
||||
"to force the {} to take ownership of {} (and any \
|
||||
other referenced variables), use the `move` keyword",
|
||||
captured_var),
|
||||
kind,
|
||||
captured_var
|
||||
),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use rustc::hir;
|
||||
use rustc::hir::def::Namespace;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::GeneratorKind;
|
||||
use rustc::mir::{
|
||||
AggregateKind, Constant, Field, Local, LocalKind, Location, Operand,
|
||||
Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind,
|
||||
|
@ -14,7 +15,7 @@ use syntax_pos::Span;
|
|||
use syntax::symbol::sym;
|
||||
|
||||
use super::borrow_set::BorrowData;
|
||||
use super::{MirBorrowckCtxt};
|
||||
use super::MirBorrowckCtxt;
|
||||
use crate::dataflow::move_paths::{InitLocation, LookupResult};
|
||||
|
||||
pub(super) struct IncludingDowncast(pub(super) bool);
|
||||
|
@ -604,7 +605,7 @@ pub(super) enum UseSpans {
|
|||
// The access is caused by capturing a variable for a closure.
|
||||
ClosureUse {
|
||||
// This is true if the captured variable was from a generator.
|
||||
is_generator: bool,
|
||||
generator_kind: Option<GeneratorKind>,
|
||||
// The span of the args of the closure, including the `move` keyword if
|
||||
// it's present.
|
||||
args_span: Span,
|
||||
|
@ -631,6 +632,13 @@ impl UseSpans {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn generator_kind(self) -> Option<GeneratorKind> {
|
||||
match self {
|
||||
UseSpans::ClosureUse { generator_kind, .. } => generator_kind,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Add a span label to the arguments of the closure, if it exists.
|
||||
pub(super) fn args_span_label(
|
||||
self,
|
||||
|
@ -656,7 +664,7 @@ impl UseSpans {
|
|||
/// Returns `false` if this place is not used in a closure.
|
||||
pub(super) fn for_closure(&self) -> bool {
|
||||
match *self {
|
||||
UseSpans::ClosureUse { is_generator, .. } => !is_generator,
|
||||
UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_none(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -664,7 +672,7 @@ impl UseSpans {
|
|||
/// Returns `false` if this place is not used in a generator.
|
||||
pub(super) fn for_generator(&self) -> bool {
|
||||
match *self {
|
||||
UseSpans::ClosureUse { is_generator, .. } => is_generator,
|
||||
UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_some(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -672,7 +680,7 @@ impl UseSpans {
|
|||
/// Describe the span associated with a use of a place.
|
||||
pub(super) fn describe(&self) -> String {
|
||||
match *self {
|
||||
UseSpans::ClosureUse { is_generator, .. } => if is_generator {
|
||||
UseSpans::ClosureUse { generator_kind, .. } => if generator_kind.is_some() {
|
||||
" in generator".to_string()
|
||||
} else {
|
||||
" in closure".to_string()
|
||||
|
@ -794,19 +802,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if let StatementKind::Assign(
|
||||
box(_, Rvalue::Aggregate(ref kind, ref places))
|
||||
) = stmt.kind {
|
||||
let (def_id, is_generator) = match kind {
|
||||
box AggregateKind::Closure(def_id, _) => (def_id, false),
|
||||
box AggregateKind::Generator(def_id, _, _) => (def_id, true),
|
||||
let def_id = match kind {
|
||||
box AggregateKind::Closure(def_id, _)
|
||||
| box AggregateKind::Generator(def_id, _, _) => def_id,
|
||||
_ => return OtherUse(stmt.source_info.span),
|
||||
};
|
||||
|
||||
debug!(
|
||||
"move_spans: def_id={:?} is_generator={:?} places={:?}",
|
||||
def_id, is_generator, places
|
||||
"move_spans: def_id={:?} places={:?}",
|
||||
def_id, places
|
||||
);
|
||||
if let Some((args_span, var_span)) = self.closure_span(*def_id, moved_place, places) {
|
||||
if let Some((args_span, generator_kind, var_span))
|
||||
= self.closure_span(*def_id, moved_place, places) {
|
||||
return ClosureUse {
|
||||
is_generator,
|
||||
generator_kind,
|
||||
args_span,
|
||||
var_span,
|
||||
};
|
||||
|
@ -857,11 +866,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
"borrow_spans: def_id={:?} is_generator={:?} places={:?}",
|
||||
def_id, is_generator, places
|
||||
);
|
||||
if let Some((args_span, var_span)) = self.closure_span(
|
||||
if let Some((args_span, generator_kind, var_span)) = self.closure_span(
|
||||
*def_id, Place::from(target).as_ref(), places
|
||||
) {
|
||||
return ClosureUse {
|
||||
is_generator,
|
||||
generator_kind,
|
||||
args_span,
|
||||
var_span,
|
||||
};
|
||||
|
@ -884,7 +893,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
def_id: DefId,
|
||||
target_place: PlaceRef<'cx, 'tcx>,
|
||||
places: &Vec<Operand<'tcx>>,
|
||||
) -> Option<(Span, Span)> {
|
||||
) -> Option<(Span, Option<GeneratorKind>, Span)> {
|
||||
debug!(
|
||||
"closure_span: def_id={:?} target_place={:?} places={:?}",
|
||||
def_id, target_place, places
|
||||
|
@ -893,14 +902,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
|
||||
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
|
||||
if let hir::ExprKind::Closure(
|
||||
.., args_span, _
|
||||
.., body_id, args_span, _
|
||||
) = expr {
|
||||
for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
|
||||
match place {
|
||||
Operand::Copy(place) |
|
||||
Operand::Move(place) if target_place == place.as_ref() => {
|
||||
debug!("closure_span: found captured local {:?}", place);
|
||||
return Some((*args_span, upvar.span));
|
||||
let body = self.infcx.tcx.hir().body(*body_id);
|
||||
let generator_kind = body.generator_kind();
|
||||
return Some((*args_span, generator_kind, upvar.span));
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ note: generator is returned here
|
|||
|
|
||||
LL | fn foo() -> Box<impl std::future::Future<Output = u32>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
||||
help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
||||
|
|
||||
LL | Box::new(async move { x } )
|
||||
| ^^^^^^^^^^
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue