Rewrite closure capture analysis
This commit is contained in:
parent
b090cd1ea6
commit
c4f28ca611
5 changed files with 170 additions and 194 deletions
|
@ -149,8 +149,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
closure_def_id,
|
||||
closure_span: span,
|
||||
capture_clause,
|
||||
current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM,
|
||||
current_origin: None,
|
||||
_current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM,
|
||||
_current_origin: None,
|
||||
capture_information: Default::default(),
|
||||
fake_reads: Default::default(),
|
||||
};
|
||||
|
@ -167,9 +167,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
"For closure={:?}, capture_information={:#?}",
|
||||
closure_def_id, delegate.capture_information
|
||||
);
|
||||
|
||||
self.log_capture_analysis_first_pass(closure_def_id, &delegate.capture_information, span);
|
||||
|
||||
self.compute_min_captures(closure_def_id, capture_clause, delegate.capture_information);
|
||||
let (capture_information, closure_kind, origin) = self
|
||||
.process_collected_capture_information(capture_clause, delegate.capture_information);
|
||||
|
||||
self.compute_min_captures(closure_def_id, capture_information);
|
||||
|
||||
let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
|
||||
|
||||
|
@ -204,7 +208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// This will update the min captures based on this new fake information.
|
||||
self.compute_min_captures(closure_def_id, capture_clause, capture_information);
|
||||
self.compute_min_captures(closure_def_id, capture_information);
|
||||
}
|
||||
|
||||
let before_feature_tys = self.final_upvar_tys(closure_def_id);
|
||||
|
@ -212,14 +216,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(closure_substs) = infer_kind {
|
||||
// Unify the (as yet unbound) type variable in the closure
|
||||
// substs with the kind we inferred.
|
||||
let inferred_kind = delegate.current_closure_kind;
|
||||
let closure_kind_ty = closure_substs.as_closure().kind_ty();
|
||||
self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
|
||||
self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
|
||||
|
||||
// If we have an origin, store it.
|
||||
if let Some(origin) = delegate.current_origin.clone() {
|
||||
if let Some(origin) = origin {
|
||||
let origin = if enable_precise_capture(self.tcx, span) {
|
||||
(origin.0, restrict_capture_precision(capture_clause, origin.1))
|
||||
(origin.0, origin.1)
|
||||
} else {
|
||||
(origin.0, Place { projections: vec![], ..origin.1 })
|
||||
};
|
||||
|
@ -306,6 +309,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn process_collected_capture_information(
|
||||
&self,
|
||||
capture_clause: hir::CaptureBy,
|
||||
capture_information: InferredCaptureInformation<'tcx>,
|
||||
) -> (InferredCaptureInformation<'tcx>, ty::ClosureKind, Option<(Span, Place<'tcx>)>) {
|
||||
let mut processed: InferredCaptureInformation<'tcx> = Default::default();
|
||||
|
||||
let mut closure_kind = ty::ClosureKind::LATTICE_BOTTOM;
|
||||
let mut origin: Option<(Span, Place<'tcx>)> = None;
|
||||
|
||||
for (place, mut capture_info) in capture_information.into_iter() {
|
||||
let place = restrict_capture_precision(capture_clause, place);
|
||||
let usage_span = if let Some(usage_expr) = capture_info.path_expr_id {
|
||||
self.tcx.hir().span(usage_expr)
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let updated = match capture_info.capture_kind {
|
||||
ty::UpvarCapture::ByValue(..) => match closure_kind {
|
||||
ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
|
||||
(ty::ClosureKind::FnOnce, Some((usage_span, place.clone())))
|
||||
}
|
||||
// If closure is already FnOnce, don't update
|
||||
ty::ClosureKind::FnOnce => (closure_kind, origin),
|
||||
},
|
||||
|
||||
ty::UpvarCapture::ByRef(ty::UpvarBorrow {
|
||||
kind: ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
|
||||
..
|
||||
}) => {
|
||||
match closure_kind {
|
||||
ty::ClosureKind::Fn => {
|
||||
(ty::ClosureKind::FnMut, Some((usage_span, place.clone())))
|
||||
}
|
||||
// Don't update the origin
|
||||
ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce => (closure_kind, origin),
|
||||
}
|
||||
}
|
||||
|
||||
_ => (closure_kind, origin),
|
||||
};
|
||||
|
||||
closure_kind = updated.0;
|
||||
origin = updated.1;
|
||||
|
||||
let (place, capture_kind) = match capture_clause {
|
||||
hir::CaptureBy::Value => process_for_move(place, capture_info.capture_kind),
|
||||
hir::CaptureBy::Ref => process_for_ref(place, capture_info.capture_kind),
|
||||
};
|
||||
|
||||
capture_info.capture_kind = capture_kind;
|
||||
processed.insert(place, capture_info);
|
||||
}
|
||||
|
||||
(processed, closure_kind, origin)
|
||||
}
|
||||
|
||||
/// Analyzes the information collected by `InferBorrowKind` to compute the min number of
|
||||
/// Places (and corresponding capture kind) that we need to keep track of to support all
|
||||
/// the required captured paths.
|
||||
|
@ -378,7 +439,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
fn compute_min_captures(
|
||||
&self,
|
||||
closure_def_id: DefId,
|
||||
capture_clause: hir::CaptureBy,
|
||||
capture_information: InferredCaptureInformation<'tcx>,
|
||||
) {
|
||||
if capture_information.is_empty() {
|
||||
|
@ -396,8 +456,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
base => bug!("Expected upvar, found={:?}", base),
|
||||
};
|
||||
|
||||
let place = restrict_capture_precision(capture_clause, place);
|
||||
|
||||
let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) {
|
||||
None => {
|
||||
let mutability = self.determine_capture_mutability(&typeck_results, &place);
|
||||
|
@ -1336,11 +1394,11 @@ struct InferBorrowKind<'a, 'tcx> {
|
|||
// we've taken the closure kind from the expectations instead, and
|
||||
// for generators we don't even implement the closure traits
|
||||
// really).
|
||||
current_closure_kind: ty::ClosureKind,
|
||||
_current_closure_kind: ty::ClosureKind,
|
||||
|
||||
// If we modified `current_closure_kind`, this field contains a `Some()` with the
|
||||
// variable access that caused us to do so.
|
||||
current_origin: Option<(Span, Place<'tcx>)>,
|
||||
_current_origin: Option<(Span, Place<'tcx>)>,
|
||||
|
||||
/// For each Place that is captured by the closure, we track the minimal kind of
|
||||
/// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
|
||||
|
@ -1384,27 +1442,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
|||
place_with_id, diag_expr_id, mode
|
||||
);
|
||||
|
||||
match (self.capture_clause, mode) {
|
||||
// In non-move closures, we only care about moves
|
||||
(hir::CaptureBy::Ref, euv::Copy) => return,
|
||||
|
||||
// We want to capture Copy types that read through a ref via a reborrow
|
||||
(hir::CaptureBy::Value, euv::Copy)
|
||||
if place_with_id.place.deref_tys().any(ty::TyS::is_ref) =>
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
(hir::CaptureBy::Ref, euv::Move) | (hir::CaptureBy::Value, euv::Move | euv::Copy) => {}
|
||||
// AMAN: Don't upgrade copy types to ByValue
|
||||
match mode {
|
||||
euv::ConsumeMode::Copy => return,
|
||||
euv::ConsumeMode::Move => {}
|
||||
};
|
||||
|
||||
let place = truncate_capture_for_move(place_with_id.place.clone());
|
||||
let place_with_id = PlaceWithHirId { place: place.clone(), hir_id: place_with_id.hir_id };
|
||||
|
||||
if !self.capture_information.contains_key(&place) {
|
||||
self.init_capture_info_for_place(&place_with_id, diag_expr_id);
|
||||
}
|
||||
|
||||
let tcx = self.fcx.tcx;
|
||||
let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
|
||||
upvar_id
|
||||
|
@ -1416,16 +1459,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
|||
|
||||
let usage_span = tcx.hir().span(diag_expr_id);
|
||||
|
||||
if matches!(mode, euv::Move) {
|
||||
// To move out of an upvar, this must be a FnOnce closure
|
||||
self.adjust_closure_kind(
|
||||
upvar_id.closure_expr_id,
|
||||
ty::ClosureKind::FnOnce,
|
||||
usage_span,
|
||||
place.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
let capture_info = ty::CaptureInfo {
|
||||
capture_kind_expr_id: Some(diag_expr_id),
|
||||
path_expr_id: Some(diag_expr_id),
|
||||
|
@ -1503,22 +1536,13 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
|||
ty::ImmBorrow => false,
|
||||
});
|
||||
|
||||
let tcx = self.fcx.tcx;
|
||||
// let tcx = self.fcx.tcx;
|
||||
|
||||
// if this is an implicit deref of an
|
||||
// upvar, then we need to modify the
|
||||
// borrow_kind of the upvar to make sure it
|
||||
// is inferred to mutable if necessary
|
||||
self.adjust_upvar_borrow_kind(place_with_id, diag_expr_id, borrow_kind);
|
||||
|
||||
if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
|
||||
self.adjust_closure_kind(
|
||||
upvar_id.closure_expr_id,
|
||||
ty::ClosureKind::FnMut,
|
||||
tcx.hir().span(diag_expr_id),
|
||||
place_with_id.place.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// We infer the borrow_kind with which to borrow upvars in a stack closure.
|
||||
|
@ -1557,48 +1581,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
|||
};
|
||||
}
|
||||
|
||||
fn adjust_closure_kind(
|
||||
&mut self,
|
||||
closure_id: LocalDefId,
|
||||
new_kind: ty::ClosureKind,
|
||||
upvar_span: Span,
|
||||
place: Place<'tcx>,
|
||||
) {
|
||||
debug!(
|
||||
"adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, place={:?})",
|
||||
closure_id, new_kind, upvar_span, place
|
||||
);
|
||||
|
||||
// Is this the closure whose kind is currently being inferred?
|
||||
if closure_id.to_def_id() != self.closure_def_id {
|
||||
debug!("adjust_closure_kind: not current closure");
|
||||
return;
|
||||
}
|
||||
|
||||
// closures start out as `Fn`.
|
||||
let existing_kind = self.current_closure_kind;
|
||||
|
||||
debug!(
|
||||
"adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
|
||||
closure_id, existing_kind, new_kind
|
||||
);
|
||||
|
||||
match (existing_kind, new_kind) {
|
||||
(ty::ClosureKind::Fn, ty::ClosureKind::Fn)
|
||||
| (ty::ClosureKind::FnMut, ty::ClosureKind::Fn | ty::ClosureKind::FnMut)
|
||||
| (ty::ClosureKind::FnOnce, _) => {
|
||||
// no change needed
|
||||
}
|
||||
|
||||
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce)
|
||||
| (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
|
||||
// new kind is stronger than the old kind
|
||||
self.current_closure_kind = new_kind;
|
||||
self.current_origin = Some((upvar_span, place));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init_capture_info_for_place(
|
||||
&mut self,
|
||||
place_with_id: &PlaceWithHirId<'tcx>,
|
||||
|
@ -1607,12 +1589,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
|||
if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
|
||||
assert_eq!(self.closure_def_id.expect_local(), upvar_id.closure_expr_id);
|
||||
|
||||
let capture_kind = self.fcx.init_capture_kind_for_place(
|
||||
&place_with_id.place,
|
||||
self.capture_clause,
|
||||
upvar_id,
|
||||
self.closure_span,
|
||||
);
|
||||
// AMAN: Always initialize to ImmBorrow
|
||||
// We will increase the CaptureKind in process_collected_capture_information.
|
||||
let origin = UpvarRegion(upvar_id, self.closure_span);
|
||||
let upvar_region = self.fcx.next_region_var(origin);
|
||||
let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: upvar_region };
|
||||
let capture_kind = ty::UpvarCapture::ByRef(upvar_borrow);
|
||||
|
||||
let expr_id = Some(diag_expr_id);
|
||||
let capture_info = ty::CaptureInfo {
|
||||
|
@ -1711,44 +1693,12 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Deref of a box isn't captured in move clousres. This is motivated by:
|
||||
/// 1. We only want to capture data that is on the stack
|
||||
/// 2. One motivation for the user to use a box might be to reduce the amount of data that gets
|
||||
/// moved (if size of pointer < size of data). We want to make sure that this optimization that
|
||||
/// the user made is respected.
|
||||
fn restrict_precision_for_box<'tcx>(
|
||||
capture_clause: hir::CaptureBy,
|
||||
mut place: Place<'tcx>,
|
||||
) -> Place<'tcx> {
|
||||
match capture_clause {
|
||||
hir::CaptureBy::Ref => {}
|
||||
hir::CaptureBy::Value => {
|
||||
if ty::TyS::is_box(place.base_ty) {
|
||||
place.projections.truncate(0);
|
||||
} else {
|
||||
// Either the box is the last access or there is a deref applied on the box
|
||||
// In either case we want to stop at the box.
|
||||
let pos = place.projections.iter().position(|proj| ty::TyS::is_box(proj.ty));
|
||||
match pos {
|
||||
None => {}
|
||||
Some(idx) => {
|
||||
place.projections.truncate(idx + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
place
|
||||
}
|
||||
|
||||
/// Truncate projections so that following rules are obeyed by the captured `place`:
|
||||
/// - No projections are applied to raw pointers, since these require unsafe blocks. We capture
|
||||
/// them completely.
|
||||
/// - No Index projections are captured, since arrays are captured completely.
|
||||
/// - Deref of a box isn't captured in move clousres.
|
||||
fn restrict_capture_precision<'tcx>(
|
||||
capture_clause: hir::CaptureBy,
|
||||
_capture_clause: hir::CaptureBy,
|
||||
mut place: Place<'tcx>,
|
||||
) -> Place<'tcx> {
|
||||
if place.projections.is_empty() {
|
||||
|
@ -1785,19 +1735,63 @@ fn restrict_capture_precision<'tcx>(
|
|||
|
||||
place.projections.truncate(length);
|
||||
|
||||
// Dont't capture projections on top of a box in move closures.
|
||||
restrict_precision_for_box(capture_clause, place)
|
||||
place
|
||||
}
|
||||
|
||||
/// Truncates a place so that the resultant capture doesn't move data out of a reference
|
||||
fn truncate_capture_for_move(mut place: Place<'tcx>) -> Place<'tcx> {
|
||||
if let Some(i) = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref) {
|
||||
// We only drop Derefs in case of move closures
|
||||
// There might be an index projection or raw ptr ahead, so we don't stop here.
|
||||
place.projections.truncate(i);
|
||||
}
|
||||
fn process_for_move<'tcx>(
|
||||
mut place: Place<'tcx>,
|
||||
kind: ty::UpvarCapture<'tcx>,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref());
|
||||
match kind {
|
||||
ty::UpvarCapture::ByRef(..) if contains_deref_of_ref => (place, kind),
|
||||
|
||||
place
|
||||
// If there's any Deref and the data needs to be moved into the closure body,
|
||||
// or it's a Deref of a Box, truncate the path to the first deref
|
||||
_ if place.deref_tys().next().is_some() => {
|
||||
let first_deref =
|
||||
place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
|
||||
let place = match first_deref {
|
||||
Some(idx) => {
|
||||
place.projections.truncate(idx);
|
||||
place
|
||||
}
|
||||
None => place,
|
||||
};
|
||||
|
||||
// AMAN: I think we don't need the span inside the ByValue anymore
|
||||
// we have more detailed span in CaptureInfo
|
||||
(place, ty::UpvarCapture::ByValue(None))
|
||||
}
|
||||
|
||||
_ => (place, ty::UpvarCapture::ByValue(None)),
|
||||
}
|
||||
}
|
||||
|
||||
fn process_for_ref<'tcx>(
|
||||
mut place: Place<'tcx>,
|
||||
kind: ty::UpvarCapture<'tcx>,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
||||
let contains_deref =
|
||||
place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
|
||||
|
||||
match kind {
|
||||
ty::UpvarCapture::ByValue(..) if contains_deref.is_some() => {
|
||||
let place = match contains_deref {
|
||||
Some(idx) => {
|
||||
place.projections.truncate(idx);
|
||||
place
|
||||
}
|
||||
// Because of the if guard on the match on `kind`, we should never get here.
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
||||
(place, kind)
|
||||
}
|
||||
|
||||
ty::UpvarCapture::ByValue(..) => (place, kind),
|
||||
ty::UpvarCapture::ByRef(..) => (place, kind),
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
|
||||
|
|
|
@ -22,8 +22,7 @@ fn big_box() {
|
|||
//~^ First Pass analysis includes:
|
||||
//~| Min Capture analysis includes:
|
||||
let p = t.0.0;
|
||||
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
|
||||
//~| NOTE: Capturing t[(0, 0)] -> ByValue
|
||||
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
|
||||
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
|
||||
println!("{} {:?}", t.1, p);
|
||||
//~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow
|
||||
|
|
|
@ -19,18 +19,13 @@ LL | |
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
|
||||
--> $DIR/by_value.rs:24:17
|
||||
|
|
||||
LL | let p = t.0.0;
|
||||
| ^^^^^
|
||||
note: Capturing t[(0, 0)] -> ByValue
|
||||
note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
|
||||
--> $DIR/by_value.rs:24:17
|
||||
|
|
||||
LL | let p = t.0.0;
|
||||
| ^^^^^
|
||||
note: Capturing t[(1, 0)] -> ImmBorrow
|
||||
--> $DIR/by_value.rs:28:29
|
||||
--> $DIR/by_value.rs:27:29
|
||||
|
|
||||
LL | println!("{} {:?}", t.1, p);
|
||||
| ^^^
|
||||
|
@ -53,7 +48,7 @@ note: Min Capture t[(0, 0)] -> ByValue
|
|||
LL | let p = t.0.0;
|
||||
| ^^^^^
|
||||
note: Min Capture t[(1, 0)] -> ImmBorrow
|
||||
--> $DIR/by_value.rs:28:29
|
||||
--> $DIR/by_value.rs:27:29
|
||||
|
|
||||
LL | println!("{} {:?}", t.1, p);
|
||||
| ^^^
|
||||
|
|
|
@ -16,7 +16,7 @@ fn simple_move_closure() {
|
|||
//~^ ERROR: First Pass analysis includes:
|
||||
//~| ERROR: Min Capture analysis includes:
|
||||
t.0.0 = "new S".into();
|
||||
//~^ NOTE: Capturing t[(0, 0),(0, 0)] -> ByValue
|
||||
//~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow
|
||||
//~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
|
||||
};
|
||||
c();
|
||||
|
@ -100,8 +100,7 @@ fn struct_contains_ref_to_another_struct_3() {
|
|||
//~^ ERROR: First Pass analysis includes:
|
||||
//~| ERROR: Min Capture analysis includes:
|
||||
let _t = t.0.0;
|
||||
//~^ NOTE: Capturing t[(0, 0),Deref] -> ImmBorrow
|
||||
//~| NOTE: Capturing t[(0, 0)] -> ByValue
|
||||
//~^ NOTE: Capturing t[(0, 0),Deref] -> ByValue
|
||||
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
|
||||
};
|
||||
|
||||
|
@ -122,8 +121,7 @@ fn truncate_box_derefs() {
|
|||
//~^ ERROR: First Pass analysis includes:
|
||||
//~| ERROR: Min Capture analysis includes:
|
||||
let _t = b.0;
|
||||
//~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue
|
||||
//~| NOTE: Capturing b[] -> ByValue
|
||||
//~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
|
||||
//~| NOTE: Min Capture b[] -> ByValue
|
||||
};
|
||||
|
||||
|
@ -139,7 +137,7 @@ fn truncate_box_derefs() {
|
|||
//~^ ERROR: First Pass analysis includes:
|
||||
//~| ERROR: Min Capture analysis includes:
|
||||
println!("{}", b.0);
|
||||
//~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue
|
||||
//~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
|
||||
//~| NOTE: Min Capture b[] -> ByValue
|
||||
};
|
||||
|
||||
|
@ -156,7 +154,7 @@ fn truncate_box_derefs() {
|
|||
//~^ ERROR: First Pass analysis includes:
|
||||
//~| ERROR: Min Capture analysis includes:
|
||||
println!("{}", t.1.0);
|
||||
//~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue
|
||||
//~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
|
||||
//~| NOTE: Min Capture t[(1, 0)] -> ByValue
|
||||
};
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ LL | let mut c = #[rustc_capture_analysis]
|
|||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/move_closure.rs:118:13
|
||||
--> $DIR/move_closure.rs:117:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -53,7 +53,7 @@ LL | let c = #[rustc_capture_analysis]
|
|||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/move_closure.rs:135:13
|
||||
--> $DIR/move_closure.rs:133:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -62,7 +62,7 @@ LL | let c = #[rustc_capture_analysis]
|
|||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/move_closure.rs:152:13
|
||||
--> $DIR/move_closure.rs:150:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -82,7 +82,7 @@ LL | |
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing t[(0, 0),(0, 0)] -> ByValue
|
||||
note: Capturing t[(0, 0),(0, 0)] -> MutBorrow
|
||||
--> $DIR/move_closure.rs:18:9
|
||||
|
|
||||
LL | t.0.0 = "new S".into();
|
||||
|
@ -221,17 +221,12 @@ LL | / move || {
|
|||
LL | |
|
||||
LL | |
|
||||
LL | | let _t = t.0.0;
|
||||
... |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing t[(0, 0),Deref] -> ImmBorrow
|
||||
--> $DIR/move_closure.rs:102:18
|
||||
|
|
||||
LL | let _t = t.0.0;
|
||||
| ^^^^^
|
||||
note: Capturing t[(0, 0)] -> ByValue
|
||||
note: Capturing t[(0, 0),Deref] -> ByValue
|
||||
--> $DIR/move_closure.rs:102:18
|
||||
|
|
||||
LL | let _t = t.0.0;
|
||||
|
@ -244,7 +239,7 @@ LL | / move || {
|
|||
LL | |
|
||||
LL | |
|
||||
LL | | let _t = t.0.0;
|
||||
... |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
@ -256,48 +251,43 @@ LL | let _t = t.0.0;
|
|||
| ^^^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/move_closure.rs:121:5
|
||||
--> $DIR/move_closure.rs:120:5
|
||||
|
|
||||
LL | / move || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _t = b.0;
|
||||
... |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing b[Deref,(0, 0)] -> ByValue
|
||||
--> $DIR/move_closure.rs:124:18
|
||||
|
|
||||
LL | let _t = b.0;
|
||||
| ^^^
|
||||
note: Capturing b[] -> ByValue
|
||||
--> $DIR/move_closure.rs:124:18
|
||||
note: Capturing b[Deref,(0, 0)] -> ImmBorrow
|
||||
--> $DIR/move_closure.rs:123:18
|
||||
|
|
||||
LL | let _t = b.0;
|
||||
| ^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/move_closure.rs:121:5
|
||||
--> $DIR/move_closure.rs:120:5
|
||||
|
|
||||
LL | / move || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _t = b.0;
|
||||
... |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture b[] -> ByValue
|
||||
--> $DIR/move_closure.rs:124:18
|
||||
--> $DIR/move_closure.rs:123:18
|
||||
|
|
||||
LL | let _t = b.0;
|
||||
| ^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/move_closure.rs:138:5
|
||||
--> $DIR/move_closure.rs:136:5
|
||||
|
|
||||
LL | / move || {
|
||||
LL | |
|
||||
|
@ -308,14 +298,14 @@ LL | |
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing b[Deref,(0, 0)] -> ByValue
|
||||
--> $DIR/move_closure.rs:141:24
|
||||
note: Capturing b[Deref,(0, 0)] -> ImmBorrow
|
||||
--> $DIR/move_closure.rs:139:24
|
||||
|
|
||||
LL | println!("{}", b.0);
|
||||
| ^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/move_closure.rs:138:5
|
||||
--> $DIR/move_closure.rs:136:5
|
||||
|
|
||||
LL | / move || {
|
||||
LL | |
|
||||
|
@ -327,13 +317,13 @@ LL | | };
|
|||
| |_____^
|
||||
|
|
||||
note: Min Capture b[] -> ByValue
|
||||
--> $DIR/move_closure.rs:141:24
|
||||
--> $DIR/move_closure.rs:139:24
|
||||
|
|
||||
LL | println!("{}", b.0);
|
||||
| ^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/move_closure.rs:155:5
|
||||
--> $DIR/move_closure.rs:153:5
|
||||
|
|
||||
LL | / move || {
|
||||
LL | |
|
||||
|
@ -344,14 +334,14 @@ LL | |
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue
|
||||
--> $DIR/move_closure.rs:158:24
|
||||
note: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
|
||||
--> $DIR/move_closure.rs:156:24
|
||||
|
|
||||
LL | println!("{}", t.1.0);
|
||||
| ^^^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/move_closure.rs:155:5
|
||||
--> $DIR/move_closure.rs:153:5
|
||||
|
|
||||
LL | / move || {
|
||||
LL | |
|
||||
|
@ -363,7 +353,7 @@ LL | | };
|
|||
| |_____^
|
||||
|
|
||||
note: Min Capture t[(1, 0)] -> ByValue
|
||||
--> $DIR/move_closure.rs:158:24
|
||||
--> $DIR/move_closure.rs:156:24
|
||||
|
|
||||
LL | println!("{}", t.1.0);
|
||||
| ^^^^^
|
||||
|
|
Loading…
Reference in a new issue