1
Fork 0

Flatten InferredCaptureInformation

Min capture computation can already handle the same place appearing twice,
and previous commits made CaptureInfo construction very cheap, so just
delegate all work to min capture and let InferBorrowKind and
process_collected_capture_information handle everything linearly.
This commit is contained in:
Gary Guo 2021-10-13 22:14:37 +01:00
parent 52db6b9d02
commit c84cea9c25
11 changed files with 169 additions and 109 deletions

View file

@ -33,7 +33,6 @@
use super::FnCtxt; use super::FnCtxt;
use crate::expr_use_visitor as euv; use crate::expr_use_visitor as euv;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -72,7 +71,7 @@ enum PlaceAncestryRelation {
/// Intermediate format to store a captured `Place` and associated `ty::CaptureInfo` /// Intermediate format to store a captured `Place` and associated `ty::CaptureInfo`
/// during capture analysis. Information in this map feeds into the minimum capture /// during capture analysis. Information in this map feeds into the minimum capture
/// analysis pass. /// analysis pass.
type InferredCaptureInformation<'tcx> = FxIndexMap<Place<'tcx>, ty::CaptureInfo>; type InferredCaptureInformation<'tcx> = Vec<(Place<'tcx>, ty::CaptureInfo)>;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) { pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
@ -258,7 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
capture_kind, capture_kind,
}; };
capture_information.insert(place, fake_info); capture_information.push((place, fake_info));
} }
} }
@ -384,76 +383,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
capture_clause: hir::CaptureBy, capture_clause: hir::CaptureBy,
capture_information: InferredCaptureInformation<'tcx>, capture_information: InferredCaptureInformation<'tcx>,
) -> (InferredCaptureInformation<'tcx>, ty::ClosureKind, Option<(Span, Place<'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 closure_kind = ty::ClosureKind::LATTICE_BOTTOM;
let mut origin: Option<(Span, Place<'tcx>)> = None; let mut origin: Option<(Span, Place<'tcx>)> = None;
for (place, mut capture_info) in capture_information { let processed = capture_information
// Apply rules for safety before inferring closure kind .into_iter()
let (place, capture_kind) = .map(|(place, mut capture_info)| {
restrict_capture_precision(place, capture_info.capture_kind); // Apply rules for safety before inferring closure kind
capture_info.capture_kind = capture_kind; let (place, capture_kind) =
restrict_capture_precision(place, capture_info.capture_kind);
let (place, capture_kind) = let (place, capture_kind) = truncate_capture_for_optimization(place, capture_kind);
truncate_capture_for_optimization(place, capture_info.capture_kind);
capture_info.capture_kind = capture_kind;
let usage_span = if let Some(usage_expr) = capture_info.path_expr_id { let usage_span = if let Some(usage_expr) = capture_info.path_expr_id {
self.tcx.hir().span(usage_expr) self.tcx.hir().span(usage_expr)
} else { } else {
unreachable!() unreachable!()
}; };
let updated = match capture_info.capture_kind { let updated = match capture_kind {
ty::UpvarCapture::ByValue => match closure_kind { ty::UpvarCapture::ByValue => match closure_kind {
ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
(ty::ClosureKind::FnOnce, Some((usage_span, place.clone()))) (ty::ClosureKind::FnOnce, Some((usage_span, place.clone())))
} }
// If closure is already FnOnce, don't update // If closure is already FnOnce, don't update
ty::ClosureKind::FnOnce => (closure_kind, origin), ty::ClosureKind::FnOnce => (closure_kind, origin.take()),
}, },
ty::UpvarCapture::ByRef( ty::UpvarCapture::ByRef(
ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow, ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
) => { ) => {
match closure_kind { match closure_kind {
ty::ClosureKind::Fn => { ty::ClosureKind::Fn => {
(ty::ClosureKind::FnMut, Some((usage_span, place.clone()))) (ty::ClosureKind::FnMut, Some((usage_span, place.clone())))
}
// Don't update the origin
ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce => {
(closure_kind, origin.take())
}
} }
// Don't update the origin
ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce => (closure_kind, origin),
} }
}
_ => (closure_kind, origin), _ => (closure_kind, origin.take()),
}; };
closure_kind = updated.0; closure_kind = updated.0;
origin = updated.1; origin = updated.1;
let (place, capture_kind) = match capture_clause { let (place, capture_kind) = match capture_clause {
hir::CaptureBy::Value => adjust_for_move_closure(place, capture_info.capture_kind), hir::CaptureBy::Value => adjust_for_move_closure(place, capture_kind),
hir::CaptureBy::Ref => { hir::CaptureBy::Ref => adjust_for_non_move_closure(place, capture_kind),
adjust_for_non_move_closure(place, capture_info.capture_kind) };
}
};
// This restriction needs to be applied after we have handled adjustments for `move` // This restriction needs to be applied after we have handled adjustments for `move`
// closures. We want to make sure any adjustment that might make us move the place into // closures. We want to make sure any adjustment that might make us move the place into
// the closure gets handled. // the closure gets handled.
let (place, capture_kind) = let (place, capture_kind) =
restrict_precision_for_drop_types(self, place, capture_kind, usage_span); restrict_precision_for_drop_types(self, place, capture_kind, usage_span);
capture_info.capture_kind = capture_kind; capture_info.capture_kind = capture_kind;
(place, capture_info)
let capture_info = if let Some(existing) = processed.get(&place) { })
determine_capture_info(*existing, capture_info) .collect();
} else {
capture_info
};
processed.insert(place, capture_info);
}
(processed, closure_kind, origin) (processed, closure_kind, origin)
} }
@ -609,8 +600,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !descendant_found { if !descendant_found {
for possible_ancestor in min_cap_list.iter_mut() { for possible_ancestor in min_cap_list.iter_mut() {
match determine_place_ancestry_relation(&place, &possible_ancestor.place) { match determine_place_ancestry_relation(&place, &possible_ancestor.place) {
PlaceAncestryRelation::SamePlace => {
ancestor_found = true;
possible_ancestor.info = determine_capture_info(
possible_ancestor.info,
updated_capture_info,
);
// Only one related place will be in the list.
break;
}
// current place is descendant of possible_ancestor // current place is descendant of possible_ancestor
PlaceAncestryRelation::Descendant | PlaceAncestryRelation::SamePlace => { PlaceAncestryRelation::Descendant => {
ancestor_found = true; ancestor_found = true;
let backup_path_expr_id = possible_ancestor.info.path_expr_id; let backup_path_expr_id = possible_ancestor.info.path_expr_id;
@ -630,7 +631,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// we need to keep the ancestor's `path_expr_id` // we need to keep the ancestor's `path_expr_id`
possible_ancestor.info.path_expr_id = backup_path_expr_id; possible_ancestor.info.path_expr_id = backup_path_expr_id;
// Only one ancestor of the current place will be in the list. // Only one related place will be in the list.
break; break;
} }
_ => {} _ => {}
@ -1532,7 +1533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn log_capture_analysis_first_pass( fn log_capture_analysis_first_pass(
&self, &self,
closure_def_id: rustc_hir::def_id::DefId, closure_def_id: rustc_hir::def_id::DefId,
capture_information: &FxIndexMap<Place<'tcx>, ty::CaptureInfo>, capture_information: &InferredCaptureInformation<'tcx>,
closure_span: Span, closure_span: Span,
) { ) {
if self.should_log_capture_analysis(closure_def_id) { if self.should_log_capture_analysis(closure_def_id) {
@ -1759,20 +1760,6 @@ struct InferBorrowKind<'a, 'tcx> {
fake_reads: Vec<(Place<'tcx>, FakeReadCause, hir::HirId)>, fake_reads: Vec<(Place<'tcx>, FakeReadCause, hir::HirId)>,
} }
impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
fn adjust_capture_info(&mut self, place: Place<'tcx>, capture_info: ty::CaptureInfo) {
match self.capture_information.get_mut(&place) {
Some(curr_info) => {
*curr_info = determine_capture_info(*curr_info, capture_info);
}
None => {
debug!("Capturing new place {:?}, capture_info={:?}", place, capture_info);
self.capture_information.insert(place, capture_info);
}
}
}
}
impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId) { fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId) {
let PlaceBase::Upvar(_) = place.base else { return }; let PlaceBase::Upvar(_) = place.base else { return };
@ -1797,14 +1784,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return }; let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return };
assert_eq!(self.closure_def_id, upvar_id.closure_expr_id); assert_eq!(self.closure_def_id, upvar_id.closure_expr_id);
self.adjust_capture_info( self.capture_information.push((
place_with_id.place.clone(), place_with_id.place.clone(),
ty::CaptureInfo { ty::CaptureInfo {
capture_kind_expr_id: Some(diag_expr_id), capture_kind_expr_id: Some(diag_expr_id),
path_expr_id: Some(diag_expr_id), path_expr_id: Some(diag_expr_id),
capture_kind: ty::UpvarCapture::ByValue, capture_kind: ty::UpvarCapture::ByValue,
}, },
); ));
} }
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
@ -1835,14 +1822,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow); capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow);
} }
self.adjust_capture_info( self.capture_information.push((
place, place,
ty::CaptureInfo { ty::CaptureInfo {
capture_kind_expr_id: Some(diag_expr_id), capture_kind_expr_id: Some(diag_expr_id),
path_expr_id: Some(diag_expr_id), path_expr_id: Some(diag_expr_id),
capture_kind, capture_kind,
}, },
); ));
} }
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]

