use crate::build::expr::category::{Category, RvalueFunc};
use crate::build::{BlockAnd, BlockAndExtension, Builder};
+use crate::build::expr::as_place::PlaceBase;
use crate::thir::*;
use rustc_middle::middle::region;
use rustc_middle::mir::AssertKind;
this.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) });
- let arg_place = unpack!(block = this.as_place(block, arg));
-
- let mutability = match arg_place.as_ref() {
- PlaceRef { local, projection: &[] } => this.local_decls[local].mutability,
- PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
- debug_assert!(
- this.local_decls[local].is_ref_for_guard(),
- "Unexpected capture place",
- );
- this.local_decls[local].mutability
- }
- PlaceRef {
- local,
- projection: &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _)],
- }
- | PlaceRef {
- local,
- projection:
- &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _), ProjectionElem::Deref],
- } => {
- let place = PlaceRef { local, projection: proj_base };
-
- // Not projected from the implicit `self` in a closure.
- debug_assert!(
- match place.local_or_deref_local() {
- Some(local) => local == Local::new(1),
- None => false,
- },
- "Unexpected capture place"
- );
- // Not in a closure
- debug_assert!(
- this.upvar_mutbls.len() > upvar_index.index(),
- "Unexpected capture place"
- );
- this.upvar_mutbls[upvar_index.index()]
+ let arg_place_builder = unpack!(block = this.as_place_builder(block, arg));
+
+ let mutability = match arg_place_builder.base() {
+ // We are capturing a path that starts off a local variable in the parent.
+ // The mutability of the current capture is same as the mutability
+ // of the local declaration in the parent.
+ PlaceBase::Local(local) => this.local_decls[local].mutability,
+ // Parent is a closure and we are capturing a path that is captured
+ // by the parent itself. The mutability of the current capture
+ // is same as that of the capture in the parent closure.
+ PlaceBase::Upvar { .. } => {
+ let enclosing_upvars_resolved = arg_place_builder.clone().into_place(
+ this.hir.tcx(),
+ this.hir.typeck_results());
+
+ match enclosing_upvars_resolved.as_ref() {
+ PlaceRef { local, projection: &[ProjectionElem::Field(upvar_index, _), ..] }
+ | PlaceRef {
+ local,
+ projection: &[ProjectionElem::Deref, ProjectionElem::Field(upvar_index, _), ..] } => {
+ // Not in a closure
+ debug_assert!(
+ local == Local::new(1),
+ "Expected local to be Local(1), found {:?}",
+ local
+ );
+ // Not in a closure
+ debug_assert!(
+ this.upvar_mutbls.len() > upvar_index.index(),
+ "Unexpected capture place, upvar_mutbls={:#?}, upvar_index={:?}",
+ this.upvar_mutbls, upvar_index
+ );
+ this.upvar_mutbls[upvar_index.index()]
+ }
+ _ => bug!("Unexpected capture place"),
+ }
}
- _ => bug!("Unexpected capture place"),
};
let borrow_kind = match mutability {
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
};
+ let arg_place = arg_place_builder.into_place(
+ this.hir.tcx(),
+ this.hir.typeck_results());
+
this.cfg.push_assign(
block,
source_info,