Change:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code: I expected to see this happen: no error Instead, this happened: rustc 1.55.0-nightly 2018 edition rustc 1.55.0-nightly 2021 edition <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
cc
claim

Discussion:
self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow); } } <del> /// Truncate projections so that following rules are obeyed by the captured `place`: </del> <ins> /// Truncate `place` so that an `unsafe` block isn't required to capture it. </ins> /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture ///   them completely. <del> /// - No Index projections are captured, since arrays are captured completely. fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> { </del> <ins> /// - No projections are applied on top of Union ADTs, since these require unsafe blocks. fn restrict_precision_for_unsafe(mut place: Place<'tcx>) -> Place<'tcx> { </ins> if place.projections.is_empty() { // Nothing to do here return place;

return place; } <del> let mut truncated_length = usize::MAX; </del> <ins> if place.base_ty.is_union() { place.projections.truncate(0); return place; } </ins> for (i, proj) in place.projections.iter().enumerate() { if proj.ty.is_unsafe_ptr() { <del> // Don't apply any projections on top of an unsafe ptr truncated_length = truncated_length.min(i + 1); </del> <ins> // Don't apply any projections on top of an unsafe ptr. place.projections.truncate(i + 1); </ins> break; } <ins> if proj.ty.is_union() { // Don't capture preicse fields of a union. place.projections.truncate(i + 1); break; } } place } /// Truncate projections so that following rules are obeyed by the captured `place`: /// - No Index projections are captured, since arrays are captured completely. /// - No unsafe block is required to capture `place` /// Truncate projections so that following rules are obeyed by the captured `place`: fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> { place = restrict_precision_for_unsafe(place); if place.projections.is_empty() { // Nothing to do here return place; } for (i, proj) in place.projections.iter().enumerate() { </ins> match proj.kind { ProjectionKind::Index => { // Arrays are completely captured, so we drop Index projections <del> truncated_length = truncated_length.min(i); </del> <ins> place.projections.truncate(i); </ins> break; } ProjectionKind::Deref => {}

} } <del> let length = place.projections.len().min(truncated_length); place.projections.truncate(length); </del> place }

<ins> #![feature(rustc_attrs)] // edition:2021 // Test that any precise capture on a union is truncated because it's unsafe to do so. union Union { value: u64, } fn main() { let u = Union { value: 42 }; let c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: unsafe { u.value } //~^ NOTE: Capturing u[(0, 0)] -> ImmBorrow //~| NOTE: Min Capture u[] -> ImmBorrow }; c(); } </ins>

<ins> error[E0658]: attributes on expressions are experimental --> $DIR/issue-87378.rs:14:13 | LL |     let c = #[rustc_capture_analysis] |             ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error: First Pass analysis includes: --> $DIR/issue-87378.rs:17:5 | LL | /     || { LL | | LL | | LL | |        unsafe { u.value } LL | | LL | | LL | |     }; | |_____^ | note: Capturing u[(0, 0)] -> ImmBorrow --> $DIR/issue-87378.rs:20:17 | LL |        unsafe { u.value } |                 ^^^^^^^ error: Min Capture analysis includes: --> $DIR/issue-87378.rs:17:5 | LL | /     || { LL | | LL | | LL | |        unsafe { u.value } LL | | LL | | LL | |     }; | |_____^ | note: Min Capture u[] -> ImmBorrow --> $DIR/issue-87378.rs:20:17 | LL |        unsafe { u.value } |                 ^^^^^^^ error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. </ins>

<ins> // edition:2021 // check-pass union Union { value: u64, } fn main() { let u = Union { value: 42 }; let c = || { unsafe { u.value } }; c(); } </ins>