View file

@ -15,6 +15,7 @@ fn main() {
//~^ NOTE: Capturing m[] -> MutBorrow //~^ NOTE: Capturing m[] -> MutBorrow
//~| NOTE: Min Capture m[] -> MutBorrow //~| NOTE: Min Capture m[] -> MutBorrow
m[1] += 40; m[1] += 40;
//~^ NOTE: Capturing m[] -> MutBorrow
}; };
c(); c();

View file

@ -15,7 +15,7 @@ LL | |
LL | | LL | |
LL | | m[0] += 10; LL | | m[0] += 10;
... | ... |
LL | | m[1] += 40; LL | |
LL | | }; LL | | };
| |_____^ | |_____^
| |
@ -24,6 +24,11 @@ note: Capturing m[] -> MutBorrow
| |
LL | m[0] += 10; LL | m[0] += 10;
| ^ | ^
note: Capturing m[] -> MutBorrow
--> $DIR/arrays-completely-captured.rs:17:9
|
LL | m[1] += 40;
| ^
error: Min Capture analysis includes: error: Min Capture analysis includes:
--> $DIR/arrays-completely-captured.rs:11:5 --> $DIR/arrays-completely-captured.rs:11:5
@ -33,7 +38,7 @@ LL | |
LL | | LL | |
LL | | m[0] += 10; LL | | m[0] += 10;
... | ... |
LL | | m[1] += 40; LL | |
LL | | }; LL | | };
| |_____^ | |_____^
| |

View file

@ -15,6 +15,8 @@ fn arrays() {
//~| ERROR: Min Capture analysis includes: //~| ERROR: Min Capture analysis includes:
let [a, b, .., e] = arr; let [a, b, .., e] = arr;
//~^ NOTE: Capturing arr[Index] -> ByValue //~^ NOTE: Capturing arr[Index] -> ByValue
//~| NOTE: Capturing arr[Index] -> ByValue
//~| NOTE: Capturing arr[Index] -> ByValue
//~| NOTE: Min Capture arr[] -> ByValue //~| NOTE: Min Capture arr[] -> ByValue
assert_eq!(a, "A"); assert_eq!(a, "A");
assert_eq!(b, "B"); assert_eq!(b, "B");

View file

@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis]
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental error[E0658]: attributes on expressions are experimental
--> $DIR/destructure_patterns.rs:36:13 --> $DIR/destructure_patterns.rs:38:13
| |
LL | let c = #[rustc_capture_analysis] LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -17,7 +17,7 @@ LL | let c = #[rustc_capture_analysis]
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental error[E0658]: attributes on expressions are experimental
--> $DIR/destructure_patterns.rs:56:13 --> $DIR/destructure_patterns.rs:58:13
| |
LL | let c = #[rustc_capture_analysis] LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -42,6 +42,16 @@ note: Capturing arr[Index] -> ByValue
| |
LL | let [a, b, .., e] = arr; LL | let [a, b, .., e] = arr;
| ^^^ | ^^^
note: Capturing arr[Index] -> ByValue
--> $DIR/destructure_patterns.rs:16:29
|
LL | let [a, b, .., e] = arr;
| ^^^
note: Capturing arr[Index] -> ByValue
--> $DIR/destructure_patterns.rs:16:29
|
LL | let [a, b, .., e] = arr;
| ^^^
error: Min Capture analysis includes: error: Min Capture analysis includes:
--> $DIR/destructure_patterns.rs:13:5 --> $DIR/destructure_patterns.rs:13:5
@ -62,7 +72,7 @@ LL | let [a, b, .., e] = arr;
| ^^^ | ^^^
error: First Pass analysis includes: error: First Pass analysis includes:
--> $DIR/destructure_patterns.rs:39:5 --> $DIR/destructure_patterns.rs:41:5
| |
LL | / || { LL | / || {
LL | | LL | |
@ -74,18 +84,18 @@ LL | | };
| |_____^ | |_____^
| |
note: Capturing p[(0, 0)] -> MutBorrow note: Capturing p[(0, 0)] -> MutBorrow
--> $DIR/destructure_patterns.rs:42:58 --> $DIR/destructure_patterns.rs:44:58
| |
LL | let Point { x: ref mut x, y: _, id: moved_id } = p; LL | let Point { x: ref mut x, y: _, id: moved_id } = p;
| ^ | ^
note: Capturing p[(2, 0)] -> ByValue note: Capturing p[(2, 0)] -> ByValue
--> $DIR/destructure_patterns.rs:42:58 --> $DIR/destructure_patterns.rs:44:58
| |
LL | let Point { x: ref mut x, y: _, id: moved_id } = p; LL | let Point { x: ref mut x, y: _, id: moved_id } = p;
| ^ | ^
error: Min Capture analysis includes: error: Min Capture analysis includes:
--> $DIR/destructure_patterns.rs:39:5 --> $DIR/destructure_patterns.rs:41:5
| |
LL | / || { LL | / || {
LL | | LL | |
@ -97,18 +107,18 @@ LL | | };
| |_____^ | |_____^
| |
note: Min Capture p[(0, 0)] -> MutBorrow note: Min Capture p[(0, 0)] -> MutBorrow
--> $DIR/destructure_patterns.rs:42:58 --> $DIR/destructure_patterns.rs:44:58
| |
LL | let Point { x: ref mut x, y: _, id: moved_id } = p; LL | let Point { x: ref mut x, y: _, id: moved_id } = p;
| ^ | ^
note: Min Capture p[(2, 0)] -> ByValue note: Min Capture p[(2, 0)] -> ByValue
--> $DIR/destructure_patterns.rs:42:58 --> $DIR/destructure_patterns.rs:44:58
| |
LL | let Point { x: ref mut x, y: _, id: moved_id } = p; LL | let Point { x: ref mut x, y: _, id: moved_id } = p;
| ^ | ^
error: First Pass analysis includes: error: First Pass analysis includes:
--> $DIR/destructure_patterns.rs:59:5 --> $DIR/destructure_patterns.rs:61:5
| |
LL | / || { LL | / || {
LL | | LL | |
@ -120,23 +130,23 @@ LL | | };
| |_____^ | |_____^
| |
note: Capturing t[(0, 0)] -> MutBorrow note: Capturing t[(0, 0)] -> MutBorrow
--> $DIR/destructure_patterns.rs:62:54 --> $DIR/destructure_patterns.rs:64:54
| |
LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; LL | let (ref mut x, ref ref_str, (moved_s, _)) = t;
| ^ | ^
note: Capturing t[(1, 0)] -> ImmBorrow note: Capturing t[(1, 0)] -> ImmBorrow
--> $DIR/destructure_patterns.rs:62:54 --> $DIR/destructure_patterns.rs:64:54
| |
LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; LL | let (ref mut x, ref ref_str, (moved_s, _)) = t;
| ^ | ^
note: Capturing t[(2, 0),(0, 0)] -> ByValue note: Capturing t[(2, 0),(0, 0)] -> ByValue
--> $DIR/destructure_patterns.rs:62:54 --> $DIR/destructure_patterns.rs:64:54
| |
LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; LL | let (ref mut x, ref ref_str, (moved_s, _)) = t;
| ^ | ^
error: Min Capture analysis includes: error: Min Capture analysis includes:
--> $DIR/destructure_patterns.rs:59:5 --> $DIR/destructure_patterns.rs:61:5
| |
LL | / || { LL | / || {
LL | | LL | |
@ -148,17 +158,17 @@ LL | | };
| |_____^ | |_____^
| |
note: Min Capture t[(0, 0)] -> MutBorrow note: Min Capture t[(0, 0)] -> MutBorrow
--> $DIR/destructure_patterns.rs:62:54 --> $DIR/destructure_patterns.rs:64:54
| |
LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; LL | let (ref mut x, ref ref_str, (moved_s, _)) = t;
| ^ | ^
note: Min Capture t[(1, 0)] -> ImmBorrow note: Min Capture t[(1, 0)] -> ImmBorrow
--> $DIR/destructure_patterns.rs:62:54 --> $DIR/destructure_patterns.rs:64:54
| |
LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; LL | let (ref mut x, ref ref_str, (moved_s, _)) = t;
| ^ | ^
note: Min Capture t[(2, 0),(0, 0)] -> ByValue note: Min Capture t[(2, 0),(0, 0)] -> ByValue
--> $DIR/destructure_patterns.rs:62:54 --> $DIR/destructure_patterns.rs:64:54
| |
LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; LL | let (ref mut x, ref ref_str, (moved_s, _)) = t;
| ^ | ^

View file

@ -0,0 +1,25 @@
// edition:2021
// Test that we point to the correct location that results a union being captured.
// Union is special because it can't be disjointly captured.
union A {
y: u32,
x: (),
}
fn main() {
let mut a = A { y: 1 };
let mut c = || {
//~^ borrow of `a.y` occurs here
let _ = unsafe { &a.y };
let _ = &mut a;
//~^ borrow occurs due to use in closure
let _ = unsafe { &mut a.y };
};
a.y = 1;
//~^ cannot assign to `a.y` because it is borrowed [E0506]
//~| assignment to borrowed `a.y` occurs here
c();
//~^ borrow later used here
}

View file

@ -0,0 +1,18 @@
error[E0506]: cannot assign to `a.y` because it is borrowed
--> $DIR/union.rs:20:5
|
LL | let mut c = || {
| -- borrow of `a.y` occurs here
...
LL | let _ = &mut a;
| - borrow occurs due to use in closure
...
LL | a.y = 1;
| ^^^^^^^ assignment to borrowed `a.y` occurs here
...
LL | c();
| - borrow later used here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0506`.

View file

@ -40,6 +40,7 @@ fn main() {
//~| NOTE: Min Capture p[(1, 0)] -> MutBorrow //~| NOTE: Min Capture p[(1, 0)] -> MutBorrow
c2(); c2();
println!("{}", p.y); println!("{}", p.y);
//~^ NOTE: Capturing p[(1, 0)] -> ImmBorrow
}; };
c1(); c1();

View file

@ -58,7 +58,7 @@ LL | |
LL | | LL | |
LL | | println!("{}", p.x); LL | | println!("{}", p.x);
... | ... |
LL | | println!("{}", p.y); LL | |
LL | | }; LL | | };
| |_____^ | |_____^
| |
@ -72,6 +72,11 @@ note: Capturing p[(1, 0)] -> MutBorrow
| |
LL | || p.y += incr; LL | || p.y += incr;
| ^^^ | ^^^
note: Capturing p[(1, 0)] -> ImmBorrow
--> $DIR/nested-closure.rs:42:24
|
LL | println!("{}", p.y);
| ^^^
error: Min Capture analysis includes: error: Min Capture analysis includes:
--> $DIR/nested-closure.rs:22:5 --> $DIR/nested-closure.rs:22:5
@ -81,7 +86,7 @@ LL | |
LL | | LL | |
LL | | println!("{}", p.x); LL | | println!("{}", p.x);
... | ... |
LL | | println!("{}", p.y); LL | |
LL | | }; LL | | };
| |_____^ | |_____^
| |

View file

@ -48,6 +48,7 @@ fn test_alignment_affected() {
//~^ ERROR: First Pass analysis includes: //~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes: //~| ERROR: Min Capture analysis includes:
let z1: &String = &foo.x; let z1: &String = &foo.x;
//~^ NOTE: Capturing foo[] -> ImmBorrow
let z2: &mut u16 = &mut foo.y; let z2: &mut u16 = &mut foo.y;
//~^ NOTE: Capturing foo[] -> MutBorrow //~^ NOTE: Capturing foo[] -> MutBorrow
//~| NOTE: Min Capture foo[] -> MutBorrow //~| NOTE: Min Capture foo[] -> MutBorrow

View file

@ -17,7 +17,7 @@ LL | let mut c = #[rustc_capture_analysis]
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental error[E0658]: attributes on expressions are experimental
--> $DIR/repr_packed.rs:78:13 --> $DIR/repr_packed.rs:79:13
| |
LL | let c = #[rustc_capture_analysis] LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -83,8 +83,13 @@ LL | | println!("({}, {})", z1, z2);
LL | | }; LL | | };
| |_____^ | |_____^
| |
note: Capturing foo[] -> ImmBorrow
--> $DIR/repr_packed.rs:50:28
|
LL | let z1: &String = &foo.x;
| ^^^^^
note: Capturing foo[] -> MutBorrow note: Capturing foo[] -> MutBorrow
--> $DIR/repr_packed.rs:51:33 --> $DIR/repr_packed.rs:52:33
| |
LL | let z2: &mut u16 = &mut foo.y; LL | let z2: &mut u16 = &mut foo.y;
| ^^^^^ | ^^^^^
@ -102,13 +107,13 @@ LL | | };
| |_____^ | |_____^
| |
note: Min Capture foo[] -> MutBorrow note: Min Capture foo[] -> MutBorrow
--> $DIR/repr_packed.rs:51:33 --> $DIR/repr_packed.rs:52:33
| |
LL | let z2: &mut u16 = &mut foo.y; LL | let z2: &mut u16 = &mut foo.y;
| ^^^^^ | ^^^^^
error: First Pass analysis includes: error: First Pass analysis includes:
--> $DIR/repr_packed.rs:81:5 --> $DIR/repr_packed.rs:82:5
| |
LL | / || { LL | / || {
LL | | LL | |
@ -120,18 +125,18 @@ LL | | };
| |_____^ | |_____^
| |
note: Capturing foo[] -> ImmBorrow note: Capturing foo[] -> ImmBorrow
--> $DIR/repr_packed.rs:84:24 --> $DIR/repr_packed.rs:85:24
| |
LL | println!("{}", foo.x); LL | println!("{}", foo.x);
| ^^^^^ | ^^^^^
note: Capturing foo[(0, 0)] -> ByValue note: Capturing foo[(0, 0)] -> ByValue
--> $DIR/repr_packed.rs:88:18 --> $DIR/repr_packed.rs:89:18
| |
LL | let _z = foo.x; LL | let _z = foo.x;
| ^^^^^ | ^^^^^
error: Min Capture analysis includes: error: Min Capture analysis includes:
--> $DIR/repr_packed.rs:81:5 --> $DIR/repr_packed.rs:82:5
| |
LL | / || { LL | / || {
LL | | LL | |
@ -143,7 +148,7 @@ LL | | };
| |_____^ | |_____^
| |
note: Min Capture foo[] -> ByValue note: Min Capture foo[] -> ByValue
--> $DIR/repr_packed.rs:84:24 --> $DIR/repr_packed.rs:85:24
| |
LL | println!("{}", foo.x); LL | println!("{}", foo.x);
| ^^^^^ foo[] used here | ^^^^^ foo[] used here