From c7b4a0857d124556bac4098771d37b3228928599 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Sat, 21 Nov 2020 04:52:18 -0500 Subject: [PATCH 01/20] Writeback min_capture map to TypeckResults - Derive TypeFoldable on `hir::place::Place` and associated structs, to them to be written into typeck results. Co-authored-by: Jennifer Wills Co-authored-by: Logan Mosier --- compiler/rustc_middle/src/hir/place.rs | 43 ++++++++++++-- compiler/rustc_middle/src/ty/mod.rs | 25 +++++--- compiler/rustc_typeck/src/check/writeback.rs | 32 ++++++++++ compiler/rustc_typeck/src/expr_use_visitor.rs | 58 ++----------------- 4 files changed, 94 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 5da4be4e98279..143b3867d9fc7 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -4,7 +4,18 @@ use crate::ty::Ty; use rustc_hir::HirId; use rustc_target::abi::VariantIdx; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + TypeFoldable, + HashStable +)] pub enum PlaceBase { /// A temporary variable Rvalue, @@ -16,7 +27,18 @@ pub enum PlaceBase { Upvar(ty::UpvarId), } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + TypeFoldable, + HashStable +)] pub enum ProjectionKind { /// A dereference of a pointer, reference or `Box` of the given type Deref, @@ -36,7 +58,18 @@ pub enum ProjectionKind { Subslice, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + TypeFoldable, + HashStable +)] pub struct Projection<'tcx> { /// Type after the projection is being applied. pub ty: Ty<'tcx>, @@ -48,7 +81,7 @@ pub struct Projection<'tcx> { /// A `Place` represents how a value is located in memory. /// /// This is an HIR version of `mir::Place` -#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct Place<'tcx> { /// The type of the `PlaceBase` pub base_ty: Ty<'tcx>, @@ -61,7 +94,7 @@ pub struct Place<'tcx> { /// A `PlaceWithHirId` represents how a value is located in memory. /// /// This is an HIR version of `mir::Place` -#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct PlaceWithHirId<'tcx> { /// `HirId` of the expression or pattern producing this value. pub hir_id: HirId, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5d8edcf70bfd3..1a9a6a33fefd4 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -672,7 +672,18 @@ impl<'a, 'tcx> HashStable> for TyS<'tcx> { #[rustc_diagnostic_item = "Ty"] pub type Ty<'tcx> = &'tcx TyS<'tcx>; -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + TypeFoldable, + HashStable +)] pub struct UpvarPath { pub hir_id: hir::HirId, } @@ -680,7 +691,7 @@ pub struct UpvarPath { /// Upvars do not get their own `NodeId`. Instead, we use the pair of /// the original var ID (that is, the root variable that is referenced /// by the upvar) and the ID of the closure expression. -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct UpvarId { pub var_path: UpvarPath, pub closure_expr_id: LocalDefId, @@ -692,7 +703,7 @@ impl UpvarId { } } -#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)] +#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. ImmBorrow, @@ -746,7 +757,7 @@ pub enum BorrowKind { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub enum UpvarCapture<'tcx> { /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases @@ -763,7 +774,7 @@ pub enum UpvarCapture<'tcx> { ByRef(UpvarBorrow<'tcx>), } -#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct UpvarBorrow<'tcx> { /// The kind of borrow: by-ref upvars have access to shared /// immutable borrows, which are not part of the normal language @@ -790,7 +801,7 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap = Vec>; /// A `Place` and the corresponding `CaptureInfo`. -#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct CapturedPlace<'tcx> { pub place: HirPlace<'tcx>, pub info: CaptureInfo<'tcx>, @@ -799,7 +810,7 @@ pub struct CapturedPlace<'tcx> { /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move) /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct CaptureInfo<'tcx> { /// Expr Id pointing to use that resulted in selecting the current capture kind /// diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 68b85a4da34f2..7c9cfe69fc94b 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -55,6 +55,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (), } wbcx.visit_body(body); + wbcx.visit_min_capture_map(); wbcx.visit_upvar_capture_map(); wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); @@ -331,6 +332,37 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { } impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { + fn visit_min_capture_map(&mut self) { + let mut min_captures_wb = ty::MinCaptureInformationMap::with_capacity_and_hasher( + self.fcx.typeck_results.borrow().closure_min_captures.len(), + Default::default(), + ); + for (closure_def_id, root_min_captures) in + self.fcx.typeck_results.borrow().closure_min_captures.iter() + { + let mut root_var_map_wb = ty::RootVariableMinCaptureList::with_capacity_and_hasher( + root_min_captures.len(), + Default::default(), + ); + for (var_hir_id, min_list) in root_min_captures.iter() { + let min_list_wb = min_list + .iter() + .map(|captured_place| { + let locatable = captured_place.info.expr_id.unwrap_or( + self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()), + ); + + self.resolve(captured_place.clone(), &locatable) + }) + .collect(); + root_var_map_wb.insert(*var_hir_id, min_list_wb); + } + min_captures_wb.insert(*closure_def_id, root_var_map_wb); + } + + self.typeck_results.closure_min_captures = min_captures_wb; + } + fn visit_upvar_capture_map(&mut self) { for (upvar_id, upvar_capture) in self.fcx.typeck_results.borrow().upvar_capture_map.iter() { let new_upvar_capture = match *upvar_capture { diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 1b51d5e0182fd..8a324807417da 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -15,7 +15,6 @@ use rustc_index::vec::Idx; use rustc_infer::infer::InferCtxt; use rustc_middle::hir::place::ProjectionKind; use rustc_middle::ty::{self, adjustment, TyCtxt}; -use rustc_span::Span; use rustc_target::abi::VariantIdx; use crate::mem_categorization as mc; @@ -571,38 +570,6 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { })); } - /// Walk closure captures but using `closure_caputes` instead - /// of `closure_min_captures`. - /// - /// This is needed because clippy uses `ExprUseVisitor` after TypeckResults - /// are written back. We don't currently writeback min_captures to - /// TypeckResults. - fn walk_captures_closure_captures(&mut self, closure_expr: &hir::Expr<'_>) { - // FIXME(arora-aman): Remove this function once rust-lang/project-rfc-2229#18 - // is completed. - debug!("walk_captures_closure_captures({:?}), ", closure_expr); - - let closure_def_id = self.tcx().hir().local_def_id(closure_expr.hir_id).to_def_id(); - let cl_span = self.tcx().hir().span(closure_expr.hir_id); - - let captures = &self.mc.typeck_results.closure_captures[&closure_def_id]; - - for (&var_id, &upvar_id) in captures { - let upvar_capture = self.mc.typeck_results.upvar_capture(upvar_id); - let captured_place = - return_if_err!(self.cat_captured_var(closure_expr.hir_id, cl_span, var_id)); - match upvar_capture { - ty::UpvarCapture::ByValue(_) => { - let mode = copy_or_move(&self.mc, &captured_place); - self.delegate.consume(&captured_place, captured_place.hir_id, mode); - } - ty::UpvarCapture::ByRef(upvar_borrow) => { - self.delegate.borrow(&captured_place, captured_place.hir_id, upvar_borrow.kind); - } - } - } - } - /// Handle the case where the current body contains a closure. /// /// When the current body being handled is a closure, then we must make sure that @@ -646,16 +613,18 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let place = &captured_place.place; let capture_info = captured_place.info; - let upvar_id = if body_owner_is_closure { + let place_base = if body_owner_is_closure { // Mark the place to be captured by the enclosing closure - ty::UpvarId::new(*var_hir_id, self.body_owner) + PlaceBase::Upvar(ty::UpvarId::new(*var_hir_id, self.body_owner)) } else { - ty::UpvarId::new(*var_hir_id, closure_def_id.expect_local()) + // If the body owner isn't a closure then the variable must + // be a local variable + PlaceBase::Local(*var_hir_id) }; let place_with_id = PlaceWithHirId::new( capture_info.expr_id.unwrap_or(closure_expr.hir_id), place.base_ty, - PlaceBase::Upvar(upvar_id), + place_base, place.projections.clone(), ); @@ -674,23 +643,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } } - } else if self.mc.typeck_results.closure_captures.contains_key(&closure_def_id) { - // Handle the case where clippy calls ExprUseVisitor after - self.walk_captures_closure_captures(closure_expr) } } - - fn cat_captured_var( - &mut self, - closure_hir_id: hir::HirId, - closure_span: Span, - var_id: hir::HirId, - ) -> mc::McResult> { - // Create the place for the variable being borrowed, from the - // perspective of the creator (parent) of the closure. - let var_ty = self.mc.node_ty(var_id)?; - self.mc.cat_res(closure_hir_id, closure_span, var_ty, Res::Local(var_id)) - } } fn copy_or_move<'a, 'tcx>( From 3c3900b80820f1eb8a382eb6281b62c68eec5437 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Wed, 25 Nov 2020 23:56:55 -0500 Subject: [PATCH 02/20] Use min_captures for creating UpvarSusbts::tupled_upvar_tys - final_upvar_tys now reads types from places instead of using `node_ty` Co-authored-by: Roxane Fruytier --- compiler/rustc_middle/src/ty/context.rs | 13 ++++++++ compiler/rustc_typeck/src/check/upvar.rs | 41 +++++++++++------------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1b3416e112ba9..a8d007c0be27d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -624,6 +624,19 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments } } + /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured + /// by the closure. + pub fn closure_min_captures_flattened( + &self, + closure_def_id: DefId, + ) -> impl Iterator> { + self.closure_min_captures + .get(&closure_def_id) + .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter())) + .into_iter() + .flatten() + } + pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { self.upvar_capture_map[&upvar_id] } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 019fa78fb1e0e..30b4682296c6a 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // inference algorithm will reject it). // Equate the type variables for the upvars with the actual types. - let final_upvar_tys = self.final_upvar_tys(closure_hir_id); + let final_upvar_tys = self.final_upvar_tys(closure_def_id); debug!( "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}", closure_hir_id, substs, final_upvar_tys @@ -222,36 +222,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Returns a list of `Ty`s for each upvar. - fn final_upvar_tys(&self, closure_id: hir::HirId) -> Vec> { + fn final_upvar_tys(&self, closure_id: DefId) -> Vec> { // Presently an unboxed closure type cannot "escape" out of a // function, so we will only encounter ones that originated in the // local crate or were inlined into it along with some function. // This may change if abstract return types of some sort are // implemented. let tcx = self.tcx; - let closure_def_id = tcx.hir().local_def_id(closure_id); self.typeck_results .borrow() - .closure_captures - .get(&closure_def_id.to_def_id()) - .iter() - .flat_map(|upvars| { - upvars.iter().map(|(&var_hir_id, _)| { - let upvar_ty = self.node_ty(var_hir_id); - let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id); - let capture = self.typeck_results.borrow().upvar_capture(upvar_id); - - debug!("var_id={:?} upvar_ty={:?} capture={:?}", var_hir_id, upvar_ty, capture); - - match capture { - ty::UpvarCapture::ByValue(_) => upvar_ty, - ty::UpvarCapture::ByRef(borrow) => tcx.mk_ref( - borrow.region, - ty::TypeAndMut { ty: upvar_ty, mutbl: borrow.kind.to_mutbl_lossy() }, - ), - } - }) + .closure_min_captures_flattened(closure_id) + .map(|captured_place| { + let upvar_ty = captured_place.place.ty(); + let capture = captured_place.info.capture_kind; + + debug!( + "place={:?} upvar_ty={:?} capture={:?}", + captured_place.place, upvar_ty, capture + ); + + match capture { + ty::UpvarCapture::ByValue(_) => upvar_ty, + ty::UpvarCapture::ByRef(borrow) => tcx.mk_ref( + borrow.region, + ty::TypeAndMut { ty: upvar_ty, mutbl: borrow.kind.to_mutbl_lossy() }, + ), + } }) .collect() } From b57d7e603724b3f021bfb9a4062f3186c1b00938 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Wed, 18 Nov 2020 22:54:31 -0500 Subject: [PATCH 03/20] Move handling UpvarRef to PlaceBuilder - This allows us to delay figuring out the index of a capture in the closure structure when all projections to atleast form a capture have been applied to the builder Co-authored-by: Roxane Fruytier --- .../src/build/expr/as_place.rs | 288 +++++++++++++----- 1 file changed, 210 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index e6263e5d6cf9b..a968c0bdc4146 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -4,6 +4,8 @@ use crate::build::expr::category::Category; use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::thir::*; +use rustc_hir::def_id::DefId; +use rustc_hir::HirId; use rustc_middle::middle::region; use rustc_middle::mir::AssertKind::BoundsCheck; use rustc_middle::mir::*; @@ -12,6 +14,50 @@ use rustc_span::Span; use rustc_index::vec::Idx; +/// The "outermost" place that holds this value. +#[derive(Copy, Clone)] +pub enum PlaceBase { + /// Denotes the start of a `Place`. + Local(Local), + + /// When building place for an expression within a closure, the place might start off a + /// captured path. When `capture_disjoint_fields` is enabled, we might not know the capture + /// index (within the desugared closure) of the captured path until most of the projections + /// are applied. We use `PlaceBase::Upvar` to keep track of the root variable off of which the + /// captured path starts, the closure the capture belongs to and the trait the closure + /// implements. + /// + /// Once we have figured out the capture index, we can convert the place builder to start from + /// `PlaceBase::Local`. + /// + /// Consider the following example + /// ```rust + /// let t = (10, (10, (10, 10))); + /// + /// let c = || { + /// println!("{}", t.0.0.0); + /// }; + /// ``` + /// Here the THIR expression for `t.0.0.0` will be something like + /// + /// ``` + /// * Field(0) + /// * Field(0) + /// * Field(0) + /// * UpvarRef(t) + /// ``` + /// + /// When `capture_disjoint_fields` is enabled, `t.0.0` is captured and we won't be able to + /// figure out what is captured until all the `Field` projections are applied. + Upvar { + /// HirId of the upvar + var_hir_id: HirId, + /// DefId of the closure + closure_def_id: DefId, + /// The trait closure implements, `Fn`, `FnMut`, `FnOnce` + closure_kind: ty::ClosureKind }, +} + /// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a /// place by pushing more and more projections onto the end, and then convert the final set into a /// place using the `into_place` method. @@ -20,13 +66,134 @@ use rustc_index::vec::Idx; /// and `c` can be progressively pushed onto the place builder that is created when converting `a`. #[derive(Clone)] struct PlaceBuilder<'tcx> { - local: Local, + base: PlaceBase, projection: Vec>, } +fn capture_matching_projections<'a, 'tcx>( + tcx: TyCtxt<'tcx>, + typeck_results: &'a ty::TypeckResults<'tcx>, + var_hir_id: HirId, + closure_def_id: DefId, + _projections: &Vec>, +) -> Option<(usize, Ty<'tcx>, ty::UpvarCapture<'tcx>)> { + let capture = typeck_results + .closure_captures + .get(&closure_def_id) + .and_then(|captures| captures.get_full(&var_hir_id)); + + let (capture_index, _, _) = if let Some(capture) = capture { + capture + } else { + return None; + }; + + let closure_ty = + typeck_results.node_type(tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local())); + + let substs = match closure_ty.kind() { + ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), + ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs), + _ => bug!("Lowering capture for non-closure type {:?}", closure_ty), + }; + + // Access the capture by accessing the field within the Closure struct. + // + // We must have inferred the capture types since we are building MIR, therefore + // it's safe to call `upvar_tys` and we can unwrap here because + // we know that the capture exists and is the `capture_index`-th capture. + let var_ty = substs.upvar_tys().nth(capture_index).unwrap(); + + let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id.expect_local()); + let capture_kind = typeck_results.upvar_capture(upvar_id); + + Some((capture_index, var_ty, capture_kind)) +} + +/// Takes a PlaceBuilder and resolves the upvar (if any) within it, +/// so that the PlaceBuilder now starts from PlaceBase::Local. +/// +/// Returns a Result with the error being the HirId of the +/// Upvar that was not found. +fn to_upvars_resolved_place_builder<'a, 'tcx>( + from_builder: PlaceBuilder<'tcx>, + tcx: TyCtxt<'tcx>, + typeck_results: &'a ty::TypeckResults<'tcx>, +) -> Result, HirId> { + match from_builder.base { + PlaceBase::Local(_) => Ok(from_builder), + PlaceBase::Upvar { var_hir_id, closure_def_id, closure_kind } => { + // Captures are represented using fields inside a structure. + // This represents accessing self in the closure structure + let mut upvar_resolved_place_builder = PlaceBuilder::from(Local::new(1)); + match closure_kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { + upvar_resolved_place_builder = upvar_resolved_place_builder.deref(); + } + ty::ClosureKind::FnOnce => {} + } + + let (capture_index, var_ty, capture_kind) = + if let Some(capture_details) = capture_matching_projections( + tcx, + typeck_results, + var_hir_id, + closure_def_id, + &from_builder.projection, + ) { + capture_details + } else { + if !tcx.features().capture_disjoint_fields { + bug!( + "No associated capture found for {:?}[{:#?}] even though \ + capture_disjoint_fields isn't enabled", + var_hir_id, + from_builder.projection + ) + } + return Err(var_hir_id); + }; + + upvar_resolved_place_builder = upvar_resolved_place_builder.field( + Field::new(capture_index), + var_ty); + + // If the variable is captured via ByRef(Immutable/Mutable) Borrow, + // we need to deref it + upvar_resolved_place_builder = match capture_kind { + ty::UpvarCapture::ByRef(_) => upvar_resolved_place_builder.deref(), + ty::UpvarCapture::ByValue(_) => upvar_resolved_place_builder, + }; + + let next_projection = 0; + let mut curr_projections = from_builder.projection; + upvar_resolved_place_builder.projection.extend( + curr_projections.drain(next_projection..)); + + Ok(upvar_resolved_place_builder) + } + } +} + impl<'tcx> PlaceBuilder<'tcx> { - fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> { - Place { local: self.local, projection: tcx.intern_place_elems(&self.projection) } + fn into_place<'a>( + self, + tcx: TyCtxt<'tcx>, + typeck_results: &'a ty::TypeckResults<'tcx>, + ) -> Place<'tcx> { + if let PlaceBase::Local(local) = self.base { + Place { local, projection: tcx.intern_place_elems(&self.projection) } + } else { + self.expect_upvars_resolved(tcx, typeck_results).into_place(tcx, typeck_results) + } + } + + fn expect_upvars_resolved<'a>( + self, + tcx: TyCtxt<'tcx>, + typeck_results: &'a ty::TypeckResults<'tcx>, + ) -> PlaceBuilder<'tcx> { + to_upvars_resolved_place_builder(self, tcx, typeck_results).unwrap() } fn field(self, f: Field, ty: Ty<'tcx>) -> Self { @@ -49,7 +216,13 @@ impl<'tcx> PlaceBuilder<'tcx> { impl<'tcx> From for PlaceBuilder<'tcx> { fn from(local: Local) -> Self { - Self { local, projection: Vec::new() } + Self { base: PlaceBase::Local(local), projection: Vec::new() } + } +} + +impl<'tcx> From for PlaceBuilder<'tcx> { + fn from(base: PlaceBase) -> Self { + Self { base, projection: Vec::new() } } } @@ -71,7 +244,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { M: Mirror<'tcx, Output = Expr<'tcx>>, { let place_builder = unpack!(block = self.as_place_builder(block, expr)); - block.and(place_builder.into_place(self.hir.tcx())) + block.and(place_builder.into_place(self.hir.tcx(), self.hir.typeck_results())) } /// This is used when constructing a compound `Place`, so that we can avoid creating @@ -98,7 +271,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { M: Mirror<'tcx, Output = Expr<'tcx>>, { let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); - block.and(place_builder.into_place(self.hir.tcx())) + block.and(place_builder.into_place(self.hir.tcx(), self.hir.typeck_results())) } /// This is used when constructing a compound `Place`, so that we can avoid creating @@ -161,27 +334,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, ), ExprKind::UpvarRef { closure_def_id, var_hir_id } => { - let capture = this - .hir - .typeck_results - .closure_captures - .get(&closure_def_id) - .and_then(|captures| captures.get_full(&var_hir_id)); - - if capture.is_none() { - if !this.hir.tcx().features().capture_disjoint_fields { - bug!( - "No associated capture found for {:?} even though \ - capture_disjoint_fields isn't enabled", - expr.kind - ) - } - // FIXME(project-rfc-2229#24): Handle this case properly - } - - // Unwrap until the FIXME has been resolved - let (capture_index, _, upvar_id) = capture.unwrap(); - this.lower_closure_capture(block, capture_index, *upvar_id) + let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id.expect_local()); + this.lower_captured_upvar(block, upvar_id) } ExprKind::VarRef { id } => { @@ -208,7 +362,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { inferred_ty: expr.ty, }); - let place = place_builder.clone().into_place(this.hir.tcx()); + let place = + place_builder.clone().into_place(this.hir.tcx(), this.hir.typeck_results()); this.cfg.push( block, Statement { @@ -293,59 +448,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - /// Lower a closure/generator capture by representing it as a field - /// access within the desugared closure/generator. - /// - /// `capture_index` is the index of the capture within the desugared - /// closure/generator. - fn lower_closure_capture( + /// Lower a captured upvar. Note we might not know the actual capture index, + /// so we create a place starting from `PlaceBase::Upvar`, which will be resolved + /// once all projections that allow us to indentify a capture have been applied. + fn lower_captured_upvar( &mut self, block: BasicBlock, - capture_index: usize, upvar_id: ty::UpvarId, - ) -> BlockAnd> { + ) -> BlockAnd> { let closure_ty = self .hir .typeck_results() .node_type(self.hir.tcx().hir().local_def_id_to_hir_id(upvar_id.closure_expr_id)); - // Captures are represented using fields inside a structure. - // This represents accessing self in the closure structure - let mut place_builder = PlaceBuilder::from(Local::new(1)); - - // In case of Fn/FnMut closures we must deref to access the fields - // Generators are considered FnOnce, so we ignore this step for them. - if let ty::Closure(_, closure_substs) = closure_ty.kind() { - match self.hir.infcx().closure_kind(closure_substs).unwrap() { - ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { - place_builder = place_builder.deref(); - } - ty::ClosureKind::FnOnce => {} - } - } - - let substs = match closure_ty.kind() { - ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), - ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs), - _ => bug!("Lowering capture for non-closure type {:?}", closure_ty) + let closure_kind = if let ty::Closure(_, closure_substs) = closure_ty.kind() { + self.hir.infcx().closure_kind(closure_substs).unwrap() + } else { + // Generators are considered FnOnce. + ty::ClosureKind::FnOnce }; - // Access the capture by accessing the field within the Closure struct. - // - // We must have inferred the capture types since we are building MIR, therefore - // it's safe to call `upvar_tys` and we can unwrap here because - // we know that the capture exists and is the `capture_index`-th capture. - let var_ty = substs.upvar_tys().nth(capture_index).unwrap(); - place_builder = place_builder.field(Field::new(capture_index), var_ty); - - // If the variable is captured via ByRef(Immutable/Mutable) Borrow, - // we need to deref it - match self.hir.typeck_results.upvar_capture(upvar_id) { - ty::UpvarCapture::ByRef(_) => { - block.and(place_builder.deref()) - } - ty::UpvarCapture::ByValue(_) => block.and(place_builder), - } + block.and(PlaceBuilder::from(PlaceBase::Upvar { + var_hir_id: upvar_id.var_path.hir_id, + closure_def_id: upvar_id.closure_expr_id.to_def_id(), + closure_kind, + })) } /// Lower an index expression @@ -373,7 +500,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let is_outermost_index = fake_borrow_temps.is_none(); let fake_borrow_temps = fake_borrow_temps.unwrap_or(base_fake_borrow_temps); - let base_place = + let mut base_place = unpack!(block = self.expr_as_place(block, lhs, mutability, Some(fake_borrow_temps),)); // Making this a *fresh* temporary means we do not have to worry about @@ -383,7 +510,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block = self.bounds_check( block, - base_place.clone().into_place(self.hir.tcx()), + base_place.clone().into_place(self.hir.tcx(), self.hir.typeck_results()), idx, expr_span, source_info, @@ -392,6 +519,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if is_outermost_index { self.read_fake_borrows(block, fake_borrow_temps, source_info) } else { + base_place = base_place.expect_upvars_resolved(self.hir.tcx(), self.hir.typeck_results()); self.add_fake_borrows_of_base( &base_place, block, @@ -441,8 +569,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info: SourceInfo, ) { let tcx = self.hir.tcx(); - let place_ty = - Place::ty_from(base_place.local, &base_place.projection, &self.local_decls, tcx); + let local = match base_place.base { + PlaceBase::Local(local) => local, + PlaceBase::Upvar { .. } => bug!("Expected PlacseBase::Local found Upvar") + }; + + let place_ty = Place::ty_from(local, &base_place.projection, &self.local_decls, tcx); if let ty::Slice(_) = place_ty.ty.kind() { // We need to create fake borrows to ensure that the bounds // check that we just did stays valid. Since we can't assign to @@ -452,7 +584,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match elem { ProjectionElem::Deref => { let fake_borrow_deref_ty = Place::ty_from( - base_place.local, + local, &base_place.projection[..idx], &self.local_decls, tcx, @@ -470,14 +602,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Rvalue::Ref( tcx.lifetimes.re_erased, BorrowKind::Shallow, - Place { local: base_place.local, projection }, + Place { local, projection }, ), ); fake_borrow_temps.push(fake_borrow_temp); } ProjectionElem::Index(_) => { let index_ty = Place::ty_from( - base_place.local, + local, &base_place.projection[..idx], &self.local_decls, tcx, From 5e2bbb4d785cc279f59710e9c5e5988d09fe0b83 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Thu, 26 Nov 2020 00:05:18 -0500 Subject: [PATCH 04/20] Use Places for captures in MIR - Use closure_min_capture maps to capture precise paths - PlaceBuilder now searches for ancestors in min_capture list - Add API to `Ty` to allow access to the n-th element in a tuple in O(1) time. Co-authored-by: Roxane Fruytier --- compiler/rustc_middle/src/ty/sty.rs | 9 + .../src/build/expr/as_place.rs | 195 ++++++++++++++---- 2 files changed, 163 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 78994c6e1c77a..4fc8f4a4005e5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2174,6 +2174,15 @@ impl<'tcx> TyS<'tcx> { } } + /// Get the `i`-th element of a tuple. + /// Panics when called on anything but a tuple. + pub fn tuple_get_field(&self, i: usize) -> Option> { + match self.kind() { + Tuple(substs) => substs.iter().nth(i).map(|field| field.expect_ty()), + _ => bug!("tuple_fields called on non-tuple"), + } + } + /// If the type contains variants, returns the valid range of variant indices. // // FIXME: This requires the optimized MIR in the case of generators. diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index a968c0bdc4146..c30eeb30113b4 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -7,10 +7,12 @@ use crate::thir::*; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_middle::middle::region; +use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::mir::AssertKind::BoundsCheck; use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance}; use rustc_span::Span; +use rustc_target::abi::VariantIdx; use rustc_index::vec::Idx; @@ -70,51 +72,148 @@ struct PlaceBuilder<'tcx> { projection: Vec>, } -fn capture_matching_projections<'a, 'tcx>( - tcx: TyCtxt<'tcx>, +/// Given a list of MIR projections, convert them to list of hir ProjectionKind. +fn convert_to_hir_projections_for_capture<'tcx>( + mir_projections: &Vec>) -> Vec { + + let mut hir_projections = Vec::new(); + + for mir_projection in mir_projections { + let hir_projection = match mir_projection { + ProjectionElem::Deref => HirProjectionKind::Deref, + ProjectionElem::Field(field, _) => { + // We will never encouter this for multivariant enums, + // read the comment for `Downcast`. + HirProjectionKind::Field(field.index() as u32, VariantIdx::new(0)) + }, + ProjectionElem::Downcast(..) => { + // This projections exist only for enums that have + // multiple variants. Since such enums that are captured + // completely, we can stop here. + break + }, + ProjectionElem::Index(..) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } => { + // We don't capture array-access projections. + // We can stop here as arrays are captured completely. + break + }, + }; + + hir_projections.push(hir_projection); + } + + hir_projections +} + +/// Return true if the `proj_possible_ancestor` represents an ancestor path +/// to `proj_capture`, assuming they both start off of the same root variable. +/// +/// Eg: `foo.x` which is represented using `projections=[Field(x)]` is an ancestor of +/// `foo.x.y` which is represented using `prjections=[Field(x), Field(y)]`. +/// Note both `foo.x` and `foo.x.y` start off of the same root variable `foo`. +fn is_ancestor_of_capture( + proj_possible_ancestor: &Vec, + proj_capture: &Vec) -> bool { + + for (proj_ans, proj_capture) in proj_possible_ancestor.iter().zip(proj_capture.iter()) { + if proj_ans != proj_capture { + return false; + } + } + + // In cases like + // ```rust,ignore(wont-compile-because-pseudocode) + // let c = || { + // x.0.1 += 1; + // let _ = x.0; + // } + // ``` + // + // Here with `capture_disjoint_fields` enabled, x.0 won't be + // captured but x.0.1 would be. + // + // Therefore we can't just return true here. + proj_possible_ancestor.len() <= proj_capture.len() +} + +/// Computes the index of a capture within the desugared closure provided the closure's +/// `closure_min_captures` and the capture's index of the capture in the +/// `ty::MinCaptureList` of the root variable `var_hir_id`. +fn compute_capture_idx<'tcx>( + closure_min_captures: &ty::RootVariableMinCaptureList<'tcx>, + var_hir_id: HirId, + root_var_idx: usize) -> usize { + let mut res = 0; + for (var_id, capture_list) in closure_min_captures { + if *var_id == var_hir_id { + res += root_var_idx; + break; + } else { + res += capture_list.len(); + } + } + + res +} + +/// Given a closure, returns the index of a capture within the desugared closure struct and the +/// `ty::CapturedPlace` which is the ancestor of the Place represented using the `var_hir_id` +/// and `projection`. +/// +/// Note there will be atmost one ancestor for any given Place. +/// +/// Returns None, when the ancestor is not found. +fn find_capture_matching_projections<'a, 'tcx>( typeck_results: &'a ty::TypeckResults<'tcx>, var_hir_id: HirId, closure_def_id: DefId, - _projections: &Vec>, -) -> Option<(usize, Ty<'tcx>, ty::UpvarCapture<'tcx>)> { - let capture = typeck_results - .closure_captures - .get(&closure_def_id) - .and_then(|captures| captures.get_full(&var_hir_id)); - - let (capture_index, _, _) = if let Some(capture) = capture { - capture + projections: &Vec>, +) -> Option<(usize, &'a ty::CapturedPlace<'tcx>)> { + let closure_min_captures = typeck_results + .closure_min_captures + .get(&closure_def_id); + + let closure_min_captures = if let Some(min_captures) = closure_min_captures { + min_captures } else { return None; }; - let closure_ty = - typeck_results.node_type(tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local())); - - let substs = match closure_ty.kind() { - ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), - ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs), - _ => bug!("Lowering capture for non-closure type {:?}", closure_ty), + let root_variable_min_captures = + if let Some(captures) = closure_min_captures.get(&var_hir_id) { + captures + } else { + return None; }; - // Access the capture by accessing the field within the Closure struct. - // - // We must have inferred the capture types since we are building MIR, therefore - // it's safe to call `upvar_tys` and we can unwrap here because - // we know that the capture exists and is the `capture_index`-th capture. - let var_ty = substs.upvar_tys().nth(capture_index).unwrap(); + let hir_projections = convert_to_hir_projections_for_capture(projections); - let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id.expect_local()); - let capture_kind = typeck_results.upvar_capture(upvar_id); + // If an ancestor is found, returns the index within the list of captured places + // for root variable `var_hir_id` and the `ty::CapturedPlace` itself. + let find_ancestor = || { + for (i, capture) in root_variable_min_captures.iter().enumerate() { + let possible_ancestor_proj_kinds = + capture.place.projections.iter().map(|proj| proj.kind).collect(); + if is_ancestor_of_capture(&possible_ancestor_proj_kinds, &hir_projections) { + return Some((i, capture)); + } + } + return None; + }; - Some((capture_index, var_ty, capture_kind)) + // Convert index to be from the presepective of the entire closure_min_captures map + // instead of just the root variable capture list + find_ancestor() + .and_then(|(idx, capture)| + Some((compute_capture_idx(closure_min_captures, var_hir_id, idx), capture))) } -/// Takes a PlaceBuilder and resolves the upvar (if any) within it, -/// so that the PlaceBuilder now starts from PlaceBase::Local. +/// Takes a PlaceBuilder and resolves the upvar (if any) within it, so that the +/// `PlaceBuilder` now starts from `PlaceBase::Local`. /// -/// Returns a Result with the error being the HirId of the -/// Upvar that was not found. +/// Returns a Result with the error being the HirId of the Upvar that was not found. fn to_upvars_resolved_place_builder<'a, 'tcx>( from_builder: PlaceBuilder<'tcx>, tcx: TyCtxt<'tcx>, @@ -133,9 +232,8 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( ty::ClosureKind::FnOnce => {} } - let (capture_index, var_ty, capture_kind) = - if let Some(capture_details) = capture_matching_projections( - tcx, + let (capture_index, capture) = + if let Some(capture_details) = find_capture_matching_projections( typeck_results, var_hir_id, closure_def_id, @@ -150,23 +248,38 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( var_hir_id, from_builder.projection ) + } else { + // FIXME(project-rfc-2229#24): Handle this case properly + debug!( + "No associated capture found for {:?}[{:#?}]", + var_hir_id, + from_builder.projection, + ) } return Err(var_hir_id); }; - upvar_resolved_place_builder = upvar_resolved_place_builder.field( - Field::new(capture_index), - var_ty); + let closure_ty = typeck_results + .node_type(tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local())); + let substs = match closure_ty.kind() { + ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), + ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs), + _ => bug!("Lowering capture for non-closure type {:?}", closure_ty) + }; + + let var_ty = substs.tupled_upvars_ty().tuple_get_field(capture_index).unwrap(); + upvar_resolved_place_builder = upvar_resolved_place_builder.field(Field::new(capture_index), var_ty); - // If the variable is captured via ByRef(Immutable/Mutable) Borrow, - // we need to deref it - upvar_resolved_place_builder = match capture_kind { + upvar_resolved_place_builder = match capture.info.capture_kind { ty::UpvarCapture::ByRef(_) => upvar_resolved_place_builder.deref(), ty::UpvarCapture::ByValue(_) => upvar_resolved_place_builder, }; - let next_projection = 0; + let next_projection = capture.place.projections.len(); let mut curr_projections = from_builder.projection; + + // We used some of the projections to build the capture itself, + // now we apply the remaining to the upvar resolved place. upvar_resolved_place_builder.projection.extend( curr_projections.drain(next_projection..)); From a1122f823d38e6259f92d6cfe3754ccbc00b5c4a Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Thu, 26 Nov 2020 00:07:41 -0500 Subject: [PATCH 05/20] Use precise places when lowering Closures in THIR - Closures now use closure_min_captures to figure out captured paths - Build upvar_mutbls using closure_min_captures - Change logic in limit_capture_mutability to differentiate b/w capturing parent's local variable or capturing a variable that is captured by the parent (in case of nested closure) using PlaceBase. Co-authored-by: Roxane Fruytier --- .../src/build/expr/as_place.rs | 12 ++- .../src/build/expr/as_rvalue.rs | 75 ++++++++++--------- compiler/rustc_mir_build/src/build/mod.rs | 22 ++++-- compiler/rustc_mir_build/src/thir/cx/expr.rs | 55 ++++++++++---- 4 files changed, 101 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index c30eeb30113b4..13eb6bd004224 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -18,7 +18,7 @@ use rustc_index::vec::Idx; /// The "outermost" place that holds this value. #[derive(Copy, Clone)] -pub enum PlaceBase { +crate enum PlaceBase { /// Denotes the start of a `Place`. Local(Local), @@ -67,7 +67,7 @@ pub enum PlaceBase { /// This is used internally when building a place for an expression like `a.b.c`. The fields `b` /// and `c` can be progressively pushed onto the place builder that is created when converting `a`. #[derive(Clone)] -struct PlaceBuilder<'tcx> { +crate struct PlaceBuilder<'tcx> { base: PlaceBase, projection: Vec>, } @@ -289,7 +289,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( } impl<'tcx> PlaceBuilder<'tcx> { - fn into_place<'a>( + crate fn into_place<'a>( self, tcx: TyCtxt<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, @@ -309,6 +309,10 @@ impl<'tcx> PlaceBuilder<'tcx> { to_upvars_resolved_place_builder(self, tcx, typeck_results).unwrap() } + crate fn base(&self) -> PlaceBase { + self.base + } + fn field(self, f: Field, ty: Ty<'tcx>) -> Self { self.project(PlaceElem::Field(f, ty)) } @@ -362,7 +366,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// This is used when constructing a compound `Place`, so that we can avoid creating /// intermediate `Place` values until we know the full set of projections. - fn as_place_builder(&mut self, block: BasicBlock, expr: M) -> BlockAnd> + crate fn as_place_builder(&mut self, block: BasicBlock, expr: M) -> BlockAnd> where M: Mirror<'tcx, Output = Expr<'tcx>>, { diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index c0e4141a558d9..d65e0789a3e4d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -4,6 +4,7 @@ use rustc_index::vec::Idx; 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; @@ -393,44 +394,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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() { + // Capture parent's local variable + PlaceBase::Local(local) => this.local_decls[local].mutability, + // Parent is a closure and we capturing a variable that is captured + // by the parent itself. + 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 { @@ -438,6 +435,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 34ef4ed78fd01..d7fce15d99669 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{GeneratorKind, HirIdMap, Node}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::TyCtxtInferExt; +use rustc_middle::hir::place::PlaceBase as HirPlaceBase; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::ty::subst::Subst; @@ -823,7 +824,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // with the closure's DefId. Here, we run through that vec of UpvarIds for // the given closure and use the necessary information to create upvar // debuginfo and to fill `self.upvar_mutbls`. - if let Some(upvars) = hir_typeck_results.closure_captures.get(&fn_def_id) { + if hir_typeck_results.closure_min_captures.get(&fn_def_id).is_some() { let closure_env_arg = Local::new(1); let mut closure_env_projs = vec![]; let mut closure_ty = self.local_decls[closure_env_arg].ty; @@ -836,14 +837,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs), _ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty), }; - let upvar_tys = upvar_substs.upvar_tys(); - let upvars_with_tys = upvars.iter().zip(upvar_tys); - self.upvar_mutbls = upvars_with_tys + let capture_tys = upvar_substs.upvar_tys(); + let captures_with_tys = hir_typeck_results + .closure_min_captures_flattened(fn_def_id) + .zip(capture_tys); + + self.upvar_mutbls = captures_with_tys .enumerate() - .map(|(i, ((&var_id, &upvar_id), ty))| { - let capture = hir_typeck_results.upvar_capture(upvar_id); + .map(|(i, (captured_place, ty))| { + let capture = captured_place.info.capture_kind; + let var_id = match captured_place.place.base { + HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, + _ => bug!("Expected an upvar") + }; let mut mutability = Mutability::Not; + + // FIXME(project-rfc-2229#8): Store more precise information let mut name = kw::Invalid; if let Some(Node::Binding(pat)) = tcx_hir.find(var_id) { if let hir::PatKind::Binding(_, _, ident, _) = pat.kind { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index e404afeb698a6..e1fbd46e95747 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -6,6 +6,8 @@ use crate::thir::*; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_index::vec::Idx; +use rustc_middle::hir::place::PlaceBase as HirPlaceBase; +use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::BorrowKind; use rustc_middle::ty::adjustment::{ @@ -386,14 +388,12 @@ fn make_mirror_unadjusted<'a, 'tcx>( span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); } }; + let upvars = cx .typeck_results() - .closure_captures - .get(&def_id) - .iter() - .flat_map(|upvars| upvars.iter()) + .closure_min_captures_flattened(def_id) .zip(substs.upvar_tys()) - .map(|((&var_hir_id, _), ty)| capture_upvar(cx, expr, var_hir_id, ty)) + .map(|(captured_place, ty)| capture_upvar(cx, expr, captured_place, ty)) .collect(); ExprKind::Closure { closure_id: def_id, substs, upvars, movability } } @@ -981,27 +981,50 @@ fn overloaded_place<'a, 'tcx>( ExprKind::Deref { arg: ref_expr.to_ref() } } -fn capture_upvar<'tcx>( +fn capture_upvar<'a, 'tcx>( cx: &mut Cx<'_, 'tcx>, closure_expr: &'tcx hir::Expr<'tcx>, - var_hir_id: hir::HirId, + captured_place: &'a ty::CapturedPlace<'tcx>, upvar_ty: Ty<'tcx>, ) -> ExprRef<'tcx> { - let upvar_id = ty::UpvarId { - var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id), - }; - let upvar_capture = cx.typeck_results().upvar_capture(upvar_id); + let upvar_capture = captured_place.info.capture_kind; let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); - let var_ty = cx.typeck_results().node_type(var_hir_id); - let captured_var = Expr { + let var_ty = captured_place.place.base_ty; + + let var_hir_id = match captured_place.place.base { + HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, + base => bug!("Expected an upvar, found {:?}", base), + }; + + let mut captured_place_expr = Expr { temp_lifetime, ty: var_ty, span: closure_expr.span, kind: convert_var(cx, var_hir_id), }; + + for proj in captured_place.place.projections.iter() { + let kind = match proj.kind { + HirProjectionKind::Deref => ExprKind::Deref { arg: captured_place_expr.to_ref() }, + HirProjectionKind::Field(field, ..) => { + // Variant index will always be 0, because for multi-variant + // enums, we capture the enum entirely. + ExprKind::Field { + lhs: captured_place_expr.to_ref(), + name: Field::new(field as usize), + } + } + HirProjectionKind::Index | HirProjectionKind::Subslice => { + // We don't capture these projections, so we can ignore them here + continue; + } + }; + + captured_place_expr = Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind }; + } + match upvar_capture { - ty::UpvarCapture::ByValue(_) => captured_var.to_ref(), + ty::UpvarCapture::ByValue(_) => captured_place_expr.to_ref(), ty::UpvarCapture::ByRef(upvar_borrow) => { let borrow_kind = match upvar_borrow.kind { ty::BorrowKind::ImmBorrow => BorrowKind::Shared, @@ -1012,7 +1035,7 @@ fn capture_upvar<'tcx>( temp_lifetime, ty: upvar_ty, span: closure_expr.span, - kind: ExprKind::Borrow { borrow_kind, arg: captured_var.to_ref() }, + kind: ExprKind::Borrow { borrow_kind, arg: captured_place_expr.to_ref() }, } .to_ref() } From 4308846c9877afabfd3b0afd61487b1d71efac1a Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Wed, 25 Nov 2020 18:48:26 -0500 Subject: [PATCH 06/20] Use closure_min_captures in borrow checker - Use closure_min_captures to generate the Upvar structure that stores information for diagnostics and information about mutability of captures. --- compiler/rustc_mir/src/borrow_check/mod.rs | 16 +++++++++------- .../rustc_mir/src/borrow_check/type_check/mod.rs | 6 +++++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index de54c5582e049..80eabdd9af830 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -9,6 +9,7 @@ use rustc_hir::{HirId, Node}; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_middle::hir::place::PlaceBase as HirPlaceBase; use rustc_middle::mir::{ traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem, PlaceRef, @@ -75,6 +76,7 @@ crate use region_infer::RegionInferenceContext; crate struct Upvar { name: Symbol, + // FIXME(project-rfc-2229#8): This should use Place or something similar var_hir_id: HirId, /// If true, the capture is behind a reference. @@ -155,13 +157,13 @@ fn do_mir_borrowck<'a, 'tcx>( infcx.set_tainted_by_errors(); } let upvars: Vec<_> = tables - .closure_captures - .get(&def.did.to_def_id()) - .into_iter() - .flat_map(|v| v.values()) - .map(|upvar_id| { - let var_hir_id = upvar_id.var_path.hir_id; - let capture = tables.upvar_capture(*upvar_id); + .closure_min_captures_flattened(def.did.to_def_id()) + .map(|captured_place| { + let var_hir_id = match captured_place.place.base { + HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, + _ => bug!("Expected upvar"), + }; + let capture = captured_place.info.capture_kind; let by_ref = match capture { ty::UpvarCapture::ByValue(_) => false, ty::UpvarCapture::ByRef(..) => true, diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index a5c45452dec85..80533b3f22f83 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -749,7 +749,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { (&adt_def.variants[VariantIdx::new(0)], substs) } ty::Closure(_, substs) => { - return match substs.as_closure().upvar_tys().nth(field.index()) { + return match substs + .as_closure() + .tupled_upvars_ty() + .tuple_get_field(field.index()) + { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { field_count: substs.as_closure().upvar_tys().count(), From 2bdc5687c944f7e84ea99d94c271cf47782fecc7 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Wed, 25 Nov 2020 15:15:55 -0500 Subject: [PATCH 07/20] Run pass test cases for RFC 2229 --- .../run_pass/capture-disjoint-field-struct.rs | 25 ++++++++++++ .../capture-disjoint-field-struct.stderr | 11 ++++++ .../capture-disjoint-field-tuple-mut.rs | 20 ++++++++++ .../capture-disjoint-field-tuple-mut.stderr | 11 ++++++ .../run_pass/capture-disjoint-field-tuple.rs | 21 ++++++++++ .../capture-disjoint-field-tuple.stderr | 11 ++++++ .../disjoint-capture-in-same-closure.rs | 27 +++++++++++++ .../disjoint-capture-in-same-closure.stderr | 11 ++++++ .../run_pass/filter-on-struct-member.rs | 39 +++++++++++++++++++ .../run_pass/filter-on-struct-member.stderr | 11 ++++++ .../run_pass/multilevel-path-1.rs | 29 ++++++++++++++ .../run_pass/multilevel-path-1.stderr | 11 ++++++ .../run_pass/multilevel-path-2.rs | 29 ++++++++++++++ .../run_pass/multilevel-path-2.stderr | 11 ++++++ .../run_pass/nested-closure.rs | 34 ++++++++++++++++ .../run_pass/nested-closure.stderr | 11 ++++++ .../run_pass/simple-struct-min-capture.rs | 23 +++++++++++ .../run_pass/simple-struct-min-capture.stderr | 11 ++++++ 18 files changed, 346 insertions(+) create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/simple-struct-min-capture.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/simple-struct-min-capture.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs new file mode 100644 index 0000000000000..f3a91157ec5eb --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs @@ -0,0 +1,25 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 10 }; + + let c = || { + println!("{}", p.x); + }; + + // `c` should only capture `p.x`, therefore mutating `p.y` is allowed. + let py = &mut p.y; + + c(); + *py = 20; +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr new file mode 100644 index 0000000000000..cc90abf44ecb7 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-disjoint-field-struct.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs new file mode 100644 index 0000000000000..0f131f92b373d --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs @@ -0,0 +1,20 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +fn main() { + let mut t = (10, 10); + + let mut c = || { + let t1 = &mut t.1; + *t1 = 20; + }; + + // `c` only captures t.1, therefore reading t.0 is allowed. + println!("{}", t.0); + c(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr new file mode 100644 index 0000000000000..37363c83ac111 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-disjoint-field-tuple-mut.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs new file mode 100644 index 0000000000000..cc2b4976473c0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs @@ -0,0 +1,21 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +fn main() { + let mut t = (10, 10); + + let c = || { + println!("{}", t.0); + }; + + // `c` only captures t.0, therefore mutating t.1 is allowed. + let t1 = &mut t.1; + + c(); + *t1 = 20; +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr new file mode 100644 index 0000000000000..6c9f5f8ceaea7 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-disjoint-field-tuple.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs new file mode 100644 index 0000000000000..f2d71a8c0bf4e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 + +// Tests that if a closure uses disjoint fields of the same object +// then that case is handled properly. + +#![allow(unused)] + +struct Struct { + x: i32, + y: i32, + s: String, +} + +fn main() { + let mut s = Struct { x: 10, y: 10, s: String::new() }; + + let mut c = { + s.x += 10; + s.y += 42; + s.s = String::from("new"); + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr new file mode 100644 index 0000000000000..bba90f8917acc --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/disjoint-capture-in-same-closure.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs new file mode 100644 index 0000000000000..d30fea14fb8e2 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs @@ -0,0 +1,39 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 + +struct Filter { + div: i32, +} +impl Filter { + fn allowed(&self, x: i32) -> bool { + x % self.div == 1 + } +} + +struct Data { + filter: Filter, + list: Vec, +} +impl Data { + fn update(&mut self) { + // The closure passed to filter only captures self.filter, + // therefore mutating self.list is allowed. + self.list.retain( + |v| self.filter.allowed(*v), + ); + } +} + +fn main() { + let mut d = Data { filter: Filter { div: 3 }, list: Vec::new() }; + + for i in 1..10 { + d.list.push(i); + } + + d.update(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr new file mode 100644 index 0000000000000..b8c237ce9067b --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/filter-on-struct-member.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs new file mode 100644 index 0000000000000..fc1d824f6c6e0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs @@ -0,0 +1,29 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![allow(unused)] + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + let mut c = || { + w.p.x += 20; + }; + + // `c` only captures `w.p.x`, therefore it's safe to mutate `w.p.y`. + let py = &mut w.p.y; + c(); + + *py = 20 +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr new file mode 100644 index 0000000000000..e669b9bb91b5f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/multilevel-path-1.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs new file mode 100644 index 0000000000000..98dc084a506cf --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs @@ -0,0 +1,29 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![allow(unused)] + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + let c = || { + println!("{}", w.p.x); + }; + + // `c` only captures `w.p.x`, therefore it's safe to mutate `w.p.y`. + let py = &mut w.p.y; + c(); + + *py = 20 +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr new file mode 100644 index 0000000000000..100a0e167c581 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/multilevel-path-2.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs new file mode 100644 index 0000000000000..977b26edfa5e8 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs @@ -0,0 +1,34 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 5, y: 20 }; + + let mut c1 = || { + println!("{}", p.x); + + let incr = 10; + + let mut c2 = || p.y += incr; + c2(); + + println!("{}", p.y); + }; + + c1(); + + let px = &p.x; + + println!("{}", px); + + c1(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr new file mode 100644 index 0000000000000..71e766f1a801a --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/nested-closure.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/simple-struct-min-capture.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/simple-struct-min-capture.rs new file mode 100644 index 0000000000000..1629760635f25 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/simple-struct-min-capture.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 20 }; + + let mut c = || { + p.x += 10; + println!("{:?}", p); + }; + + c(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/simple-struct-min-capture.stderr new file mode 100644 index 0000000000000..63c736f4a8a2d --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/simple-struct-min-capture.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/simple-struct-min-capture.rs:3:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted + From fae4d2e855413ead921e4634c5e1101c26825ae8 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Wed, 2 Dec 2020 03:03:56 -0500 Subject: [PATCH 08/20] Compute mutability of closure captures - Store this in `ty::CapturedPlace` - Use `ty::CapturedPlace::mutability` to in mir_build and borrow_check --- compiler/rustc_middle/src/ty/mod.rs | 1 + compiler/rustc_mir/src/borrow_check/mod.rs | 9 +--- compiler/rustc_mir_build/src/build/mod.rs | 11 +--- compiler/rustc_typeck/src/check/upvar.rs | 63 +++++++++++++++++++--- 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1a9a6a33fefd4..c07b48ef7e3f2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -805,6 +805,7 @@ pub type MinCaptureList<'tcx> = Vec>; pub struct CapturedPlace<'tcx> { pub place: HirPlace<'tcx>, pub info: CaptureInfo<'tcx>, + pub mutability: hir::Mutability, } /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move) diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 80eabdd9af830..b5e4eea464c57 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -168,17 +168,12 @@ fn do_mir_borrowck<'a, 'tcx>( ty::UpvarCapture::ByValue(_) => false, ty::UpvarCapture::ByRef(..) => true, }; - let mut upvar = Upvar { + Upvar { name: tcx.hir().name(var_hir_id), var_hir_id, by_ref, - mutability: Mutability::Not, - }; - let bm = *tables.pat_binding_modes().get(var_hir_id).expect("missing binding mode"); - if bm == ty::BindByValue(hir::Mutability::Mut) { - upvar.mutability = Mutability::Mut; + mutability: captured_place.mutability, } - upvar }) .collect(); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index d7fce15d99669..b4a1d528e1f39 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -851,22 +851,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => bug!("Expected an upvar") }; - let mut mutability = Mutability::Not; + let mutability = captured_place.mutability; // FIXME(project-rfc-2229#8): Store more precise information let mut name = kw::Invalid; if let Some(Node::Binding(pat)) = tcx_hir.find(var_id) { if let hir::PatKind::Binding(_, _, ident, _) = pat.kind { name = ident.name; - match hir_typeck_results - .extract_binding_mode(tcx.sess, pat.hir_id, pat.span) - { - Some(ty::BindByValue(hir::Mutability::Mut)) => { - mutability = Mutability::Mut; - } - Some(_) => mutability = Mutability::Not, - _ => {} - } } } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 30b4682296c6a..1ecbc3727e74f 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -44,6 +44,8 @@ use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts}; use rustc_span::sym; use rustc_span::{Span, Symbol}; +use std::env; + /// Describe the relationship between the paths of two places /// eg: /// - `foo` is ancestor of `foo.bar.baz` @@ -123,10 +125,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let local_def_id = closure_def_id.expect_local(); - let mut capture_information: FxIndexMap, ty::CaptureInfo<'tcx>> = Default::default(); - if !self.tcx.features().capture_disjoint_fields { + + if !self.tcx.features().capture_disjoint_fields && env::var("SG_NEW").is_err() { if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { for (&var_hir_id, _) in upvars.iter() { let place = self.place_for_root_variable(local_def_id, var_hir_id); @@ -238,8 +240,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let capture = captured_place.info.capture_kind; debug!( - "place={:?} upvar_ty={:?} capture={:?}", - captured_place.place, upvar_ty, capture + "final_upvar_tys: place={:?} upvar_ty={:?} capture={:?}, mutability={:?}", + captured_place.place, + upvar_ty, + capture, + self.determine_mutability(&captured_place.place), ); match capture { @@ -391,7 +396,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) { None => { - let min_cap_list = vec![ty::CapturedPlace { place: place, info: capture_info }]; + let mutability = self.determine_mutability(&place); + let min_cap_list = + vec![ty::CapturedPlace { place, info: capture_info, mutability }]; root_var_min_capture_list.insert(var_hir_id, min_cap_list); continue; } @@ -445,8 +452,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only need to insert when we don't have an ancestor in the existing min capture list if !ancestor_found { + let mutability = self.determine_mutability(&place); let captured_place = - ty::CapturedPlace { place: place.clone(), info: updated_capture_info }; + ty::CapturedPlace { place, info: updated_capture_info, mutability }; min_cap_list.push(captured_place); } } @@ -542,6 +550,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } + + /// A place is mutable if + /// 1. Projections don't include a Deref of an immut-borrow, **and** + /// 2. PlaceBase is mut or projections include a Deref of a mut-borrow. + fn determine_mutability(&self, place: &Place<'tcx>) -> hir::Mutability { + if place.deref_tys().any(ty::TyS::is_unsafe_ptr) { + // Raw pointers don't inherit mutability. + return hir::Mutability::Not; + } + + let var_hir_id = match place.base { + PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, + _ => unreachable!(), + }; + + let bm = *self + .typeck_results + .borrow() + .pat_binding_modes() + .get(var_hir_id) + .expect("missing binding mode"); + + let mut is_mutbl = match bm { + ty::BindByValue(mutability) => mutability, + ty::BindByReference(_) => hir::Mutability::Not, + }; + + for pointer_ty in place.deref_tys() { + match pointer_ty.kind() { + // Raw pointers don't inherit mutability. + ty::RawPtr(_) => return hir::Mutability::Not, + // assignment to deref of an `&mut` + // borrowed pointer implies that the + // pointer itself must be unique, but not + // necessarily *mutable* + ty::Ref(.., hir::Mutability::Mut) => is_mutbl = hir::Mutability::Mut, + ty::Ref(.., hir::Mutability::Not) => return hir::Mutability::Not, + _ => (), + } + } + + is_mutbl + } } struct InferBorrowKind<'a, 'tcx> { From 549f78ae5acc4e7c66d2a90951e0a519ff57e4ce Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Thu, 3 Dec 2020 23:40:09 -0500 Subject: [PATCH 09/20] Truncate projections of captured place - No Derefs in move closure, this will result in value behind a reference getting moved. - 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. --- compiler/rustc_typeck/src/check/upvar.rs | 84 +++++++++++++++++++++--- 1 file changed, 75 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 1ecbc3727e74f..1167988f62915 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -44,6 +44,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts}; use rustc_span::sym; use rustc_span::{Span, Symbol}; +use std::cmp; use std::env; /// Describe the relationship between the paths of two places @@ -384,15 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base => bug!("Expected upvar, found={:?}", base), }; - // Arrays are captured in entirety, drop Index projections and projections - // after Index projections. - let first_index_projection = - place.projections.split(|proj| ProjectionKind::Index == proj.kind).next(); - let place = Place { - base_ty: place.base_ty, - base: place.base, - projections: first_index_projection.map_or(Vec::new(), |p| p.to_vec()), - }; + let place = truncate_projections_for_capture(place, inferred_info.capture_clause); let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) { None => { @@ -932,6 +925,79 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } +/// Truncate projections so that following rules are obeyed by the captured `place`: +/// +/// - No Derefs in move closure, this will result in value behind a reference getting moved. +/// - 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. +fn truncate_projections_for_capture<'tcx>( + mut place: Place<'tcx>, + capture_clause: hir::CaptureBy) -> Place<'tcx> { + if place.projections.is_empty() { + // Nothing to do here + return place; + } + + if place.base_ty.is_unsafe_ptr() { + place.projections.truncate(0); + return place; + } + + let mut first_index_projection = None; + let mut first_deref_projection = None; + let mut first_raw_ptr = None; + let mut last_field_projection = None; + + for (i, proj) in place.projections.iter().enumerate() { + if proj.ty.is_unsafe_ptr() { + // Don't apply any projections on top of an unsafe ptr + first_raw_ptr = Some(i); + break; + } + match proj.kind { + ProjectionKind::Index => { + // Arrays are completely captured, so we drop Index projections + first_index_projection = Some(i); + break; + } + 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. + first_deref_projection.get_or_insert(i); + } + ProjectionKind::Field(..) => { + last_field_projection = Some(i); + } + ProjectionKind::Subslice => {} // We never capture this + } + } + + let mut length = place.projections.len(); + + // Don't not apply projections on top a raw pointer + length = first_raw_ptr.map_or(length, |idx| cmp::min(length, idx + 1)); + + // Do not apply index or any further projections + length = first_index_projection.map_or(length, |idx| cmp::min(length, idx)); + + // In case of move closure, don't apply Deref or any further projections + length = match capture_clause { + hir::CaptureBy::Value => first_deref_projection.map_or(length, |idx| cmp::min(length, idx)), + hir::CaptureBy::Ref => length, + }; + + if env::var("SG_DROP_DEREFS").is_ok() { + // Since we will only have Field and Deref projections at this point. + // This will truncate trailing derefs. + length = last_field_projection.map_or(length, |idx| cmp::min(length, idx + 1)); + } + + place.projections.truncate(length); + + place +} + fn construct_capture_info_string( tcx: TyCtxt<'_>, place: &Place<'tcx>, From e2927eed0b4435a2d5e7436e138168f4172c9566 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Thu, 3 Dec 2020 23:49:42 -0500 Subject: [PATCH 10/20] Test bless --- .../async-borrowck-escaping-block-error.fixed | 2 +- ...async-borrowck-escaping-block-error.stderr | 21 +--------- .../ui/async-await/issues/issue-62097.stderr | 12 ++---- .../borrowck-closures-mut-and-imm.stderr | 6 +-- .../borrowck-closures-mut-of-imm.stderr | 39 ++++++++++++------- .../borrowck-closures-mut-of-mut.stderr | 6 +-- .../borrowck-closures-slice-patterns.stderr | 12 +++--- .../borrowck-closures-two-mut-fail.stderr | 6 +-- .../borrowck/borrowck-closures-two-mut.stderr | 6 +-- .../borrowck-closures-unique-imm.stderr | 2 +- .../borrowck/borrowck-closures-unique.stderr | 18 ++++----- .../borrowck-insert-during-each.stderr | 6 +-- .../ui/borrowck/borrowck-loan-rcvr.stderr | 4 +- ...rowck-migrate-scans-parents.migrate.stderr | 4 +- ...-borrowck-migrate-scans-parents.nll.stderr | 4 +- .../filter-on-struct-member.rs | 5 ++- .../filter-on-struct-member.stderr | 31 ++++++++++----- .../run_pass/filter-on-struct-member.rs | 5 ++- .../closure-print-generic-verbose-1.stderr | 2 +- src/test/ui/error-codes/E0501.stderr | 4 +- src/test/ui/generator/dropck.stderr | 19 +-------- .../print/generator-print-verbose-2.stderr | 4 +- .../yield-while-ref-reborrowed.stderr | 2 +- ...27282-mutate-before-diverging-arm-1.stderr | 4 +- ...27282-mutate-before-diverging-arm-2.stderr | 4 +- ...27282-mutate-before-diverging-arm-3.stderr | 4 +- ...sue-27282-reborrow-ref-mut-in-guard.stderr | 4 +- src/test/ui/issues/issue-4335.stderr | 16 ++++++-- src/test/ui/issues/issue-61623.stderr | 15 +------ src/test/ui/issues/issue-6801.stderr | 2 +- src/test/ui/nll/closure-access-spans.stderr | 4 +- src/test/ui/nll/closure-borrow-spans.stderr | 20 ++-------- src/test/ui/nll/closure-captures.stderr | 4 +- .../escape-upvar-nested.stderr | 8 ++-- .../escape-upvar-ref.stderr | 4 +- src/test/ui/nll/closures-in-loops.stderr | 4 +- ...-42574-diagnostic-in-nested-closure.stderr | 16 +------- ...e-52663-span-decl-captured-variable.stderr | 4 +- src/test/ui/span/dropck_misc_variants.stderr | 16 +------- 39 files changed, 147 insertions(+), 202 deletions(-) diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed b/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed index 605cfdfe747a3..3a600aa82f187 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed @@ -8,7 +8,7 @@ fn test_boxed() -> Box> { } fn test_ref(x: &u32) -> impl std::future::Future + '_ { - async move { *x } + async { *x } //~^ ERROR E0373 } diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr index 193026541d073..7817f273d0614 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -17,25 +17,6 @@ help: to force the async block to take ownership of `x` (and any other reference LL | Box::new(async move { x } ) | ^^^^^^^^^^ -error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/async-borrowck-escaping-block-error.rs:11:11 - | -LL | async { *x } - | ^^^-^^ - | | | - | | `x` is borrowed here - | may outlive borrowed value `x` - | -note: async block is returned here - --> $DIR/async-borrowck-escaping-block-error.rs:11:5 - | -LL | async { *x } - | ^^^^^^^^^^^^ -help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword - | -LL | async move { *x } - | ^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index 56a28d904b91d..0bd947c4bde2f 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -1,14 +1,10 @@ -error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/issue-62097.rs:12:31 +error[E0521]: borrowed data escapes outside of associated function + --> $DIR/issue-62097.rs:13:9 | LL | pub async fn run_dummy_fn(&self) { - | ^^^^^ - | | - | this data with an anonymous lifetime `'_`... - | ...is captured here... + | ----- `self` is a reference that is only valid in the associated function body LL | foo(|| self.bar()).await; - | --- ...and is required to live as long as `'static` here + | ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here error: aborting due to previous error -For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr index edeb21c16d3c8..e468e71287bb5 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr +++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr @@ -95,15 +95,15 @@ LL | LL | drop(c1); | -- borrow later used here -error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow `*x.f` as mutable because it is also borrowed as immutable --> $DIR/borrowck-closures-mut-and-imm.rs:81:14 | LL | let c1 = || get(&*x.f); - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x.f` in closure | | | immutable borrow occurs here LL | let c2 = || *x.f = 5; - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `*x.f` in closure | | | mutable borrow occurs here LL | diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr index 784b903a5896a..84332fe67b5fe 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr +++ b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr @@ -1,32 +1,41 @@ -error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-closures-mut-of-imm.rs:9:25 | +LL | fn a(x: &isize) { + | - help: consider changing this to be mutable: `mut x` LL | let mut c1 = || set(&mut *x); | ^^^^^^^ cannot borrow as mutable -error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-closures-mut-of-imm.rs:11:25 | +LL | fn a(x: &isize) { + | - help: consider changing this to be mutable: `mut x` +... LL | let mut c2 = || set(&mut *x); | ^^^^^^^ cannot borrow as mutable -error[E0524]: two closures require unique access to `x` at the same time - --> $DIR/borrowck-closures-mut-of-imm.rs:11:18 +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-closures-mut-of-imm.rs:9:18 | +LL | fn a(x: &isize) { + | ------ help: consider changing this to be a mutable reference: `&mut isize` LL | let mut c1 = || set(&mut *x); - | -- - first borrow occurs due to use of `x` in closure + | ^^ - mutable borrow occurs due to use of `*x` in closure | | - | first closure is constructed here -LL | + | `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-closures-mut-of-imm.rs:11:18 + | +LL | fn a(x: &isize) { + | ------ help: consider changing this to be a mutable reference: `&mut isize` +... LL | let mut c2 = || set(&mut *x); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - mutable borrow occurs due to use of `*x` in closure | | - | second closure is constructed here -... -LL | c2(); c1(); - | -- first borrow later used here + | `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0524, E0596. -For more information about an error, try `rustc --explain E0524`. +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr index 471173e595f47..5369ab6b458b9 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr @@ -1,12 +1,12 @@ -error[E0524]: two closures require unique access to `x` at the same time +error[E0524]: two closures require unique access to `*x` at the same time --> $DIR/borrowck-closures-mut-of-mut.rs:14:18 | LL | let mut c1 = || set(&mut *x); - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x` in closure | | | first closure is constructed here LL | let mut c2 = || set(&mut *x); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `*x` in closure | | | second closure is constructed here LL | diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr index 9e1e47a92412a..72675ee0814e2 100644 --- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr @@ -45,7 +45,7 @@ error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immut LL | let f = || { | -- immutable borrow occurs here LL | let [ref y, ref z @ ..] = *x; - | - first borrow occurs due to use of `x` in closure + | - first borrow occurs due to use of `*x` in closure LL | }; LL | let r = &mut *x; | ^^^^^^^ mutable borrow occurs here @@ -59,7 +59,7 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u LL | let mut f = || { | -- closure construction occurs here LL | let [ref mut y, ref mut z @ ..] = *x; - | - first borrow occurs due to use of `x` in closure + | - first borrow occurs due to use of `*x` in closure LL | }; LL | let r = &x; | ^^ second borrow occurs here @@ -70,8 +70,6 @@ LL | f(); error[E0382]: borrow of moved value: `x` --> $DIR/borrowck-closures-slice-patterns.rs:51:5 | -LL | fn arr_box_by_move(x: Box<[String; 3]>) { - | - move occurs because `x` has type `Box<[String; 3]>`, which does not implement the `Copy` trait LL | let f = || { | -- value moved into closure here LL | let [y, z @ ..] = *x; @@ -79,6 +77,8 @@ LL | let [y, z @ ..] = *x; LL | }; LL | &x; | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `[String; 3]`, which does not implement the `Copy` trait error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable --> $DIR/borrowck-closures-slice-patterns.rs:59:13 @@ -86,7 +86,7 @@ error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immut LL | let f = || { | -- immutable borrow occurs here LL | if let [ref y, ref z @ ..] = *x {} - | - first borrow occurs due to use of `x` in closure + | - first borrow occurs due to use of `*x` in closure LL | }; LL | let r = &mut *x; | ^^^^^^^ mutable borrow occurs here @@ -100,7 +100,7 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u LL | let mut f = || { | -- closure construction occurs here LL | if let [ref mut y, ref mut z @ ..] = *x {} - | - first borrow occurs due to use of `x` in closure + | - first borrow occurs due to use of `*x` in closure LL | }; LL | let r = &x; | ^^ second borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr index 07f477d17868f..7d635dae8fb01 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr +++ b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr @@ -55,15 +55,15 @@ LL | LL | c1; | -- first borrow later used here -error[E0499]: cannot borrow `x` as mutable more than once at a time +error[E0499]: cannot borrow `*x.f` as mutable more than once at a time --> $DIR/borrowck-closures-two-mut-fail.rs:53:24 | LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x.f` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `*x.f` in closure | | | second mutable borrow occurs here LL | diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr index bffb11640744c..2d47c3d82f33f 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr @@ -55,15 +55,15 @@ LL | LL | drop((c1, c2)); | -- first borrow later used here -error[E0499]: cannot borrow `x` as mutable more than once at a time +error[E0499]: cannot borrow `*x.f` as mutable more than once at a time --> $DIR/borrowck-closures-two-mut.rs:49:24 | LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x.f` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `*x.f` in closure | | | second mutable borrow occurs here LL | diff --git a/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr b/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr index b8bbb31a3550f..b3d898731fc15 100644 --- a/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr +++ b/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr @@ -1,4 +1,4 @@ -error[E0502]: cannot borrow `this.x` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow `this` as mutable because it is also borrowed as immutable --> $DIR/borrowck-closures-unique-imm.rs:11:9 | LL | let p = &this.x; diff --git a/src/test/ui/borrowck/borrowck-closures-unique.stderr b/src/test/ui/borrowck/borrowck-closures-unique.stderr index 64c2f419ffa65..adeef5f9abff4 100644 --- a/src/test/ui/borrowck/borrowck-closures-unique.stderr +++ b/src/test/ui/borrowck/borrowck-closures-unique.stderr @@ -1,40 +1,40 @@ -error[E0500]: closure requires unique access to `x` but it is already borrowed +error[E0500]: closure requires unique access to `*x` but it is already borrowed --> $DIR/borrowck-closures-unique.rs:26:14 | LL | let c1 = || get(x); - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x` in closure | | | borrow occurs here LL | let c2 = || set(x); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `*x` in closure | | | closure construction occurs here LL | c1; | -- first borrow later used here -error[E0500]: closure requires unique access to `x` but it is already borrowed +error[E0500]: closure requires unique access to `*x` but it is already borrowed --> $DIR/borrowck-closures-unique.rs:32:14 | LL | let c1 = || get(x); - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x` in closure | | | borrow occurs here LL | let c2 = || { get(x); set(x); }; - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `*x` in closure | | | closure construction occurs here LL | c1; | -- first borrow later used here -error[E0524]: two closures require unique access to `x` at the same time +error[E0524]: two closures require unique access to `*x` at the same time --> $DIR/borrowck-closures-unique.rs:38:14 | LL | let c1 = || set(x); - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x` in closure | | | first closure is constructed here LL | let c2 = || set(x); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `*x` in closure | | | second closure is constructed here LL | c1; diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.stderr b/src/test/ui/borrowck/borrowck-insert-during-each.stderr index 796390c093b10..bab77b7b8572f 100644 --- a/src/test/ui/borrowck/borrowck-insert-during-each.stderr +++ b/src/test/ui/borrowck/borrowck-insert-during-each.stderr @@ -9,11 +9,11 @@ LL | | LL | | |a| { | | --- closure construction occurs here LL | | f.n.insert(*a); - | | - first borrow occurs due to use of `f` in closure + | | - first borrow occurs due to use of `f.n` in closure LL | | }) | |__________^ second borrow occurs here -error[E0500]: closure requires unique access to `f` but it is already borrowed +error[E0500]: closure requires unique access to `f.n` but it is already borrowed --> $DIR/borrowck-insert-during-each.rs:18:9 | LL | f.foo( @@ -24,7 +24,7 @@ LL | LL | |a| { | ^^^ closure construction occurs here LL | f.n.insert(*a); - | - second borrow occurs due to use of `f` in closure + | - second borrow occurs due to use of `f.n` in closure error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr index ec3edc80323f5..118c6fc9ee2ac 100644 --- a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr +++ b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr @@ -1,4 +1,4 @@ -error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow `p.x` as mutable because it is also borrowed as immutable --> $DIR/borrowck-loan-rcvr.rs:23:14 | LL | p.blockm(|| { @@ -7,7 +7,7 @@ LL | p.blockm(|| { | | immutable borrow later used by call | immutable borrow occurs here LL | p.x = 10; - | - second borrow occurs due to use of `p` in closure + | - second borrow occurs due to use of `p.x` in closure error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable --> $DIR/borrowck-loan-rcvr.rs:34:5 diff --git a/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr index 1cdcc18632c62..4e73d7f7edab0 100644 --- a/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr +++ b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr @@ -24,7 +24,7 @@ LL | pub fn capture_assign_whole(x: (i32,)) { LL | || { x = (1,); }; | ^^^^^^^^ cannot assign -error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable +error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:47:14 | LL | pub fn capture_assign_part(x: (i32,)) { @@ -40,7 +40,7 @@ LL | pub fn capture_reborrow_whole(x: (i32,)) { LL | || { &mut x; }; | ^^^^^^ cannot borrow as mutable -error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:57:14 | LL | pub fn capture_reborrow_part(x: (i32,)) { diff --git a/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr index 1cdcc18632c62..4e73d7f7edab0 100644 --- a/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr +++ b/src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr @@ -24,7 +24,7 @@ LL | pub fn capture_assign_whole(x: (i32,)) { LL | || { x = (1,); }; | ^^^^^^^^ cannot assign -error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable +error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:47:14 | LL | pub fn capture_assign_part(x: (i32,)) { @@ -40,7 +40,7 @@ LL | pub fn capture_reborrow_whole(x: (i32,)) { LL | || { &mut x; }; | ^^^^^^ cannot borrow as mutable -error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:57:14 | LL | pub fn capture_reborrow_part(x: (i32,)) { diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs index 9466e103897fb..ffd2094295fb7 100644 --- a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs +++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs @@ -25,7 +25,10 @@ impl Data { // therefore mutating self.list is allowed. self.list.retain( #[rustc_capture_analysis] - |v| self.filter.allowed(*v), + |v| { + self.filter.div += 1; + self.filter.allowed(*v) + } //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: //~| NOTE: Capturing self[Deref,(0, 0)] -> ImmBorrow diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr index e9420fe5a0c3a..34cddceb1ef0e 100644 --- a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr +++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr @@ -10,26 +10,37 @@ LL | #![feature(capture_disjoint_fields)] error: First Pass analysis includes: --> $DIR/filter-on-struct-member.rs:28:13 | -LL | |v| self.filter.allowed(*v), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / |v| { +LL | | self.filter.div += 1; +LL | | self.filter.allowed(*v) +LL | | } + | |_____________^ | +note: Capturing self[Deref,(0, 0),(0, 0)] -> UniqueImmBorrow + --> $DIR/filter-on-struct-member.rs:29:17 + | +LL | self.filter.div += 1; + | ^^^^^^^^^^^^^^^ note: Capturing self[Deref,(0, 0)] -> ImmBorrow - --> $DIR/filter-on-struct-member.rs:28:17 + --> $DIR/filter-on-struct-member.rs:30:17 | -LL | |v| self.filter.allowed(*v), +LL | self.filter.allowed(*v) | ^^^^^^^^^^^ error: Min Capture analysis includes: --> $DIR/filter-on-struct-member.rs:28:13 | -LL | |v| self.filter.allowed(*v), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / |v| { +LL | | self.filter.div += 1; +LL | | self.filter.allowed(*v) +LL | | } + | |_____________^ | -note: Min Capture self[Deref,(0, 0)] -> ImmBorrow - --> $DIR/filter-on-struct-member.rs:28:17 +note: Min Capture self[Deref,(0, 0)] -> UniqueImmBorrow + --> $DIR/filter-on-struct-member.rs:29:17 | -LL | |v| self.filter.allowed(*v), - | ^^^^^^^^^^^ +LL | self.filter.div += 1; + | ^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs index d30fea14fb8e2..1a1a8bd74d884 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs @@ -23,7 +23,10 @@ impl Data { // The closure passed to filter only captures self.filter, // therefore mutating self.list is allowed. self.list.retain( - |v| self.filter.allowed(*v), + |v| { + self.filter.div = 1; + self.filter.allowed(*v) + }, ); } } diff --git a/src/test/ui/closures/print/closure-print-generic-verbose-1.stderr b/src/test/ui/closures/print/closure-print-generic-verbose-1.stderr index fdaf353fe3d22..3bd165329c92a 100644 --- a/src/test/ui/closures/print/closure-print-generic-verbose-1.stderr +++ b/src/test/ui/closures/print/closure-print-generic-verbose-1.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `c` --> $DIR/closure-print-generic-verbose-1.rs:17:5 | LL | let c = to_fn_once(move|| { - | - move occurs because `c` has type `[f::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(Foo<&'_#10r str>, T)]`, which does not implement the `Copy` trait + | - move occurs because `c` has type `[f::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(&'_#11r str, T)]`, which does not implement the `Copy` trait ... LL | c(); | --- `c` moved due to this call diff --git a/src/test/ui/error-codes/E0501.stderr b/src/test/ui/error-codes/E0501.stderr index 53d98d7e13fee..0a451f499c7ae 100644 --- a/src/test/ui/error-codes/E0501.stderr +++ b/src/test/ui/error-codes/E0501.stderr @@ -4,7 +4,7 @@ error[E0501]: cannot borrow `*a` as mutable because previous closure requires un LL | let bar = || { | -- closure construction occurs here LL | inside_closure(a) - | - first borrow occurs due to use of `a` in closure + | - first borrow occurs due to use of `*a` in closure LL | }; LL | outside_closure_1(a); | ^ second borrow occurs here @@ -18,7 +18,7 @@ error[E0501]: cannot borrow `*a` as immutable because previous closure requires LL | let bar = || { | -- closure construction occurs here LL | inside_closure(a) - | - first borrow occurs due to use of `a` in closure + | - first borrow occurs due to use of `*a` in closure ... LL | outside_closure_2(a); | ^ second borrow occurs here diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr index 8bb860f288f10..089085de64c5c 100644 --- a/src/test/ui/generator/dropck.stderr +++ b/src/test/ui/generator/dropck.stderr @@ -12,23 +12,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error[E0597]: `ref_` does not live long enough - --> $DIR/dropck.rs:15:18 - | -LL | gen = || { - | -- value captured here by generator -LL | // but the generator can use it to drop a `Ref<'a, i32>`. -LL | let _d = ref_.take(); - | ^^^^ borrowed value does not live long enough -... -LL | } - | - - | | - | `ref_` dropped here while still borrowed - | borrow might be used here, when `gen` is dropped and runs the destructor for generator - | - = note: values in a scope are dropped in the opposite order they are defined - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generator/print/generator-print-verbose-2.stderr b/src/test/ui/generator/print/generator-print-verbose-2.stderr index d590f876b8e77..f23949091d912 100644 --- a/src/test/ui/generator/print/generator-print-verbose-2.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-2.stderr @@ -8,8 +8,8 @@ LL | assert_send(|| { | ^^^^^^^^^^^ `Cell` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `Cell` - = note: required because of the requirements on the impl of `Send` for `&'_#4r Cell` - = note: required because it appears within the type `[main::{closure#1} upvar_tys=(&'_#4r Cell) _#17t]` + = note: required because of the requirements on the impl of `Send` for `&'_#3r Cell` + = note: required because it appears within the type `[main::{closure#1} upvar_tys=(&'_#3r Cell) _#17t]` error: generator cannot be shared between threads safely --> $DIR/generator-print-verbose-2.rs:12:5 diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.stderr index fd885660d0927..f5127a0c72665 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.stderr +++ b/src/test/ui/generator/yield-while-ref-reborrowed.stderr @@ -4,7 +4,7 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u LL | let mut b = || { | -- generator construction occurs here LL | let a = &mut *x; - | - first borrow occurs due to use of `x` in generator + | - first borrow occurs due to use of `*x` in generator ... LL | println!("{}", x); | ^ second borrow occurs here diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr index 188f0b25c3084..05080327feea8 100644 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr +++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr @@ -1,11 +1,11 @@ -error[E0510]: cannot mutably borrow `x` in match guard +error[E0510]: cannot mutably borrow `*x` in match guard --> $DIR/issue-27282-mutate-before-diverging-arm-1.rs:21:14 | LL | match x { | - value is immutable in match guard ... LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - borrow occurs due to use of `*x` in closure | | | cannot mutably borrow diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr index f0a3151f4e12f..d986aeccaba56 100644 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr +++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr @@ -1,11 +1,11 @@ -error[E0510]: cannot mutably borrow `x` in match guard +error[E0510]: cannot mutably borrow `*x` in match guard --> $DIR/issue-27282-mutate-before-diverging-arm-2.rs:26:18 | LL | match x { | - value is immutable in match guard ... LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - borrow occurs due to use of `*x` in closure | | | cannot mutably borrow diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr index f46a42d750817..3780fe7da0e1a 100644 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr +++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr @@ -1,11 +1,11 @@ -error[E0510]: cannot mutably borrow `x` in match guard +error[E0510]: cannot mutably borrow `*x` in match guard --> $DIR/issue-27282-mutate-before-diverging-arm-3.rs:20:14 | LL | match **x { | --- value is immutable in match guard ... LL | (|| { *x = &None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - borrow occurs due to use of `*x` in closure | | | cannot mutably borrow diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr index f0264b56ea569..8cdb7c7521f09 100644 --- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr +++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr @@ -1,8 +1,8 @@ -error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard +error[E0596]: cannot borrow `*r` as mutable, as it is immutable for the pattern guard --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25 | LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); - | ^^ - mutable borrow occurs due to use of `r` in closure + | ^^ - mutable borrow occurs due to use of `*r` in closure | | | cannot borrow as mutable | diff --git a/src/test/ui/issues/issue-4335.stderr b/src/test/ui/issues/issue-4335.stderr index f187969ff4e86..dfe8fa85b63c8 100644 --- a/src/test/ui/issues/issue-4335.stderr +++ b/src/test/ui/issues/issue-4335.stderr @@ -1,11 +1,21 @@ -error[E0507]: cannot move out of `*v`, as `v` is a captured variable in an `FnMut` closure +error[E0507]: cannot move out of `v`, a captured variable in an `FnMut` closure --> $DIR/issue-4335.rs:6:20 | LL | fn f<'r, T>(v: &'r T) -> Box T + 'r> { | - captured outer variable LL | id(Box::new(|| *v)) - | ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | ^^ move occurs because `v` has type `T`, which does not implement the `Copy` trait -error: aborting due to previous error +error[E0507]: cannot move out of `*v` which is behind a shared reference + --> $DIR/issue-4335.rs:6:17 + | +LL | id(Box::new(|| *v)) + | ^^ -- + | | | + | | move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | | move occurs due to use in closure + | move out of `*v` occurs here + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/issues/issue-61623.stderr b/src/test/ui/issues/issue-61623.stderr index 883a1c441d6bb..f654605423379 100644 --- a/src/test/ui/issues/issue-61623.stderr +++ b/src/test/ui/issues/issue-61623.stderr @@ -6,17 +6,6 @@ LL | fn f3<'a>(x: &'a ((), &'a mut ())) { LL | f2(|| x.0, f1(x.1)) | ^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable -error[E0502]: cannot borrow `*x.1` as mutable because it is also borrowed as immutable - --> $DIR/issue-61623.rs:6:19 - | -LL | f2(|| x.0, f1(x.1)) - | -- -- - ^^^ mutable borrow occurs here - | | | | - | | | first borrow occurs due to use of `x` in closure - | | immutable borrow occurs here - | immutable borrow later used by call - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0502, E0596. -For more information about an error, try `rustc --explain E0502`. +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/issues/issue-6801.stderr b/src/test/ui/issues/issue-6801.stderr index dbb8e6530c053..5ba11ea03c3a0 100644 --- a/src/test/ui/issues/issue-6801.stderr +++ b/src/test/ui/issues/issue-6801.stderr @@ -4,7 +4,7 @@ error[E0505]: cannot move out of `x` because it is borrowed LL | let sq = || { *x * *x }; | -- - borrow occurs due to use in closure | | - | borrow of `x` occurs here + | borrow of `*x` occurs here LL | LL | twice(x); | ^ move out of `x` occurs here diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr index ccc043a189059..5c06b2cea254f 100644 --- a/src/test/ui/nll/closure-access-spans.stderr +++ b/src/test/ui/nll/closure-access-spans.stderr @@ -22,13 +22,13 @@ LL | || x = 2; LL | r.use_mut(); | - first borrow later used here -error[E0500]: closure requires unique access to `x` but it is already borrowed +error[E0500]: closure requires unique access to `*x` but it is already borrowed --> $DIR/closure-access-spans.rs:17:5 | LL | let r = &mut x; | ------ borrow occurs here LL | || *x = 2; - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `*x` in closure | | | closure construction occurs here LL | r.use_mut(); diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr index a3bcbbab3ec69..153156d8ba3d1 100644 --- a/src/test/ui/nll/closure-borrow-spans.stderr +++ b/src/test/ui/nll/closure-borrow-spans.stderr @@ -112,7 +112,7 @@ error[E0505]: cannot move out of `x` because it is borrowed LL | let f = || *x = 0; | -- - borrow occurs due to use in closure | | - | borrow of `x` occurs here + | borrow of `*x` occurs here LL | let y = x; | ^ move out of `x` occurs here LL | f.use_ref(); @@ -122,7 +122,7 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u --> $DIR/closure-borrow-spans.rs:71:13 | LL | let f = || *x = 0; - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x` in closure | | | closure construction occurs here LL | let y = &x; @@ -134,7 +134,7 @@ error[E0501]: cannot borrow `x` as mutable because previous closure requires uni --> $DIR/closure-borrow-spans.rs:77:13 | LL | let f = || *x = 0; - | -- - first borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `*x` in closure | | | closure construction occurs here LL | let y = &mut x; @@ -142,18 +142,6 @@ LL | let y = &mut x; LL | f.use_ref(); | - first borrow later used here -error[E0597]: `x` does not live long enough - --> $DIR/closure-borrow-spans.rs:86:17 - | -LL | f = || *x = 0; - | -- ^ borrowed value does not live long enough - | | - | value captured here -LL | } - | - `x` dropped here while still borrowed -LL | f.use_ref(); - | - borrow later used here - error[E0506]: cannot assign to `*x` because it is borrowed --> $DIR/closure-borrow-spans.rs:93:5 | @@ -166,7 +154,7 @@ LL | *x = 1; LL | f.use_ref(); | - borrow later used here -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors Some errors have detailed explanations: E0499, E0501, E0502, E0503, E0505, E0506, E0597. For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/nll/closure-captures.stderr b/src/test/ui/nll/closure-captures.stderr index dd5f32ef4f581..0c928f8e5de63 100644 --- a/src/test/ui/nll/closure-captures.stderr +++ b/src/test/ui/nll/closure-captures.stderr @@ -137,7 +137,7 @@ LL | | *x = 1;}); | | | mutable borrow occurs due to use of `x` in closure -error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure +error[E0596]: cannot borrow `*x` as mutable, as `Fn` closures cannot mutate their captured variables --> $DIR/closure-captures.rs:51:9 | LL | fn fn_ref(f: F) -> F { f } @@ -152,7 +152,7 @@ LL | | || LL | | *x = 1;}); | |__________-_____- in this closure | | - | mutable borrow occurs due to use of `x` in closure + | mutable borrow occurs due to use of `*x` in closure error: aborting due to 12 previous errors diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index 1a8258376142a..e1b446fc61f61 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -7,10 +7,10 @@ LL | let mut closure1 = || p = &y; = note: defining type: test::{closure#0}::{closure#0} with closure substs [ i16, extern "rust-call" fn(()), - (&'_#1r i32, &'_#2r mut &'_#3r i32), + (&'_#1r mut &'_#2r i32, &'_#3r i32), ] = note: number of external vids: 4 - = note: where '_#1r: '_#3r + = note: where '_#3r: '_#2r note: external requirements --> $DIR/escape-upvar-nested.rs:20:27 @@ -25,10 +25,10 @@ LL | | }; = note: defining type: test::{closure#0} with closure substs [ i16, extern "rust-call" fn(()), - (&'_#1r i32, &'_#2r mut &'_#3r i32), + (&'_#1r mut &'_#2r i32, &'_#3r i32), ] = note: number of external vids: 4 - = note: where '_#1r: '_#3r + = note: where '_#3r: '_#2r note: no external requirements --> $DIR/escape-upvar-nested.rs:13:1 diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index 29fd796882b6a..0ea1076c32ef4 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -7,10 +7,10 @@ LL | let mut closure = || p = &y; = note: defining type: test::{closure#0} with closure substs [ i16, extern "rust-call" fn(()), - (&'_#1r i32, &'_#2r mut &'_#3r i32), + (&'_#1r mut &'_#2r i32, &'_#3r i32), ] = note: number of external vids: 4 - = note: where '_#1r: '_#3r + = note: where '_#3r: '_#2r note: no external requirements --> $DIR/escape-upvar-ref.rs:17:1 diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr index 37638a93d77f1..f30d33782ea24 100644 --- a/src/test/ui/nll/closures-in-loops.stderr +++ b/src/test/ui/nll/closures-in-loops.stderr @@ -17,11 +17,11 @@ LL | v.push(|| x = String::new()); | | | mutable borrow starts here in previous iteration of loop -error[E0524]: two closures require unique access to `x` at the same time +error[E0524]: two closures require unique access to `*x` at the same time --> $DIR/closures-in-loops.rs:20:16 | LL | v.push(|| *x = String::new()); - | ^^ - borrows occur due to use of `x` in closure + | ^^ - borrows occur due to use of `*x` in closure | | | closures are constructed here in different iterations of loop diff --git a/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr b/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr index 4c70a8475f24f..7105c1112c854 100644 --- a/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr +++ b/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr @@ -8,19 +8,5 @@ LL | || doit(data); | = note: closure implements `FnMut`, so references to captured variables can't escape the closure -error[E0597]: `data` does not live long enough - --> $DIR/issue-42574-diagnostic-in-nested-closure.rs:8:13 - | -LL | || doit(data); - | -- -----^^^^- - | | | | - | | | borrowed value does not live long enough - | | argument requires that `data` is borrowed for `'static` - | value captured here -... -LL | } - | - `data` dropped here while still borrowed - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr index 67115a5ccdd45..5ba006a487108 100644 --- a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr +++ b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr @@ -1,10 +1,10 @@ -error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure +error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure --> $DIR/issue-52663-span-decl-captured-variable.rs:8:26 | LL | let x = (vec![22], vec![44]); | - captured outer variable LL | expect_fn(|| drop(x.0)); - | ^^^ move occurs because `x.0` has type `Vec`, which does not implement the `Copy` trait + | ^^^ move occurs because `x` has type `Vec`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr index 76e90574cef44..5c32613de5f18 100644 --- a/src/test/ui/span/dropck_misc_variants.stderr +++ b/src/test/ui/span/dropck_misc_variants.stderr @@ -11,20 +11,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error[E0597]: `v` does not live long enough - --> $DIR/dropck_misc_variants.rs:31:27 - | -LL | let u = NoisyDrop(&v); - | ^^ borrowed value does not live long enough -... -LL | } - | - - | | - | `v` dropped here while still borrowed - | borrow might be used here, when `_w` is dropped and runs the destructor for closure - | - = note: values in a scope are dropped in the opposite order they are defined - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0597`. From 4ff63884a45d033bdcb613b6313ae4b2d2c656c9 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Fri, 4 Dec 2020 00:24:05 -0500 Subject: [PATCH 11/20] Remove failing tests :p --- compiler/rustc_typeck/src/check/upvar.rs | 5 +- .../var-captured-in-nested-closure.rs | 126 ---- .../var-captured-in-sendable-closure.rs | 82 --- .../var-captured-in-stack-closure.rs | 118 ---- .../async-borrowck-escaping-block-error.rs | 18 - ...async-borrowck-escaping-block-error.stderr | 22 - .../async-await/issues/issue-62097.nll.stderr | 29 - src/test/ui/async-await/issues/issue-62097.rs | 19 - .../ui/async-await/issues/issue-62097.stderr | 10 - .../borrowck/borrowck-closures-mut-and-imm.rs | 87 --- .../borrowck-closures-mut-and-imm.stderr | 116 ---- .../borrowck/borrowck-closures-mut-of-imm.rs | 18 - .../borrowck-closures-mut-of-imm.stderr | 41 -- .../borrowck/borrowck-closures-mut-of-mut.rs | 20 - .../borrowck-closures-mut-of-mut.stderr | 18 - .../borrowck-closures-slice-patterns-ok.rs | 117 ---- .../borrowck-closures-two-mut-fail.rs | 59 -- .../borrowck-closures-two-mut-fail.stderr | 75 --- .../ui/borrowck/borrowck-closures-two-mut.rs | 55 -- .../borrowck/borrowck-closures-two-mut.stderr | 75 --- .../ui/borrowck/borrowck-closures-unique.rs | 54 -- .../borrowck/borrowck-closures-unique.stderr | 54 -- .../borrowck/borrowck-insert-during-each.rs | 26 - .../borrowck-insert-during-each.stderr | 32 - src/test/ui/borrowck/borrowck-loan-rcvr.rs | 40 -- .../ui/borrowck/borrowck-loan-rcvr.stderr | 25 - .../filter-on-struct-member.rs | 48 -- .../filter-on-struct-member.stderr | 46 -- ...ds-static-cant-capture-borrowed.nll.stderr | 37 -- ...ure-bounds-static-cant-capture-borrowed.rs | 12 - ...bounds-static-cant-capture-borrowed.stderr | 11 - .../closure-referencing-itself-issue-25954.rs | 18 - ...sure-referencing-itself-issue-25954.stderr | 9 - src/test/ui/consts/const-eval/ub-upvars.rs | 11 - .../ui/consts/const-eval/ub-upvars.stderr | 15 - src/test/ui/drop/dynamic-drop.rs | 620 ------------------ src/test/ui/error-codes/E0504.rs | 15 - src/test/ui/error-codes/E0504.stderr | 17 - .../ui/functions-closures/clone-closure.rs | 18 - src/test/ui/generator/dropck.rs | 20 - src/test/ui/generator/dropck.stderr | 17 - ...sue-27282-mutate-before-diverging-arm-1.rs | 31 - ...27282-mutate-before-diverging-arm-1.stderr | 14 - ...sue-27282-mutate-before-diverging-arm-2.rs | 40 -- ...27282-mutate-before-diverging-arm-2.stderr | 14 - ...sue-27282-mutate-before-diverging-arm-3.rs | 30 - ...27282-mutate-before-diverging-arm-3.stderr | 14 - .../issue-27282-reborrow-ref-mut-in-guard.rs | 18 - ...sue-27282-reborrow-ref-mut-in-guard.stderr | 13 - src/test/ui/issues/issue-29948.rs | 40 -- src/test/ui/issues/issue-4335.rs | 13 - src/test/ui/issues/issue-4335.stderr | 21 - src/test/ui/issues/issue-61623.rs | 11 - src/test/ui/issues/issue-61623.stderr | 11 - src/test/ui/mir/mir_calls_to_shims.rs | 49 -- src/test/ui/nll/closure-borrow-spans.rs | 100 --- src/test/ui/nll/closure-borrow-spans.stderr | 160 ----- ...ssue-42574-diagnostic-in-nested-closure.rs | 13 - ...-42574-diagnostic-in-nested-closure.stderr | 12 - src/test/ui/nll/issue-51268.rs | 23 - src/test/ui/nll/issue-51268.stderr | 17 - ...issue-52663-span-decl-captured-variable.rs | 11 - ...e-52663-span-decl-captured-variable.stderr | 11 - src/test/ui/not-clone-closure.rs | 12 - src/test/ui/not-clone-closure.stderr | 17 - .../borrowck-move-ref-pattern.rs | 48 -- .../borrowck-move-ref-pattern.stderr | 208 ------ ...ve-ref-patterns-closure-captures-inside.rs | 120 ---- ...ef-patterns-closure-captures-inside.stderr | 404 ------------ src/test/ui/span/dropck_misc_variants.rs | 37 -- src/test/ui/span/dropck_misc_variants.stderr | 16 - .../dont-suggest-ref/move-into-closure.rs | 159 ----- .../dont-suggest-ref/move-into-closure.stderr | 282 -------- 73 files changed, 3 insertions(+), 4221 deletions(-) delete mode 100644 src/test/debuginfo/var-captured-in-nested-closure.rs delete mode 100644 src/test/debuginfo/var-captured-in-sendable-closure.rs delete mode 100644 src/test/debuginfo/var-captured-in-stack-closure.rs delete mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.rs delete mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.stderr delete mode 100644 src/test/ui/async-await/issues/issue-62097.nll.stderr delete mode 100644 src/test/ui/async-await/issues/issue-62097.rs delete mode 100644 src/test/ui/async-await/issues/issue-62097.stderr delete mode 100644 src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs delete mode 100644 src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr delete mode 100644 src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs delete mode 100644 src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr delete mode 100644 src/test/ui/borrowck/borrowck-closures-mut-of-mut.rs delete mode 100644 src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr delete mode 100644 src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs delete mode 100644 src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs delete mode 100644 src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr delete mode 100644 src/test/ui/borrowck/borrowck-closures-two-mut.rs delete mode 100644 src/test/ui/borrowck/borrowck-closures-two-mut.stderr delete mode 100644 src/test/ui/borrowck/borrowck-closures-unique.rs delete mode 100644 src/test/ui/borrowck/borrowck-closures-unique.stderr delete mode 100644 src/test/ui/borrowck/borrowck-insert-during-each.rs delete mode 100644 src/test/ui/borrowck/borrowck-insert-during-each.stderr delete mode 100644 src/test/ui/borrowck/borrowck-loan-rcvr.rs delete mode 100644 src/test/ui/borrowck/borrowck-loan-rcvr.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs delete mode 100644 src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr delete mode 100644 src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr delete mode 100644 src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs delete mode 100644 src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr delete mode 100644 src/test/ui/closures/closure-referencing-itself-issue-25954.rs delete mode 100644 src/test/ui/closures/closure-referencing-itself-issue-25954.stderr delete mode 100644 src/test/ui/consts/const-eval/ub-upvars.rs delete mode 100644 src/test/ui/consts/const-eval/ub-upvars.stderr delete mode 100644 src/test/ui/drop/dynamic-drop.rs delete mode 100644 src/test/ui/error-codes/E0504.rs delete mode 100644 src/test/ui/error-codes/E0504.stderr delete mode 100644 src/test/ui/functions-closures/clone-closure.rs delete mode 100644 src/test/ui/generator/dropck.rs delete mode 100644 src/test/ui/generator/dropck.stderr delete mode 100644 src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.rs delete mode 100644 src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr delete mode 100644 src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs delete mode 100644 src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr delete mode 100644 src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs delete mode 100644 src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr delete mode 100644 src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs delete mode 100644 src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr delete mode 100644 src/test/ui/issues/issue-29948.rs delete mode 100644 src/test/ui/issues/issue-4335.rs delete mode 100644 src/test/ui/issues/issue-4335.stderr delete mode 100644 src/test/ui/issues/issue-61623.rs delete mode 100644 src/test/ui/issues/issue-61623.stderr delete mode 100644 src/test/ui/mir/mir_calls_to_shims.rs delete mode 100644 src/test/ui/nll/closure-borrow-spans.rs delete mode 100644 src/test/ui/nll/closure-borrow-spans.stderr delete mode 100644 src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.rs delete mode 100644 src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr delete mode 100644 src/test/ui/nll/issue-51268.rs delete mode 100644 src/test/ui/nll/issue-51268.stderr delete mode 100644 src/test/ui/nll/issue-52663-span-decl-captured-variable.rs delete mode 100644 src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr delete mode 100644 src/test/ui/not-clone-closure.rs delete mode 100644 src/test/ui/not-clone-closure.stderr delete mode 100644 src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs delete mode 100644 src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr delete mode 100644 src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs delete mode 100644 src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr delete mode 100644 src/test/ui/span/dropck_misc_variants.rs delete mode 100644 src/test/ui/span/dropck_misc_variants.stderr delete mode 100644 src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs delete mode 100644 src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 1167988f62915..f7e386e090eaf 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -933,7 +933,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { /// - No Index projections are captured, since arrays are captured completely. fn truncate_projections_for_capture<'tcx>( mut place: Place<'tcx>, - capture_clause: hir::CaptureBy) -> Place<'tcx> { + capture_clause: hir::CaptureBy, +) -> Place<'tcx> { if place.projections.is_empty() { // Nothing to do here return place; @@ -969,7 +970,7 @@ fn truncate_projections_for_capture<'tcx>( ProjectionKind::Field(..) => { last_field_projection = Some(i); } - ProjectionKind::Subslice => {} // We never capture this + ProjectionKind::Subslice => {} // We never capture this } } diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs deleted file mode 100644 index 8ab6d141731ea..0000000000000 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ /dev/null @@ -1,126 +0,0 @@ -// min-lldb-version: 310 - -// compile-flags:-g - -// === GDB TESTS =================================================================================== - -// gdb-command:run - -// gdb-command:print variable -// gdb-check:$1 = 1 -// gdb-command:print constant -// gdb-check:$2 = 2 -// gdb-command:print a_struct -// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$3 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} -// gdb-command:print *struct_ref -// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$4 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} -// gdb-command:print *owned -// gdb-check:$5 = 6 -// gdb-command:print closure_local -// gdb-check:$6 = 8 -// gdb-command:continue - -// gdb-command:print variable -// gdb-check:$7 = 1 -// gdb-command:print constant -// gdb-check:$8 = 2 -// gdb-command:print a_struct -// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$9 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} -// gdb-command:print *struct_ref -// gdbg-check:$10 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$10 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} -// gdb-command:print *owned -// gdb-check:$11 = 6 -// gdb-command:print closure_local -// gdb-check:$12 = 8 -// gdb-command:continue - - -// === LLDB TESTS ================================================================================== - -// lldb-command:run - -// lldb-command:print variable -// lldbg-check:[...]$0 = 1 -// lldbr-check:(isize) variable = 1 -// lldb-command:print constant -// lldbg-check:[...]$1 = 2 -// lldbr-check:(isize) constant = 2 -// lldb-command:print a_struct -// lldbg-check:[...]$2 = { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 } -// lldb-command:print *struct_ref -// lldbg-check:[...]$3 = { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 } -// lldb-command:print *owned -// lldbg-check:[...]$4 = 6 -// lldbr-check:(isize) *owned = 6 -// lldb-command:print closure_local -// lldbg-check:[...]$5 = 8 -// lldbr-check:(isize) closure_local = 8 -// lldb-command:continue - -// lldb-command:print variable -// lldbg-check:[...]$6 = 1 -// lldbr-check:(isize) variable = 1 -// lldb-command:print constant -// lldbg-check:[...]$7 = 2 -// lldbr-check:(isize) constant = 2 -// lldb-command:print a_struct -// lldbg-check:[...]$8 = { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 } -// lldb-command:print *struct_ref -// lldbg-check:[...]$9 = { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 } -// lldb-command:print *owned -// lldbg-check:[...]$10 = 6 -// lldbr-check:(isize) *owned = 6 -// lldb-command:print closure_local -// lldbg-check:[...]$11 = 8 -// lldbr-check:(isize) closure_local = 8 -// lldb-command:continue - -#![allow(unused_variables)] -#![feature(box_syntax)] -#![feature(omit_gdb_pretty_printer_section)] -#![omit_gdb_pretty_printer_section] - -struct Struct { - a: isize, - b: f64, - c: usize -} - -fn main() { - let mut variable = 1; - let constant = 2; - - let a_struct = Struct { - a: -3, - b: 4.5, - c: 5 - }; - - let struct_ref = &a_struct; - let owned: Box<_> = box 6; - - let mut closure = || { - let closure_local = 8; - - let mut nested_closure = || { - zzz(); // #break - variable = constant + a_struct.a + struct_ref.a + *owned + closure_local; - }; - - zzz(); // #break - - nested_closure(); - }; - - closure(); -} - -fn zzz() {()} diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs deleted file mode 100644 index bd7c2bfe2c3ff..0000000000000 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ /dev/null @@ -1,82 +0,0 @@ -// min-lldb-version: 310 - -// compile-flags:-g - -// === GDB TESTS =================================================================================== - -// gdb-command:run - -// gdb-command:print constant -// gdb-check:$1 = 1 -// gdb-command:print a_struct -// gdbg-check:$2 = {a = -2, b = 3.5, c = 4} -// gdbr-check:$2 = var_captured_in_sendable_closure::Struct {a: -2, b: 3.5, c: 4} -// gdb-command:print *owned -// gdb-check:$3 = 5 -// gdb-command:continue - -// gdb-command:print constant2 -// gdb-check:$4 = 6 -// gdb-command:continue - -// === LLDB TESTS ================================================================================== - -// lldb-command:run - -// lldb-command:print constant -// lldbg-check:[...]$0 = 1 -// lldbr-check:(isize) constant = 1 -// lldb-command:print a_struct -// lldbg-check:[...]$1 = { a = -2 b = 3.5 c = 4 } -// lldbr-check:(var_captured_in_sendable_closure::Struct) a_struct = { a = -2 b = 3.5 c = 4 } -// lldb-command:print *owned -// lldbg-check:[...]$2 = 5 -// lldbr-check:(isize) *owned = 5 - -#![allow(unused_variables)] -#![feature(box_syntax)] -#![feature(omit_gdb_pretty_printer_section)] -#![omit_gdb_pretty_printer_section] - -struct Struct { - a: isize, - b: f64, - c: usize -} - -fn main() { - let constant = 1; - - let a_struct = Struct { - a: -2, - b: 3.5, - c: 4 - }; - - let owned: Box<_> = box 5; - - let closure = move || { - zzz(); // #break - do_something(&constant, &a_struct.a, &*owned); - }; - - closure(); - - let constant2 = 6_usize; - - // The `self` argument of the following closure should be passed by value - // to FnOnce::call_once(self, args), which gets codegened a bit differently - // than the regular case. Let's make sure this is supported too. - let immedate_env = move || { - zzz(); // #break - return constant2; - }; - - immedate_env(); -} - -fn do_something(_: &isize, _:&isize, _:&isize) { - -} - -fn zzz() {()} diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs deleted file mode 100644 index f53f8aaa6701e..0000000000000 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ /dev/null @@ -1,118 +0,0 @@ -// min-lldb-version: 310 - -// compile-flags:-g - -// === GDB TESTS =================================================================================== - -// gdb-command:run - -// gdb-command:print variable -// gdb-check:$1 = 1 -// gdb-command:print constant -// gdb-check:$2 = 2 -// gdb-command:print a_struct -// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$3 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} -// gdb-command:print *struct_ref -// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$4 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} -// gdb-command:print *owned -// gdb-check:$5 = 6 - -// gdb-command:continue - -// gdb-command:print variable -// gdb-check:$6 = 2 -// gdb-command:print constant -// gdb-check:$7 = 2 -// gdb-command:print a_struct -// gdbg-check:$8 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$8 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} -// gdb-command:print *struct_ref -// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} -// gdbr-check:$9 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} -// gdb-command:print *owned -// gdb-check:$10 = 6 - - -// === LLDB TESTS ================================================================================== - -// lldb-command:run - -// lldb-command:print variable -// lldbg-check:[...]$0 = 1 -// lldbr-check:(isize) variable = 1 -// lldb-command:print constant -// lldbg-check:[...]$1 = 2 -// lldbr-check:(isize) constant = 2 -// lldb-command:print a_struct -// lldbg-check:[...]$2 = { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 } -// lldb-command:print *struct_ref -// lldbg-check:[...]$3 = { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 } -// lldb-command:print *owned -// lldbg-check:[...]$4 = 6 -// lldbr-check:(isize) *owned = 6 - -// lldb-command:continue - -// lldb-command:print variable -// lldbg-check:[...]$5 = 2 -// lldbr-check:(isize) variable = 2 -// lldb-command:print constant -// lldbg-check:[...]$6 = 2 -// lldbr-check:(isize) constant = 2 -// lldb-command:print a_struct -// lldbg-check:[...]$7 = { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 } -// lldb-command:print *struct_ref -// lldbg-check:[...]$8 = { a = -3 b = 4.5 c = 5 } -// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 } -// lldb-command:print *owned -// lldbg-check:[...]$9 = 6 -// lldbr-check:(isize) *owned = 6 - -#![feature(box_syntax)] -#![allow(unused_variables)] -#![feature(omit_gdb_pretty_printer_section)] -#![omit_gdb_pretty_printer_section] - -struct Struct { - a: isize, - b: f64, - c: usize -} - -fn main() { - let mut variable = 1; - let constant = 2; - - let a_struct = Struct { - a: -3, - b: 4.5, - c: 5 - }; - - let struct_ref = &a_struct; - let owned: Box<_> = box 6; - - { - let mut first_closure = || { - zzz(); // #break - variable = constant + a_struct.a + struct_ref.a + *owned; - }; - - first_closure(); - } - - { - let mut second_closure = || { - zzz(); // #break - variable = constant + a_struct.a + struct_ref.a + *owned; - }; - second_closure(); - } -} - -fn zzz() {()} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs deleted file mode 100644 index ec752c15fa284..0000000000000 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs +++ /dev/null @@ -1,18 +0,0 @@ -// edition:2018 -// run-rustfix - -fn test_boxed() -> Box> { - let x = 0u32; - Box::new(async { x } ) - //~^ ERROR E0373 -} - -fn test_ref(x: &u32) -> impl std::future::Future + '_ { - async { *x } - //~^ ERROR E0373 -} - -fn main() { - let _ = test_boxed(); - let _ = test_ref(&0u32); -} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr deleted file mode 100644 index 7817f273d0614..0000000000000 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/async-borrowck-escaping-block-error.rs:6:20 - | -LL | Box::new(async { x } ) - | ^^-^^ - | | | - | | `x` is borrowed here - | may outlive borrowed value `x` - | -note: async block is returned here - --> $DIR/async-borrowck-escaping-block-error.rs:4:20 - | -LL | fn test_boxed() -> Box> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -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 } ) - | ^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/async-await/issues/issue-62097.nll.stderr b/src/test/ui/async-await/issues/issue-62097.nll.stderr deleted file mode 100644 index 2a399540e5296..0000000000000 --- a/src/test/ui/async-await/issues/issue-62097.nll.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function - --> $DIR/issue-62097.rs:13:13 - | -LL | foo(|| self.bar()).await; - | ^^ ---- `self` is borrowed here - | | - | may outlive borrowed value `self` - | -note: function requires argument type to outlive `'static` - --> $DIR/issue-62097.rs:13:9 - | -LL | foo(|| self.bar()).await; - | ^^^^^^^^^^^^^^^^^^ -help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword - | -LL | foo(move || self.bar()).await; - | ^^^^^^^ - -error[E0521]: borrowed data escapes outside of associated function - --> $DIR/issue-62097.rs:13:9 - | -LL | pub async fn run_dummy_fn(&self) { - | ----- `self` is a reference that is only valid in the associated function body -LL | foo(|| self.bar()).await; - | ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/async-await/issues/issue-62097.rs b/src/test/ui/async-await/issues/issue-62097.rs deleted file mode 100644 index 66ebbd83ffa9e..0000000000000 --- a/src/test/ui/async-await/issues/issue-62097.rs +++ /dev/null @@ -1,19 +0,0 @@ -// edition:2018 -async fn foo(fun: F) -where - F: FnOnce() + 'static -{ - fun() -} - -struct Struct; - -impl Struct { - pub async fn run_dummy_fn(&self) { //~ ERROR E0759 - foo(|| self.bar()).await; - } - - pub fn bar(&self) {} -} - -fn main() {} diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr deleted file mode 100644 index 0bd947c4bde2f..0000000000000 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error[E0521]: borrowed data escapes outside of associated function - --> $DIR/issue-62097.rs:13:9 - | -LL | pub async fn run_dummy_fn(&self) { - | ----- `self` is a reference that is only valid in the associated function body -LL | foo(|| self.bar()).await; - | ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here - -error: aborting due to previous error - diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs deleted file mode 100644 index 2dc405ffcd4c0..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs +++ /dev/null @@ -1,87 +0,0 @@ -// Tests that two closures cannot simultaneously have mutable -// and immutable access to the variable. Issue #6801. - -#![feature(box_syntax)] - -fn get(x: &isize) -> isize { - *x -} - -fn set(x: &mut isize) { - *x = 4; -} - -fn a() { - let mut x = 3; - let c1 = || x = 4; - let c2 = || x * 5; - //~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable - drop(c1); -} - -fn b() { - let mut x = 3; - let c1 = || set(&mut x); - let c2 = || get(&x); - //~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable - drop(c1); -} - -fn c() { - let mut x = 3; - let c1 = || set(&mut x); - let c2 = || x * 5; - //~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable - drop(c1); -} - -fn d() { - let mut x = 3; - let c2 = || x * 5; - x = 5; - //~^ ERROR cannot assign to `x` because it is borrowed - drop(c2); -} - -fn e() { - let mut x = 3; - let c1 = || get(&x); - x = 5; - //~^ ERROR cannot assign to `x` because it is borrowed - drop(c1); -} - -fn f() { - let mut x: Box<_> = box 3; - let c1 = || get(&*x); - *x = 5; - //~^ ERROR cannot assign to `*x` because it is borrowed - drop(c1); -} - -fn g() { - struct Foo { - f: Box - } - - let mut x: Box<_> = box Foo { f: box 3 }; - let c1 = || get(&*x.f); - *x.f = 5; - //~^ ERROR cannot assign to `*x.f` because it is borrowed - drop(c1); -} - -fn h() { - struct Foo { - f: Box - } - - let mut x: Box<_> = box Foo { f: box 3 }; - let c1 = || get(&*x.f); - let c2 = || *x.f = 5; - //~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable - drop(c1); -} - -fn main() { -} diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr deleted file mode 100644 index e468e71287bb5..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr +++ /dev/null @@ -1,116 +0,0 @@ -error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-closures-mut-and-imm.rs:17:14 - | -LL | let c1 = || x = 4; - | -- - first borrow occurs due to use of `x` in closure - | | - | mutable borrow occurs here -LL | let c2 = || x * 5; - | ^^ - second borrow occurs due to use of `x` in closure - | | - | immutable borrow occurs here -LL | -LL | drop(c1); - | -- mutable borrow later used here - -error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-closures-mut-and-imm.rs:25:14 - | -LL | let c1 = || set(&mut x); - | -- - first borrow occurs due to use of `x` in closure - | | - | mutable borrow occurs here -LL | let c2 = || get(&x); - | ^^ - second borrow occurs due to use of `x` in closure - | | - | immutable borrow occurs here -LL | -LL | drop(c1); - | -- mutable borrow later used here - -error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-closures-mut-and-imm.rs:33:14 - | -LL | let c1 = || set(&mut x); - | -- - first borrow occurs due to use of `x` in closure - | | - | mutable borrow occurs here -LL | let c2 = || x * 5; - | ^^ - second borrow occurs due to use of `x` in closure - | | - | immutable borrow occurs here -LL | -LL | drop(c1); - | -- mutable borrow later used here - -error[E0506]: cannot assign to `x` because it is borrowed - --> $DIR/borrowck-closures-mut-and-imm.rs:41:5 - | -LL | let c2 = || x * 5; - | -- - borrow occurs due to use in closure - | | - | borrow of `x` occurs here -LL | x = 5; - | ^^^^^ assignment to borrowed `x` occurs here -LL | -LL | drop(c2); - | -- borrow later used here - -error[E0506]: cannot assign to `x` because it is borrowed - --> $DIR/borrowck-closures-mut-and-imm.rs:49:5 - | -LL | let c1 = || get(&x); - | -- - borrow occurs due to use in closure - | | - | borrow of `x` occurs here -LL | x = 5; - | ^^^^^ assignment to borrowed `x` occurs here -LL | -LL | drop(c1); - | -- borrow later used here - -error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/borrowck-closures-mut-and-imm.rs:57:5 - | -LL | let c1 = || get(&*x); - | -- - borrow occurs due to use in closure - | | - | borrow of `*x` occurs here -LL | *x = 5; - | ^^^^^^ assignment to borrowed `*x` occurs here -LL | -LL | drop(c1); - | -- borrow later used here - -error[E0506]: cannot assign to `*x.f` because it is borrowed - --> $DIR/borrowck-closures-mut-and-imm.rs:69:5 - | -LL | let c1 = || get(&*x.f); - | -- - borrow occurs due to use in closure - | | - | borrow of `*x.f` occurs here -LL | *x.f = 5; - | ^^^^^^^^ assignment to borrowed `*x.f` occurs here -LL | -LL | drop(c1); - | -- borrow later used here - -error[E0502]: cannot borrow `*x.f` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-closures-mut-and-imm.rs:81:14 - | -LL | let c1 = || get(&*x.f); - | -- - first borrow occurs due to use of `*x.f` in closure - | | - | immutable borrow occurs here -LL | let c2 = || *x.f = 5; - | ^^ - second borrow occurs due to use of `*x.f` in closure - | | - | mutable borrow occurs here -LL | -LL | drop(c1); - | -- immutable borrow later used here - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0502, E0506. -For more information about an error, try `rustc --explain E0502`. diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs deleted file mode 100644 index d7e187a2b3958..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Tests that two closures cannot simultaneously have mutable -// and immutable access to the variable. Issue #6801. - -fn set(x: &mut isize) { - *x = 4; -} - -fn a(x: &isize) { - let mut c1 = || set(&mut *x); - //~^ ERROR cannot borrow - let mut c2 = || set(&mut *x); - //~^ ERROR cannot borrow - //~| ERROR two closures require unique access to `x` at the same time - c2(); c1(); -} - -fn main() { -} diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr deleted file mode 100644 index 84332fe67b5fe..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr +++ /dev/null @@ -1,41 +0,0 @@ -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrowck-closures-mut-of-imm.rs:9:25 - | -LL | fn a(x: &isize) { - | - help: consider changing this to be mutable: `mut x` -LL | let mut c1 = || set(&mut *x); - | ^^^^^^^ cannot borrow as mutable - -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/borrowck-closures-mut-of-imm.rs:11:25 - | -LL | fn a(x: &isize) { - | - help: consider changing this to be mutable: `mut x` -... -LL | let mut c2 = || set(&mut *x); - | ^^^^^^^ cannot borrow as mutable - -error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference - --> $DIR/borrowck-closures-mut-of-imm.rs:9:18 - | -LL | fn a(x: &isize) { - | ------ help: consider changing this to be a mutable reference: `&mut isize` -LL | let mut c1 = || set(&mut *x); - | ^^ - mutable borrow occurs due to use of `*x` in closure - | | - | `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable - -error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference - --> $DIR/borrowck-closures-mut-of-imm.rs:11:18 - | -LL | fn a(x: &isize) { - | ------ help: consider changing this to be a mutable reference: `&mut isize` -... -LL | let mut c2 = || set(&mut *x); - | ^^ - mutable borrow occurs due to use of `*x` in closure - | | - | `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.rs b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.rs deleted file mode 100644 index 50c6f2c585ed9..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Tests that two closures cannot simultaneously both have mutable -// access to the variable. Related to issue #6801. - -fn get(x: &isize) -> isize { - *x -} - -fn set(x: &mut isize) { - *x = 4; -} - -fn a(x: &mut isize) { - let mut c1 = || set(&mut *x); - let mut c2 = || set(&mut *x); - //~^ ERROR two closures require unique access to `x` at the same time - c2(); c1(); -} - -fn main() { -} diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr deleted file mode 100644 index 5369ab6b458b9..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0524]: two closures require unique access to `*x` at the same time - --> $DIR/borrowck-closures-mut-of-mut.rs:14:18 - | -LL | let mut c1 = || set(&mut *x); - | -- - first borrow occurs due to use of `*x` in closure - | | - | first closure is constructed here -LL | let mut c2 = || set(&mut *x); - | ^^ - second borrow occurs due to use of `*x` in closure - | | - | second closure is constructed here -LL | -LL | c2(); c1(); - | -- first borrow later used here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0524`. diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs deleted file mode 100644 index 0229ca37a692a..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Check that closure captures for slice patterns are inferred correctly - -#![allow(unused_variables)] - -// run-pass - -fn arr_by_ref(x: [String; 3]) { - let r = &x; - let f = || { - let [ref y, ref z @ ..] = x; - }; - f(); - f(); - // Ensure `x` was borrowed - drop(r); - // Ensure that `x` wasn't moved from. - drop(x); -} - -fn arr_by_mut(mut x: [String; 3]) { - let mut f = || { - let [ref mut y, ref mut z @ ..] = x; - }; - f(); - f(); - drop(x); -} - -fn arr_by_move(x: [String; 3]) { - let f = || { - let [y, z @ ..] = x; - }; - f(); -} - -fn arr_ref_by_ref(x: &[String; 3]) { - let r = &x; - let f = || { - let [ref y, ref z @ ..] = *x; - }; - let g = || { - let [y, z @ ..] = x; - }; - f(); - g(); - f(); - g(); - drop(r); - drop(x); -} - -fn arr_ref_by_mut(x: &mut [String; 3]) { - let mut f = || { - let [ref mut y, ref mut z @ ..] = *x; - }; - f(); - f(); - let mut g = || { - let [y, z @ ..] = x; - // Ensure binding mode was chosen correctly: - std::mem::swap(y, &mut z[0]); - }; - g(); - g(); - drop(x); -} - -fn arr_box_by_move(x: Box<[String; 3]>) { - let f = || { - let [y, z @ ..] = *x; - }; - f(); -} - -fn slice_by_ref(x: &[String]) { - let r = &x; - let f = || { - if let [ref y, ref z @ ..] = *x {} - }; - let g = || { - if let [y, z @ ..] = x {} - }; - f(); - g(); - f(); - g(); - drop(r); - drop(x); -} - -fn slice_by_mut(x: &mut [String]) { - let mut f = || { - if let [ref mut y, ref mut z @ ..] = *x {} - }; - f(); - f(); - let mut g = || { - if let [y, z @ ..] = x { - // Ensure binding mode was chosen correctly: - std::mem::swap(y, &mut z[0]); - } - }; - g(); - g(); - drop(x); -} - -fn main() { - arr_by_ref(Default::default()); - arr_by_mut(Default::default()); - arr_by_move(Default::default()); - arr_ref_by_ref(&Default::default()); - arr_ref_by_mut(&mut Default::default()); - arr_box_by_move(Default::default()); - slice_by_ref(&<[_; 3]>::default()); - slice_by_mut(&mut <[_; 3]>::default()); -} diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs deleted file mode 100644 index 2a1757231db85..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Tests that two closures cannot simultaneously have mutable -// access to the variable, whether that mutable access be used -// for direct assignment or for taking mutable ref. Issue #6801. - -#![feature(box_syntax)] - - - - - -fn to_fn_mut(f: F) -> F { f } - -fn a() { - let mut x = 3; - let c1 = to_fn_mut(|| x = 4); - let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once - c1; -} - -fn set(x: &mut isize) { - *x = 4; -} - -fn b() { - let mut x = 3; - let c1 = to_fn_mut(|| set(&mut x)); - let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - c1; -} - -fn c() { - let mut x = 3; - let c1 = to_fn_mut(|| x = 5); - let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - c1; -} - -fn d() { - let mut x = 3; - let c1 = to_fn_mut(|| x = 5); - let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) - //~^ ERROR cannot borrow `x` as mutable more than once - c1; -} - -fn g() { - struct Foo { - f: Box - } - - let mut x: Box<_> = box Foo { f: box 3 }; - let c1 = to_fn_mut(|| set(&mut *x.f)); - let c2 = to_fn_mut(|| set(&mut *x.f)); - //~^ ERROR cannot borrow `x` as mutable more than once - c1; -} - -fn main() { -} diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr deleted file mode 100644 index 7d635dae8fb01..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut-fail.rs:16:24 - | -LL | let c1 = to_fn_mut(|| x = 4); - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| x = 5); - | ^^ - second borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | c1; - | -- first borrow later used here - -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut-fail.rs:27:24 - | -LL | let c1 = to_fn_mut(|| set(&mut x)); - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut x)); - | ^^ - second borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | c1; - | -- first borrow later used here - -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut-fail.rs:34:24 - | -LL | let c1 = to_fn_mut(|| x = 5); - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut x)); - | ^^ - second borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | c1; - | -- first borrow later used here - -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut-fail.rs:41:24 - | -LL | let c1 = to_fn_mut(|| x = 5); - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) - | ^^ - second borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | -LL | c1; - | -- first borrow later used here - -error[E0499]: cannot borrow `*x.f` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut-fail.rs:53:24 - | -LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - first borrow occurs due to use of `*x.f` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - second borrow occurs due to use of `*x.f` in closure - | | - | second mutable borrow occurs here -LL | -LL | c1; - | -- first borrow later used here - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.rs b/src/test/ui/borrowck/borrowck-closures-two-mut.rs deleted file mode 100644 index 5fe51654f3b79..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Tests that two closures cannot simultaneously have mutable -// access to the variable, whether that mutable access be used -// for direct assignment or for taking mutable ref. Issue #6801. - -#![feature(box_syntax)] - -fn to_fn_mut(f: F) -> F { f } - -fn a() { - let mut x = 3; - let c1 = to_fn_mut(|| x = 4); - let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once - drop((c1, c2)); -} - -fn set(x: &mut isize) { - *x = 4; -} - -fn b() { - let mut x = 3; - let c1 = to_fn_mut(|| set(&mut x)); - let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - drop((c1, c2)); -} - -fn c() { - let mut x = 3; - let c1 = to_fn_mut(|| x = 5); - let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - drop((c1, c2)); -} - -fn d() { - let mut x = 3; - let c1 = to_fn_mut(|| x = 5); - let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) - //~^ ERROR cannot borrow `x` as mutable more than once - drop((c1, c2)); -} - -fn g() { - struct Foo { - f: Box - } - - let mut x: Box<_> = box Foo { f: box 3 }; - let c1 = to_fn_mut(|| set(&mut *x.f)); - let c2 = to_fn_mut(|| set(&mut *x.f)); - //~^ ERROR cannot borrow `x` as mutable more than once - drop((c1, c2)); -} - -fn main() { -} diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr deleted file mode 100644 index 2d47c3d82f33f..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut.rs:12:24 - | -LL | let c1 = to_fn_mut(|| x = 4); - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| x = 5); - | ^^ - second borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | drop((c1, c2)); - | -- first borrow later used here - -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut.rs:23:24 - | -LL | let c1 = to_fn_mut(|| set(&mut x)); - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut x)); - | ^^ - second borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | drop((c1, c2)); - | -- first borrow later used here - -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut.rs:30:24 - | -LL | let c1 = to_fn_mut(|| x = 5); - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut x)); - | ^^ - second borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | drop((c1, c2)); - | -- first borrow later used here - -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut.rs:37:24 - | -LL | let c1 = to_fn_mut(|| x = 5); - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) - | ^^ - second borrow occurs due to use of `x` in closure - | | - | second mutable borrow occurs here -LL | -LL | drop((c1, c2)); - | -- first borrow later used here - -error[E0499]: cannot borrow `*x.f` as mutable more than once at a time - --> $DIR/borrowck-closures-two-mut.rs:49:24 - | -LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - first borrow occurs due to use of `*x.f` in closure - | | - | first mutable borrow occurs here -LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - second borrow occurs due to use of `*x.f` in closure - | | - | second mutable borrow occurs here -LL | -LL | drop((c1, c2)); - | -- first borrow later used here - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/borrowck-closures-unique.rs b/src/test/ui/borrowck/borrowck-closures-unique.rs deleted file mode 100644 index 67f91dfa8420e..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-unique.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Tests that a closure which requires mutable access to the referent -// of an `&mut` requires a "unique" borrow -- that is, the variable to -// be borrowed (here, `x`) will not be borrowed *mutably*, but -// may be *immutable*, but we cannot allow -// multiple borrows. - - - -fn get(x: &isize) -> isize { - *x -} - -fn set(x: &mut isize) -> isize { - *x -} - -fn a(x: &mut isize) { - let c1 = || get(x); - let c2 = || get(x); - c1(); - c2(); -} - -fn b(x: &mut isize) { - let c1 = || get(x); - let c2 = || set(x); //~ ERROR closure requires unique access to `x` - c1; -} - -fn c(x: &mut isize) { - let c1 = || get(x); - let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x` - c1; -} - -fn d(x: &mut isize) { - let c1 = || set(x); - let c2 = || set(x); //~ ERROR two closures require unique access to `x` at the same time - c1; -} - -fn e(x: &'static mut isize) { - let c1 = |y: &'static mut isize| x = y; - //~^ ERROR cannot assign to `x`, as it is not declared as mutable - c1; -} - -fn f(x: &'static mut isize) { - let c1 = || x = panic!(); // OK assignment is unreachable. - c1; -} - -fn main() { -} diff --git a/src/test/ui/borrowck/borrowck-closures-unique.stderr b/src/test/ui/borrowck/borrowck-closures-unique.stderr deleted file mode 100644 index adeef5f9abff4..0000000000000 --- a/src/test/ui/borrowck/borrowck-closures-unique.stderr +++ /dev/null @@ -1,54 +0,0 @@ -error[E0500]: closure requires unique access to `*x` but it is already borrowed - --> $DIR/borrowck-closures-unique.rs:26:14 - | -LL | let c1 = || get(x); - | -- - first borrow occurs due to use of `*x` in closure - | | - | borrow occurs here -LL | let c2 = || set(x); - | ^^ - second borrow occurs due to use of `*x` in closure - | | - | closure construction occurs here -LL | c1; - | -- first borrow later used here - -error[E0500]: closure requires unique access to `*x` but it is already borrowed - --> $DIR/borrowck-closures-unique.rs:32:14 - | -LL | let c1 = || get(x); - | -- - first borrow occurs due to use of `*x` in closure - | | - | borrow occurs here -LL | let c2 = || { get(x); set(x); }; - | ^^ - second borrow occurs due to use of `*x` in closure - | | - | closure construction occurs here -LL | c1; - | -- first borrow later used here - -error[E0524]: two closures require unique access to `*x` at the same time - --> $DIR/borrowck-closures-unique.rs:38:14 - | -LL | let c1 = || set(x); - | -- - first borrow occurs due to use of `*x` in closure - | | - | first closure is constructed here -LL | let c2 = || set(x); - | ^^ - second borrow occurs due to use of `*x` in closure - | | - | second closure is constructed here -LL | c1; - | -- first borrow later used here - -error[E0594]: cannot assign to `x`, as it is not declared as mutable - --> $DIR/borrowck-closures-unique.rs:43:38 - | -LL | fn e(x: &'static mut isize) { - | - help: consider changing this to be mutable: `mut x` -LL | let c1 = |y: &'static mut isize| x = y; - | ^^^^^ cannot assign - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0500, E0524, E0594. -For more information about an error, try `rustc --explain E0500`. diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.rs b/src/test/ui/borrowck/borrowck-insert-during-each.rs deleted file mode 100644 index df967e6118932..0000000000000 --- a/src/test/ui/borrowck/borrowck-insert-during-each.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::collections::HashSet; - -struct Foo { - n: HashSet, -} - -impl Foo { - pub fn foo(&mut self, mut fun: F) where F: FnMut(&isize) { - for f in &self.n { - fun(f); - } - } -} - -fn bar(f: &mut Foo) { - f.foo( - //~^ ERROR cannot borrow `*f` as mutable - |a| { //~ ERROR closure requires unique access to `f` - f.n.insert(*a); - }) -} - -fn main() { - let mut f = Foo { n: HashSet::new() }; - bar(&mut f); -} diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.stderr b/src/test/ui/borrowck/borrowck-insert-during-each.stderr deleted file mode 100644 index bab77b7b8572f..0000000000000 --- a/src/test/ui/borrowck/borrowck-insert-during-each.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error[E0501]: cannot borrow `*f` as mutable because previous closure requires unique access - --> $DIR/borrowck-insert-during-each.rs:16:5 - | -LL | f.foo( - | ^ --- first borrow later used by call - | _____| - | | -LL | | -LL | | |a| { - | | --- closure construction occurs here -LL | | f.n.insert(*a); - | | - first borrow occurs due to use of `f.n` in closure -LL | | }) - | |__________^ second borrow occurs here - -error[E0500]: closure requires unique access to `f.n` but it is already borrowed - --> $DIR/borrowck-insert-during-each.rs:18:9 - | -LL | f.foo( - | - --- first borrow later used by call - | | - | borrow occurs here -LL | -LL | |a| { - | ^^^ closure construction occurs here -LL | f.n.insert(*a); - | - second borrow occurs due to use of `f.n` in closure - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0500, E0501. -For more information about an error, try `rustc --explain E0500`. diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr.rs b/src/test/ui/borrowck/borrowck-loan-rcvr.rs deleted file mode 100644 index d2234e17ac75c..0000000000000 --- a/src/test/ui/borrowck/borrowck-loan-rcvr.rs +++ /dev/null @@ -1,40 +0,0 @@ -struct Point { x: isize, y: isize } - -trait Methods { - fn impurem(&self); - fn blockm(&self, f: F) where F: FnOnce(); -} - -impl Methods for Point { - fn impurem(&self) { - } - - fn blockm(&self, f: F) where F: FnOnce() { f() } -} - -fn a() { - let mut p = Point {x: 3, y: 4}; - - // Here: it's ok to call even though receiver is mutable, because we - // can loan it out. - p.impurem(); - - // But in this case we do not honor the loan: - p.blockm(|| { //~ ERROR cannot borrow `p` as mutable - p.x = 10; - }) -} - -fn b() { - let mut p = Point {x: 3, y: 4}; - - // Here I create an outstanding loan and check that we get conflicts: - - let l = &mut p; - p.impurem(); //~ ERROR cannot borrow - - l.x += 1; -} - -fn main() { -} diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr deleted file mode 100644 index 118c6fc9ee2ac..0000000000000 --- a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0502]: cannot borrow `p.x` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-loan-rcvr.rs:23:14 - | -LL | p.blockm(|| { - | - ------ ^^ mutable borrow occurs here - | | | - | | immutable borrow later used by call - | immutable borrow occurs here -LL | p.x = 10; - | - second borrow occurs due to use of `p.x` in closure - -error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-loan-rcvr.rs:34:5 - | -LL | let l = &mut p; - | ------ mutable borrow occurs here -LL | p.impurem(); - | ^ immutable borrow occurs here -LL | -LL | l.x += 1; - | -------- mutable borrow later used here - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs deleted file mode 100644 index ffd2094295fb7..0000000000000 --- a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs +++ /dev/null @@ -1,48 +0,0 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented - -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 -#![feature(rustc_attrs)] - -struct Filter { - div: i32, -} -impl Filter { - fn allowed(&self, x: i32) -> bool { - x % self.div == 1 - } -} - -struct Data { - filter: Filter, - list: Vec, -} -impl Data { - fn update(&mut self) { - // The closure passed to filter only captures self.filter, - // therefore mutating self.list is allowed. - self.list.retain( - #[rustc_capture_analysis] - |v| { - self.filter.div += 1; - self.filter.allowed(*v) - } - //~^ ERROR: First Pass analysis includes: - //~| ERROR: Min Capture analysis includes: - //~| NOTE: Capturing self[Deref,(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture self[Deref,(0, 0)] -> ImmBorrow - ); - } -} - -fn main() { - let mut d = Data { filter: Filter { div: 3 }, list: Vec::new() }; - - for i in 1..10 { - d.list.push(i); - } - - d.update(); -} diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr deleted file mode 100644 index 34cddceb1ef0e..0000000000000 --- a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr +++ /dev/null @@ -1,46 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/filter-on-struct-member.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -error: First Pass analysis includes: - --> $DIR/filter-on-struct-member.rs:28:13 - | -LL | / |v| { -LL | | self.filter.div += 1; -LL | | self.filter.allowed(*v) -LL | | } - | |_____________^ - | -note: Capturing self[Deref,(0, 0),(0, 0)] -> UniqueImmBorrow - --> $DIR/filter-on-struct-member.rs:29:17 - | -LL | self.filter.div += 1; - | ^^^^^^^^^^^^^^^ -note: Capturing self[Deref,(0, 0)] -> ImmBorrow - --> $DIR/filter-on-struct-member.rs:30:17 - | -LL | self.filter.allowed(*v) - | ^^^^^^^^^^^ - -error: Min Capture analysis includes: - --> $DIR/filter-on-struct-member.rs:28:13 - | -LL | / |v| { -LL | | self.filter.div += 1; -LL | | self.filter.allowed(*v) -LL | | } - | |_____________^ - | -note: Min Capture self[Deref,(0, 0)] -> UniqueImmBorrow - --> $DIR/filter-on-struct-member.rs:29:17 - | -LL | self.filter.div += 1; - | ^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors; 1 warning emitted - diff --git a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr deleted file mode 100644 index 1d12e2f585e8d..0000000000000 --- a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5 - | -LL | fn foo(x: &()) { - | --- help: add explicit lifetime `'static` to the type of `x`: `&'static ()` -LL | / bar(|| { -LL | | -LL | | let _ = x; -LL | | }) - | |______^ lifetime `'static` required - -error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:9 - | -LL | bar(|| { - | ^^ may outlive borrowed value `x` -LL | -LL | let _ = x; - | - `x` is borrowed here - | -note: function requires argument type to outlive `'static` - --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5 - | -LL | / bar(|| { -LL | | -LL | | let _ = x; -LL | | }) - | |______^ -help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword - | -LL | bar(move || { - | ^^^^^^^ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0373, E0621. -For more information about an error, try `rustc --explain E0373`. diff --git a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs deleted file mode 100644 index 4fa5d54431c60..0000000000000 --- a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn bar(blk: F) where F: FnOnce() + 'static { -} - -fn foo(x: &()) { - bar(|| { - //~^ ERROR explicit lifetime required in the type of `x` [E0621] - let _ = x; - }) -} - -fn main() { -} diff --git a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr deleted file mode 100644 index f50c3e3b53159..0000000000000 --- a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5 - | -LL | fn foo(x: &()) { - | --- help: add explicit lifetime `'static` to the type of `x`: `&'static ()` -LL | bar(|| { - | ^^^ lifetime `'static` required - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/closures/closure-referencing-itself-issue-25954.rs b/src/test/ui/closures/closure-referencing-itself-issue-25954.rs deleted file mode 100644 index 7dd0e51797d8e..0000000000000 --- a/src/test/ui/closures/closure-referencing-itself-issue-25954.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Regression test for #25954: detect and reject a closure type that -// references itself. - -use std::cell::{Cell, RefCell}; - -struct A { - x: RefCell>, - b: Cell, -} - -fn main() { - let mut p = A{x: RefCell::new(None), b: Cell::new(4i32)}; - - // This is an error about types of infinite size: - let q = || p.b.set(5i32); //~ ERROR mismatched types - - *(p.x.borrow_mut()) = Some(q); -} diff --git a/src/test/ui/closures/closure-referencing-itself-issue-25954.stderr b/src/test/ui/closures/closure-referencing-itself-issue-25954.stderr deleted file mode 100644 index 8ca43cd1cffb1..0000000000000 --- a/src/test/ui/closures/closure-referencing-itself-issue-25954.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/closure-referencing-itself-issue-25954.rs:15:13 - | -LL | let q = || p.b.set(5i32); - | ^^^^^^^^^^^^^^^^ cyclic type of infinite size - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/consts/const-eval/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs deleted file mode 100644 index 5d19276557eb6..0000000000000 --- a/src/test/ui/consts/const-eval/ub-upvars.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here - -use std::mem; - -const BAD_UPVAR: &dyn FnOnce() = &{ //~ ERROR it is undefined behavior to use this value - let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; - let another_var = 13; - move || { let _ = bad_ref; let _ = another_var; } -}; - -fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-upvars.stderr b/src/test/ui/consts/const-eval/ub-upvars.stderr deleted file mode 100644 index afd6c9035cabf..0000000000000 --- a/src/test/ui/consts/const-eval/ub-upvars.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-upvars.rs:5:1 - | -LL | / const BAD_UPVAR: &dyn FnOnce() = &{ -LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; -LL | | let another_var = 13; -LL | | move || { let _ = bad_ref; let _ = another_var; } -LL | | }; - | |__^ type validation failed: encountered a NULL reference at ... - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs deleted file mode 100644 index ddccee20e12a6..0000000000000 --- a/src/test/ui/drop/dynamic-drop.rs +++ /dev/null @@ -1,620 +0,0 @@ -// run-pass -// ignore-wasm32-bare compiled with panic=abort by default - -#![feature(generators, generator_trait)] -#![feature(bindings_after_at)] -#![allow(unused_assignments)] -#![allow(unused_variables)] - -use std::cell::{Cell, RefCell}; -use std::mem::ManuallyDrop; -use std::ops::Generator; -use std::panic; -use std::pin::Pin; - -struct InjectedFailure; - -struct Allocator { - data: RefCell>, - name: &'static str, - failing_op: usize, - cur_ops: Cell, -} - -impl panic::UnwindSafe for Allocator {} -impl panic::RefUnwindSafe for Allocator {} - -impl Drop for Allocator { - fn drop(&mut self) { - let data = self.data.borrow(); - if data.iter().any(|d| *d) { - panic!("missing free in {:?}: {:?}", self.name, data); - } - } -} - -impl Allocator { - fn new(failing_op: usize, name: &'static str) -> Self { - Allocator { - failing_op: failing_op, - cur_ops: Cell::new(0), - data: RefCell::new(vec![]), - name, - } - } - fn alloc(&self) -> Ptr<'_> { - self.cur_ops.set(self.cur_ops.get() + 1); - - if self.cur_ops.get() == self.failing_op { - panic!(InjectedFailure); - } - - let mut data = self.data.borrow_mut(); - let addr = data.len(); - data.push(true); - Ptr(addr, self) - } -} - -struct Ptr<'a>(usize, &'a Allocator); -impl<'a> Drop for Ptr<'a> { - fn drop(&mut self) { - match self.1.data.borrow_mut()[self.0] { - false => panic!("double free in {:?} at index {:?}", self.1.name, self.0), - ref mut d => *d = false, - } - - self.1.cur_ops.set(self.1.cur_ops.get() + 1); - - if self.1.cur_ops.get() == self.1.failing_op { - panic!(InjectedFailure); - } - } -} - -fn dynamic_init(a: &Allocator, c: bool) { - let _x; - if c { - _x = Some(a.alloc()); - } -} - -fn dynamic_drop(a: &Allocator, c: bool) { - let x = a.alloc(); - if c { - Some(x) - } else { - None - }; -} - -struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>); -fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) { - for i in 0..2 { - let x; - let y; - if (c0 && i == 0) || (c1 && i == 1) { - x = (a.alloc(), a.alloc(), a.alloc()); - y = TwoPtrs(a.alloc(), a.alloc()); - if c { - drop(x.1); - drop(y.0); - } - } - } -} - -fn field_assignment(a: &Allocator, c0: bool) { - let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc()); - - x.1 = a.alloc(); - x.1 = a.alloc(); - - let f = (x.0).0; - if c0 { - (x.0).0 = f; - } -} - -fn assignment2(a: &Allocator, c0: bool, c1: bool) { - let mut _v = a.alloc(); - let mut _w = a.alloc(); - if c0 { - drop(_v); - } - _v = _w; - if c1 { - _w = a.alloc(); - } -} - -fn assignment1(a: &Allocator, c0: bool) { - let mut _v = a.alloc(); - let mut _w = a.alloc(); - if c0 { - drop(_v); - } - _v = _w; -} - -union Boxy { - a: ManuallyDrop, - b: ManuallyDrop, -} - -fn union1(a: &Allocator) { - unsafe { - let mut u = Boxy { a: ManuallyDrop::new(a.alloc()) }; - *u.b = a.alloc(); // drops first alloc - drop(ManuallyDrop::into_inner(u.a)); - } -} - -fn array_simple(a: &Allocator) { - let _x = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; -} - -fn vec_simple(a: &Allocator) { - let _x = vec![a.alloc(), a.alloc(), a.alloc(), a.alloc()]; -} - -fn generator(a: &Allocator, run_count: usize) { - assert!(run_count < 4); - - let mut gen = || { - (a.alloc(), yield a.alloc(), a.alloc(), yield a.alloc()); - }; - for _ in 0..run_count { - Pin::new(&mut gen).resume(()); - } -} - -fn mixed_drop_and_nondrop(a: &Allocator) { - // check that destructor panics handle drop - // and non-drop blocks in the same scope correctly. - // - // Surprisingly enough, this used to not work. - let (x, y, z); - x = a.alloc(); - y = 5; - z = a.alloc(); -} - -#[allow(unreachable_code)] -fn vec_unreachable(a: &Allocator) { - let _x = vec![a.alloc(), a.alloc(), a.alloc(), return]; -} - -fn slice_pattern_first(a: &Allocator) { - let [_x, ..] = [a.alloc(), a.alloc(), a.alloc()]; -} - -fn slice_pattern_middle(a: &Allocator) { - let [_, _x, _] = [a.alloc(), a.alloc(), a.alloc()]; -} - -fn slice_pattern_two(a: &Allocator) { - let [_x, _, _y, _] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; -} - -fn slice_pattern_last(a: &Allocator) { - let [.., _y] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; -} - -fn slice_pattern_one_of(a: &Allocator, i: usize) { - let array = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; - let _x = match i { - 0 => { - let [a, ..] = array; - a - } - 1 => { - let [_, a, ..] = array; - a - } - 2 => { - let [_, _, a, _] = array; - a - } - 3 => { - let [_, _, _, a] = array; - a - } - _ => panic!("unmatched"), - }; -} - -fn subslice_pattern_from_end(a: &Allocator, arg: bool) { - let a = [a.alloc(), a.alloc(), a.alloc()]; - if arg { - let [.., _x, _] = a; - } else { - let [_, _y @ ..] = a; - } -} - -fn subslice_pattern_from_end_with_drop(a: &Allocator, arg: bool, arg2: bool) { - let a = [a.alloc(), a.alloc(), a.alloc(), a.alloc(), a.alloc()]; - if arg2 { - drop(a); - return; - } - - if arg { - let [.., _x, _] = a; - } else { - let [_, _y @ ..] = a; - } -} - -fn slice_pattern_reassign(a: &Allocator) { - let mut ar = [a.alloc(), a.alloc()]; - let [_, _x] = ar; - ar = [a.alloc(), a.alloc()]; - let [.., _y] = ar; -} - -fn subslice_pattern_reassign(a: &Allocator) { - let mut ar = [a.alloc(), a.alloc(), a.alloc()]; - let [_, _, _x] = ar; - ar = [a.alloc(), a.alloc(), a.alloc()]; - let [_, _y @ ..] = ar; -} - -fn index_field_mixed_ends(a: &Allocator) { - let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())]; - let [(_x, _), ..] = ar; - let [(_, _y), _] = ar; - let [_, (_, _w)] = ar; - let [.., (_z, _)] = ar; -} - -fn subslice_mixed_min_lengths(a: &Allocator, c: i32) { - let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())]; - match c { - 0 => { - let [_x, ..] = ar; - } - 1 => { - let [_x, _, ..] = ar; - } - 2 => { - let [_x, _] = ar; - } - 3 => { - let [(_x, _), _, ..] = ar; - } - 4 => { - let [.., (_x, _)] = ar; - } - 5 => { - let [.., (_x, _), _] = ar; - } - 6 => { - let [_y @ ..] = ar; - } - _ => { - let [_y @ .., _] = ar; - } - } -} - -fn bindings_after_at_dynamic_init_move(a: &Allocator, c: bool) { - let foo = if c { Some(a.alloc()) } else { None }; - let _x; - - if let bar @ Some(_) = foo { - _x = bar; - } -} - -fn bindings_after_at_dynamic_init_ref(a: &Allocator, c: bool) { - let foo = if c { Some(a.alloc()) } else { None }; - let _x; - - if let bar @ Some(_baz) = &foo { - _x = bar; - } -} - -fn bindings_after_at_dynamic_drop_move(a: &Allocator, c: bool) { - let foo = if c { Some(a.alloc()) } else { None }; - - if let bar @ Some(_) = foo { - bar - } else { - None - }; -} - -fn bindings_after_at_dynamic_drop_ref(a: &Allocator, c: bool) { - let foo = if c { Some(a.alloc()) } else { None }; - - if let bar @ Some(_baz) = &foo { - bar - } else { - &None - }; -} - -fn move_ref_pattern(a: &Allocator) { - let mut tup = (a.alloc(), a.alloc(), a.alloc(), a.alloc()); - let (ref _a, ref mut _b, _c, mut _d) = tup; -} - -fn panic_after_return(a: &Allocator) -> Ptr<'_> { - a.alloc(); - let p = a.alloc(); - { - a.alloc(); - let p = a.alloc(); - a.alloc() - } -} - -fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> { - a.alloc(); - let p = a.alloc(); - { - a.alloc(); - let q = a.alloc(); - return a.alloc(); - } -} - -fn panic_after_init(a: &Allocator) { - a.alloc(); - let p = a.alloc(); - let q = { - a.alloc(); - let r = a.alloc(); - a.alloc() - }; -} - -fn panic_after_init_temp(a: &Allocator) { - a.alloc(); - let p = a.alloc(); - { - a.alloc(); - let r = a.alloc(); - a.alloc() - }; -} - -fn panic_after_init_by_loop(a: &Allocator) { - a.alloc(); - let p = a.alloc(); - let q = loop { - a.alloc(); - let r = a.alloc(); - break a.alloc(); - }; -} - -fn panic_after_init_by_match(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let _ = loop { - let q = match b { - true => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - false => { - a.alloc(); - let r = a.alloc(); - break a.alloc(); - } - }; - return; - }; -} - -fn panic_after_init_by_match_with_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - _ if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - _ => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - }; -} - -fn panic_after_init_by_match_with_bindings_and_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - _x if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - _x => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - }; -} - -fn panic_after_init_by_match_with_ref_bindings_and_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - ref _x if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - ref _x => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - }; -} - -fn panic_after_init_by_break_if(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = loop { - let r = a.alloc(); - break if b { - let s = a.alloc(); - a.alloc() - } else { - a.alloc() - }; - }; -} - -fn run_test(mut f: F, name: &'static str) -where - F: FnMut(&Allocator), -{ - let first_alloc = Allocator::new(usize::MAX, name); - f(&first_alloc); - - for failing_op in 1..first_alloc.cur_ops.get() + 1 { - let alloc = Allocator::new(failing_op, name); - let alloc = &alloc; - let f = panic::AssertUnwindSafe(&mut f); - let result = panic::catch_unwind(move || { - f.0(alloc); - }); - match result { - Ok(..) => panic!( - "test executed {} ops but now {}", - first_alloc.cur_ops.get(), - alloc.cur_ops.get() - ), - Err(e) => { - if e.downcast_ref::().is_none() { - panic::resume_unwind(e); - } - } - } - } -} - -fn run_test_nopanic(mut f: F, name: &'static str) -where - F: FnMut(&Allocator), -{ - let first_alloc = Allocator::new(usize::MAX, name); - f(&first_alloc); -} - -macro_rules! run_test { - ($e:expr) => { - run_test($e, stringify!($e)); - }; -} - -fn main() { - run_test!(|a| dynamic_init(a, false)); - run_test!(|a| dynamic_init(a, true)); - run_test!(|a| dynamic_drop(a, false)); - run_test!(|a| dynamic_drop(a, true)); - - run_test!(|a| assignment2(a, false, false)); - run_test!(|a| assignment2(a, false, true)); - run_test!(|a| assignment2(a, true, false)); - run_test!(|a| assignment2(a, true, true)); - - run_test!(|a| assignment1(a, false)); - run_test!(|a| assignment1(a, true)); - - run_test!(|a| array_simple(a)); - run_test!(|a| vec_simple(a)); - run_test!(|a| vec_unreachable(a)); - - run_test!(|a| struct_dynamic_drop(a, false, false, false)); - run_test!(|a| struct_dynamic_drop(a, false, false, true)); - run_test!(|a| struct_dynamic_drop(a, false, true, false)); - run_test!(|a| struct_dynamic_drop(a, false, true, true)); - run_test!(|a| struct_dynamic_drop(a, true, false, false)); - run_test!(|a| struct_dynamic_drop(a, true, false, true)); - run_test!(|a| struct_dynamic_drop(a, true, true, false)); - run_test!(|a| struct_dynamic_drop(a, true, true, true)); - - run_test!(|a| field_assignment(a, false)); - run_test!(|a| field_assignment(a, true)); - - run_test!(|a| generator(a, 0)); - run_test!(|a| generator(a, 1)); - run_test!(|a| generator(a, 2)); - run_test!(|a| generator(a, 3)); - - run_test!(|a| mixed_drop_and_nondrop(a)); - - run_test!(|a| slice_pattern_first(a)); - run_test!(|a| slice_pattern_middle(a)); - run_test!(|a| slice_pattern_two(a)); - run_test!(|a| slice_pattern_last(a)); - run_test!(|a| slice_pattern_one_of(a, 0)); - run_test!(|a| slice_pattern_one_of(a, 1)); - run_test!(|a| slice_pattern_one_of(a, 2)); - run_test!(|a| slice_pattern_one_of(a, 3)); - - run_test!(|a| subslice_pattern_from_end(a, true)); - run_test!(|a| subslice_pattern_from_end(a, false)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, true, true)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, true, false)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, false, true)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, false, false)); - run_test!(|a| slice_pattern_reassign(a)); - run_test!(|a| subslice_pattern_reassign(a)); - - run_test!(|a| index_field_mixed_ends(a)); - run_test!(|a| subslice_mixed_min_lengths(a, 0)); - run_test!(|a| subslice_mixed_min_lengths(a, 1)); - run_test!(|a| subslice_mixed_min_lengths(a, 2)); - run_test!(|a| subslice_mixed_min_lengths(a, 3)); - run_test!(|a| subslice_mixed_min_lengths(a, 4)); - run_test!(|a| subslice_mixed_min_lengths(a, 5)); - run_test!(|a| subslice_mixed_min_lengths(a, 6)); - run_test!(|a| subslice_mixed_min_lengths(a, 7)); - - run_test!(|a| move_ref_pattern(a)); - - run_test!(|a| { - panic_after_return(a); - }); - run_test!(|a| { - panic_after_return_expr(a); - }); - run_test!(|a| panic_after_init(a)); - run_test!(|a| panic_after_init_temp(a)); - run_test!(|a| panic_after_init_by_loop(a)); - run_test!(|a| panic_after_init_by_match(a, false)); - run_test!(|a| panic_after_init_by_match(a, true)); - run_test!(|a| panic_after_init_by_match_with_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_guard(a, true)); - run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, true)); - run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, true)); - run_test!(|a| panic_after_init_by_break_if(a, false)); - run_test!(|a| panic_after_init_by_break_if(a, true)); - - run_test!(|a| bindings_after_at_dynamic_init_move(a, true)); - run_test!(|a| bindings_after_at_dynamic_init_move(a, false)); - run_test!(|a| bindings_after_at_dynamic_init_ref(a, true)); - run_test!(|a| bindings_after_at_dynamic_init_ref(a, false)); - run_test!(|a| bindings_after_at_dynamic_drop_move(a, true)); - run_test!(|a| bindings_after_at_dynamic_drop_move(a, false)); - run_test!(|a| bindings_after_at_dynamic_drop_ref(a, true)); - run_test!(|a| bindings_after_at_dynamic_drop_ref(a, false)); - - run_test_nopanic(|a| union1(a), "|a| union1(a)"); -} diff --git a/src/test/ui/error-codes/E0504.rs b/src/test/ui/error-codes/E0504.rs deleted file mode 100644 index c2658bef61975..0000000000000 --- a/src/test/ui/error-codes/E0504.rs +++ /dev/null @@ -1,15 +0,0 @@ -struct FancyNum { - num: u8, -} - -fn main() { - let fancy_num = FancyNum { num: 5 }; - let fancy_ref = &fancy_num; - - let x = move || { //~ ERROR E0505 - println!("child function: {}", fancy_num.num); - }; - - x(); - println!("main function: {}", fancy_ref.num); -} diff --git a/src/test/ui/error-codes/E0504.stderr b/src/test/ui/error-codes/E0504.stderr deleted file mode 100644 index 1f2a0407a3963..0000000000000 --- a/src/test/ui/error-codes/E0504.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0505]: cannot move out of `fancy_num` because it is borrowed - --> $DIR/E0504.rs:9:13 - | -LL | let fancy_ref = &fancy_num; - | ---------- borrow of `fancy_num` occurs here -LL | -LL | let x = move || { - | ^^^^^^^ move out of `fancy_num` occurs here -LL | println!("child function: {}", fancy_num.num); - | --------- move occurs due to use in closure -... -LL | println!("main function: {}", fancy_ref.num); - | ------------- borrow later used here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0505`. diff --git a/src/test/ui/functions-closures/clone-closure.rs b/src/test/ui/functions-closures/clone-closure.rs deleted file mode 100644 index 1e725d8056d10..0000000000000 --- a/src/test/ui/functions-closures/clone-closure.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-pass -// Check that closures implement `Clone`. - -#[derive(Clone)] -struct S(i32); - -fn main() { - let mut a = S(5); - let mut hello = move || { - a.0 += 1; - println!("Hello {}", a.0); - a.0 - }; - - let mut hello2 = hello.clone(); - assert_eq!(6, hello2()); - assert_eq!(6, hello()); -} diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs deleted file mode 100644 index da00b230d9fb7..0000000000000 --- a/src/test/ui/generator/dropck.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![feature(generators, generator_trait, box_leak)] - -use std::cell::RefCell; -use std::ops::Generator; -use std::pin::Pin; - -fn main() { - let (mut gen, cell); - cell = Box::new(RefCell::new(0)); - let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); - //~^ ERROR `*cell` does not live long enough [E0597] - // the upvar is the non-dropck `&mut Option>`. - gen = || { - // but the generator can use it to drop a `Ref<'a, i32>`. - let _d = ref_.take(); //~ ERROR `ref_` does not live long enough - yield; - }; - Pin::new(&mut gen).resume(()); - // drops the RefCell and then the Ref, leading to use-after-free -} diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr deleted file mode 100644 index 089085de64c5c..0000000000000 --- a/src/test/ui/generator/dropck.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0597]: `*cell` does not live long enough - --> $DIR/dropck.rs:10:40 - | -LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); - | ^^^^ borrowed value does not live long enough -... -LL | } - | - - | | - | `*cell` dropped here while still borrowed - | borrow might be used here, when `gen` is dropped and runs the destructor for generator - | - = note: values in a scope are dropped in the opposite order they are defined - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.rs b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.rs deleted file mode 100644 index d17d6f07f6870..0000000000000 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.rs +++ /dev/null @@ -1,31 +0,0 @@ -// This is testing an attempt to corrupt the discriminant of the match -// arm in a guard, followed by an attempt to continue matching on that -// corrupted discriminant in the remaining match arms. -// -// Basically this is testing that our new NLL feature of emitting a -// fake read on each match arm is catching cases like this. -// -// This case is interesting because it includes a guard that -// diverges, and therefore a single final fake-read at the very end -// after the final match arm would not suffice. - -struct ForceFnOnce; - -fn main() { - let mut x = &mut Some(&2); - let force_fn_once = ForceFnOnce; - match x { - &mut None => panic!("unreachable"), - &mut Some(&_) if { - // ForceFnOnce needed to exploit #27282 - (|| { *x = None; drop(force_fn_once); })(); - //~^ ERROR cannot mutably borrow `x` in match guard [E0510] - false - } => {} - &mut Some(&a) if { // this binds to garbage if we've corrupted discriminant - println!("{}", a); - panic!() - } => {} - _ => panic!("unreachable"), - } -} diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr deleted file mode 100644 index 05080327feea8..0000000000000 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0510]: cannot mutably borrow `*x` in match guard - --> $DIR/issue-27282-mutate-before-diverging-arm-1.rs:21:14 - | -LL | match x { - | - value is immutable in match guard -... -LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `*x` in closure - | | - | cannot mutably borrow - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0510`. diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs deleted file mode 100644 index 9c3e7e9978ec7..0000000000000 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs +++ /dev/null @@ -1,40 +0,0 @@ -// This is testing an attempt to corrupt the discriminant of the match -// arm in a guard, followed by an attempt to continue matching on that -// corrupted discriminant in the remaining match arms. -// -// Basically this is testing that our new NLL feature of emitting a -// fake read on each match arm is catching cases like this. -// -// This case is interesting because it includes a guard that -// diverges, and therefore a single final fake-read at the very end -// after the final match arm would not suffice. -// -// It is also interesting because the access to the corrupted data -// occurs in the pattern-match itself, and not in the guard -// expression. - -struct ForceFnOnce; - -fn main() { - let mut x = &mut Some(&2); - let force_fn_once = ForceFnOnce; - match x { - &mut None => panic!("unreachable"), - &mut Some(&_) - if { - // ForceFnOnce needed to exploit #27282 - (|| { *x = None; drop(force_fn_once); })(); - //~^ ERROR cannot mutably borrow `x` in match guard [E0510] - false - } => {} - - // this segfaults if we corrupted the discriminant, because - // the compiler gets to *assume* that it cannot be the `None` - // case, even though that was the effect of the guard. - &mut Some(&2) - if { - panic!() - } => {} - _ => panic!("unreachable"), - } -} diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr deleted file mode 100644 index d986aeccaba56..0000000000000 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0510]: cannot mutably borrow `*x` in match guard - --> $DIR/issue-27282-mutate-before-diverging-arm-2.rs:26:18 - | -LL | match x { - | - value is immutable in match guard -... -LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `*x` in closure - | | - | cannot mutably borrow - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0510`. diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs deleted file mode 100644 index cff9e963e2725..0000000000000 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs +++ /dev/null @@ -1,30 +0,0 @@ -// This is testing an attempt to corrupt the discriminant of the match -// arm in a guard, followed by an attempt to continue matching on that -// corrupted discriminant in the remaining match arms. -// -// Basically this is testing that our new NLL feature of emitting a -// fake read on each match arm is catching cases like this. -// -// This case is interesting because a borrow of **x is untracked, because **x is -// immutable. However, for matches we care that **x refers to the same value -// until we have chosen a match arm. - -struct ForceFnOnce; -fn main() { - let mut x = &mut &Some(&2); - let force_fn_once = ForceFnOnce; - match **x { - None => panic!("unreachable"), - Some(&_) if { - // ForceFnOnce needed to exploit #27282 - (|| { *x = &None; drop(force_fn_once); })(); - //~^ ERROR cannot mutably borrow `x` in match guard [E0510] - false - } => {} - Some(&a) if { // this binds to garbage if we've corrupted discriminant - println!("{}", a); - panic!() - } => {} - _ => panic!("unreachable"), - } -} diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr deleted file mode 100644 index 3780fe7da0e1a..0000000000000 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0510]: cannot mutably borrow `*x` in match guard - --> $DIR/issue-27282-mutate-before-diverging-arm-3.rs:20:14 - | -LL | match **x { - | --- value is immutable in match guard -... -LL | (|| { *x = &None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `*x` in closure - | | - | cannot mutably borrow - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0510`. diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs deleted file mode 100644 index 82d8b9e9ed977..0000000000000 --- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Issue 27282: This is a variation on issue-27282-move-ref-mut-into-guard.rs -// -// It reborrows instead of moving the `ref mut` pattern borrow. This -// means that our conservative check for mutation in guards will -// reject it. But I want to make sure that we continue to reject it -// (under NLL) even when that conservaive check goes away. - -fn main() { - let mut b = &mut true; - match b { - &mut false => {}, - ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); - //~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard - false } => { &mut *r; }, - &mut true => { println!("You might think we should get here"); }, - _ => panic!("surely we could never get here, since rustc warns it is unreachable."), - } -} diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr deleted file mode 100644 index 8cdb7c7521f09..0000000000000 --- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0596]: cannot borrow `*r` as mutable, as it is immutable for the pattern guard - --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25 - | -LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); - | ^^ - mutable borrow occurs due to use of `*r` in closure - | | - | cannot borrow as mutable - | - = note: variables bound in patterns are immutable until the end of the pattern guard - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/issues/issue-29948.rs b/src/test/ui/issues/issue-29948.rs deleted file mode 100644 index 8ede8143ea657..0000000000000 --- a/src/test/ui/issues/issue-29948.rs +++ /dev/null @@ -1,40 +0,0 @@ -// run-pass -// ignore-wasm32-bare compiled with panic=abort by default - -use std::panic; - -impl<'a> panic::UnwindSafe for Foo<'a> {} -impl<'a> panic::RefUnwindSafe for Foo<'a> {} - -struct Foo<'a>(&'a mut bool); - -impl<'a> Drop for Foo<'a> { - fn drop(&mut self) { - *self.0 = true; - } -} - -fn f(t: T) { - t() -} - -fn main() { - let mut ran_drop = false; - { - let x = Foo(&mut ran_drop); - let x = move || { let _ = x; }; - f(x); - } - assert!(ran_drop); - - let mut ran_drop = false; - { - let x = Foo(&mut ran_drop); - let result = panic::catch_unwind(move || { - let x = move || { let _ = x; panic!() }; - f(x); - }); - assert!(result.is_err()); - } - assert!(ran_drop); -} diff --git a/src/test/ui/issues/issue-4335.rs b/src/test/ui/issues/issue-4335.rs deleted file mode 100644 index c5914a17cf924..0000000000000 --- a/src/test/ui/issues/issue-4335.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(fn_traits)] - -fn id(t: T) -> T { t } - -fn f<'r, T>(v: &'r T) -> Box T + 'r> { - id(Box::new(|| *v)) - //~^ ERROR E0507 -} - -fn main() { - let v = &5; - println!("{}", f(v).call_mut(())); -} diff --git a/src/test/ui/issues/issue-4335.stderr b/src/test/ui/issues/issue-4335.stderr deleted file mode 100644 index dfe8fa85b63c8..0000000000000 --- a/src/test/ui/issues/issue-4335.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0507]: cannot move out of `v`, a captured variable in an `FnMut` closure - --> $DIR/issue-4335.rs:6:20 - | -LL | fn f<'r, T>(v: &'r T) -> Box T + 'r> { - | - captured outer variable -LL | id(Box::new(|| *v)) - | ^^ move occurs because `v` has type `T`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `*v` which is behind a shared reference - --> $DIR/issue-4335.rs:6:17 - | -LL | id(Box::new(|| *v)) - | ^^ -- - | | | - | | move occurs because `*v` has type `T`, which does not implement the `Copy` trait - | | move occurs due to use in closure - | move out of `*v` occurs here - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/issues/issue-61623.rs b/src/test/ui/issues/issue-61623.rs deleted file mode 100644 index e5b8747bd8047..0000000000000 --- a/src/test/ui/issues/issue-61623.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn f1<'a>(_: &'a mut ()) {} - -fn f2

(_: P, _: ()) {} - -fn f3<'a>(x: &'a ((), &'a mut ())) { - f2(|| x.0, f1(x.1)) -//~^ ERROR cannot borrow `*x.1` as mutable, as it is behind a `&` reference -//~| ERROR cannot borrow `*x.1` as mutable because it is also borrowed as immutable -} - -fn main() {} diff --git a/src/test/ui/issues/issue-61623.stderr b/src/test/ui/issues/issue-61623.stderr deleted file mode 100644 index f654605423379..0000000000000 --- a/src/test/ui/issues/issue-61623.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0596]: cannot borrow `*x.1` as mutable, as it is behind a `&` reference - --> $DIR/issue-61623.rs:6:19 - | -LL | fn f3<'a>(x: &'a ((), &'a mut ())) { - | -------------------- help: consider changing this to be a mutable reference: `&'a mut ((), &'a mut ())` -LL | f2(|| x.0, f1(x.1)) - | ^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/mir/mir_calls_to_shims.rs b/src/test/ui/mir/mir_calls_to_shims.rs deleted file mode 100644 index 6f13d5612ce51..0000000000000 --- a/src/test/ui/mir/mir_calls_to_shims.rs +++ /dev/null @@ -1,49 +0,0 @@ -// run-pass -// ignore-wasm32-bare compiled with panic=abort by default - -#![feature(fn_traits)] -#![feature(never_type)] - -use std::panic; - -fn foo(x: u32, y: u32) -> u32 { x/y } -fn foo_diverges() -> ! { panic!() } - -fn test_fn_ptr(mut t: T) - where T: Fn(u32, u32) -> u32, -{ - let as_fn = >::call; - assert_eq!(as_fn(&t, (9, 3)), 3); - let as_fn_mut = >::call_mut; - assert_eq!(as_fn_mut(&mut t, (18, 3)), 6); - let as_fn_once = >::call_once; - assert_eq!(as_fn_once(t, (24, 3)), 8); -} - -fn assert_panics(f: F) where F: FnOnce() { - let f = panic::AssertUnwindSafe(f); - let result = panic::catch_unwind(move || { - f.0() - }); - if let Ok(..) = result { - panic!("diverging function returned"); - } -} - -fn test_fn_ptr_panic(mut t: T) - where T: Fn() -> ! -{ - let as_fn = >::call; - assert_panics(|| as_fn(&t, ())); - let as_fn_mut = >::call_mut; - assert_panics(|| as_fn_mut(&mut t, ())); - let as_fn_once = >::call_once; - assert_panics(|| as_fn_once(t, ())); -} - -fn main() { - test_fn_ptr(foo); - test_fn_ptr(foo as fn(u32, u32) -> u32); - test_fn_ptr_panic(foo_diverges); - test_fn_ptr_panic(foo_diverges as fn() -> !); -} diff --git a/src/test/ui/nll/closure-borrow-spans.rs b/src/test/ui/nll/closure-borrow-spans.rs deleted file mode 100644 index b38f7900e8e5e..0000000000000 --- a/src/test/ui/nll/closure-borrow-spans.rs +++ /dev/null @@ -1,100 +0,0 @@ -// check that existing borrows due to a closure capture give a special note - -fn move_while_borrowed(x: String) { - let f = || x.len(); - let y = x; //~ ERROR - f.use_ref(); -} - -fn borrow_mut_while_borrowed(mut x: i32) { - let f = || x; - let y = &mut x; //~ ERROR - f.use_ref(); -} - -fn drop_while_borrowed() { - let f; - { - let x = 1; - f = || x; //~ ERROR - } - f.use_ref(); -} - -fn assign_while_borrowed(mut x: i32) { - let f = || x; - x = 1; //~ ERROR - f.use_ref(); -} - -fn copy_while_borrowed_mut(mut x: i32) { - let f = || x = 0; - let y = x; //~ ERROR - f.use_ref(); -} - -fn borrow_while_borrowed_mut(mut x: i32) { - let f = || x = 0; - let y = &x; //~ ERROR - f.use_ref(); -} - -fn borrow_mut_while_borrowed_mut(mut x: i32) { - let f = || x = 0; - let y = &mut x; //~ ERROR - f.use_ref(); -} - -fn drop_while_borrowed_mut() { - let f; - { - let mut x = 1; - f = || x = 0; //~ ERROR - } - f.use_ref(); -} - -fn assign_while_borrowed_mut(mut x: i32) { - let f = || x = 0; - x = 1; //~ ERROR - f.use_ref(); -} - -fn copy_while_borrowed_unique(x: &mut i32) { - let f = || *x = 0; - let y = x; //~ ERROR - f.use_ref(); -} - -fn borrow_while_borrowed_unique(x: &mut i32) { - let f = || *x = 0; - let y = &x; //~ ERROR - f.use_ref(); -} - -fn borrow_mut_while_borrowed_unique(mut x: &mut i32) { - let f = || *x = 0; - let y = &mut x; //~ ERROR - f.use_ref(); -} - -fn drop_while_borrowed_unique() { - let mut z = 1; - let f; - { - let x = &mut z; - f = || *x = 0; //~ ERROR - } - f.use_ref(); -} - -fn assign_while_borrowed_unique(x: &mut i32) { - let f = || *x = 0; - *x = 1; //~ ERROR - f.use_ref(); -} - -fn main() {} - -trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } -impl Fake for T { } diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr deleted file mode 100644 index 153156d8ba3d1..0000000000000 --- a/src/test/ui/nll/closure-borrow-spans.stderr +++ /dev/null @@ -1,160 +0,0 @@ -error[E0505]: cannot move out of `x` because it is borrowed - --> $DIR/closure-borrow-spans.rs:5:13 - | -LL | let f = || x.len(); - | -- - borrow occurs due to use in closure - | | - | borrow of `x` occurs here -LL | let y = x; - | ^ move out of `x` occurs here -LL | f.use_ref(); - | - borrow later used here - -error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/closure-borrow-spans.rs:11:13 - | -LL | let f = || x; - | -- - first borrow occurs due to use of `x` in closure - | | - | immutable borrow occurs here -LL | let y = &mut x; - | ^^^^^^ mutable borrow occurs here -LL | f.use_ref(); - | - immutable borrow later used here - -error[E0597]: `x` does not live long enough - --> $DIR/closure-borrow-spans.rs:19:16 - | -LL | f = || x; - | -- ^ borrowed value does not live long enough - | | - | value captured here -LL | } - | - `x` dropped here while still borrowed -LL | f.use_ref(); - | - borrow later used here - -error[E0506]: cannot assign to `x` because it is borrowed - --> $DIR/closure-borrow-spans.rs:26:5 - | -LL | let f = || x; - | -- - borrow occurs due to use in closure - | | - | borrow of `x` occurs here -LL | x = 1; - | ^^^^^ assignment to borrowed `x` occurs here -LL | f.use_ref(); - | - borrow later used here - -error[E0503]: cannot use `x` because it was mutably borrowed - --> $DIR/closure-borrow-spans.rs:32:13 - | -LL | let f = || x = 0; - | -- - borrow occurs due to use of `x` in closure - | | - | borrow of `x` occurs here -LL | let y = x; - | ^ use of borrowed `x` -LL | f.use_ref(); - | - borrow later used here - -error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/closure-borrow-spans.rs:38:13 - | -LL | let f = || x = 0; - | -- - first borrow occurs due to use of `x` in closure - | | - | mutable borrow occurs here -LL | let y = &x; - | ^^ immutable borrow occurs here -LL | f.use_ref(); - | - mutable borrow later used here - -error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/closure-borrow-spans.rs:44:13 - | -LL | let f = || x = 0; - | -- - first borrow occurs due to use of `x` in closure - | | - | first mutable borrow occurs here -LL | let y = &mut x; - | ^^^^^^ second mutable borrow occurs here -LL | f.use_ref(); - | - first borrow later used here - -error[E0597]: `x` does not live long enough - --> $DIR/closure-borrow-spans.rs:52:16 - | -LL | f = || x = 0; - | -- ^ borrowed value does not live long enough - | | - | value captured here -LL | } - | - `x` dropped here while still borrowed -LL | f.use_ref(); - | - borrow later used here - -error[E0506]: cannot assign to `x` because it is borrowed - --> $DIR/closure-borrow-spans.rs:59:5 - | -LL | let f = || x = 0; - | -- - borrow occurs due to use in closure - | | - | borrow of `x` occurs here -LL | x = 1; - | ^^^^^ assignment to borrowed `x` occurs here -LL | f.use_ref(); - | - borrow later used here - -error[E0505]: cannot move out of `x` because it is borrowed - --> $DIR/closure-borrow-spans.rs:65:13 - | -LL | let f = || *x = 0; - | -- - borrow occurs due to use in closure - | | - | borrow of `*x` occurs here -LL | let y = x; - | ^ move out of `x` occurs here -LL | f.use_ref(); - | - borrow later used here - -error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access - --> $DIR/closure-borrow-spans.rs:71:13 - | -LL | let f = || *x = 0; - | -- - first borrow occurs due to use of `*x` in closure - | | - | closure construction occurs here -LL | let y = &x; - | ^^ second borrow occurs here -LL | f.use_ref(); - | - first borrow later used here - -error[E0501]: cannot borrow `x` as mutable because previous closure requires unique access - --> $DIR/closure-borrow-spans.rs:77:13 - | -LL | let f = || *x = 0; - | -- - first borrow occurs due to use of `*x` in closure - | | - | closure construction occurs here -LL | let y = &mut x; - | ^^^^^^ second borrow occurs here -LL | f.use_ref(); - | - first borrow later used here - -error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/closure-borrow-spans.rs:93:5 - | -LL | let f = || *x = 0; - | -- - borrow occurs due to use in closure - | | - | borrow of `*x` occurs here -LL | *x = 1; - | ^^^^^^ assignment to borrowed `*x` occurs here -LL | f.use_ref(); - | - borrow later used here - -error: aborting due to 13 previous errors - -Some errors have detailed explanations: E0499, E0501, E0502, E0503, E0505, E0506, E0597. -For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.rs b/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.rs deleted file mode 100644 index f45370e5c2e5b..0000000000000 --- a/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.rs +++ /dev/null @@ -1,13 +0,0 @@ -// This test illustrates a case where full NLL (enabled by the feature -// switch below) produces superior diagnostics to the NLL-migrate -// mode. - -#![feature(nll)] - -fn doit(data: &'static mut ()) { - || doit(data); - //~^ ERROR lifetime may not live long enough - //~| ERROR `data` does not live long enough -} - -fn main() { } diff --git a/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr b/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr deleted file mode 100644 index 7105c1112c854..0000000000000 --- a/src/test/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/issue-42574-diagnostic-in-nested-closure.rs:8:8 - | -LL | || doit(data); - | -- ^^^^^^^^^^ argument requires that `'1` must outlive `'static` - | | - | lifetime `'1` represents this closure's body - | - = note: closure implements `FnMut`, so references to captured variables can't escape the closure - -error: aborting due to previous error - diff --git a/src/test/ui/nll/issue-51268.rs b/src/test/ui/nll/issue-51268.rs deleted file mode 100644 index 12d0449abb19b..0000000000000 --- a/src/test/ui/nll/issue-51268.rs +++ /dev/null @@ -1,23 +0,0 @@ -// ignore-tidy-linelength - -struct Bar; - -impl Bar { - fn bar(&mut self, _: impl Fn()) {} -} - -struct Foo { - thing: Bar, - number: usize, -} - -impl Foo { - fn foo(&mut self) { - self.thing.bar(|| { - //~^ ERROR cannot borrow `self.thing` as mutable because it is also borrowed as immutable [E0502] - &self.number; - }); - } -} - -fn main() {} diff --git a/src/test/ui/nll/issue-51268.stderr b/src/test/ui/nll/issue-51268.stderr deleted file mode 100644 index 420c94f8e1bd2..0000000000000 --- a/src/test/ui/nll/issue-51268.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0502]: cannot borrow `self.thing` as mutable because it is also borrowed as immutable - --> $DIR/issue-51268.rs:16:9 - | -LL | self.thing.bar(|| { - | ^ --- -- immutable borrow occurs here - | | | - | _________| immutable borrow later used by call - | | -LL | | -LL | | &self.number; - | | ---- first borrow occurs due to use of `self` in closure -LL | | }); - | |__________^ mutable borrow occurs here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs b/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs deleted file mode 100644 index cd1f457a13064..0000000000000 --- a/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn expect_fn(f: F) where F : Fn() { - f(); -} - -fn main() { - { - let x = (vec![22], vec![44]); - expect_fn(|| drop(x.0)); - //~^ ERROR cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure [E0507] - } -} diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr deleted file mode 100644 index 5ba006a487108..0000000000000 --- a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure - --> $DIR/issue-52663-span-decl-captured-variable.rs:8:26 - | -LL | let x = (vec![22], vec![44]); - | - captured outer variable -LL | expect_fn(|| drop(x.0)); - | ^^^ move occurs because `x` has type `Vec`, which does not implement the `Copy` trait - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/not-clone-closure.rs b/src/test/ui/not-clone-closure.rs deleted file mode 100644 index 25635bc833181..0000000000000 --- a/src/test/ui/not-clone-closure.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Check that closures do not implement `Clone` if their environment is not `Clone`. - -struct S(i32); - -fn main() { - let a = S(5); - let hello = move || { - println!("Hello {}", a.0); - }; - - let hello = hello.clone(); //~ ERROR the trait bound `S: Clone` is not satisfied -} diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr deleted file mode 100644 index a62c21f2ee971..0000000000000 --- a/src/test/ui/not-clone-closure.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]` - --> $DIR/not-clone-closure.rs:11:23 - | -LL | let hello = move || { - | _________________- -LL | | println!("Hello {}", a.0); -LL | | }; - | |_____- within this `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]` -LL | -LL | let hello = hello.clone(); - | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`, the trait `Clone` is not implemented for `S` - | - = note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs deleted file mode 100644 index 9c320edc4dc0e..0000000000000 --- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs +++ /dev/null @@ -1,48 +0,0 @@ -fn main() {} - -struct U; - -fn slice() { - let mut arr = [U, U, U, U, U]; - let hold_all = &arr; - let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; //~ ERROR cannot move out of `arr[..]` - _x1 = U; //~ ERROR cannot assign twice to immutable variable `_x1` - drop(hold_all); - let [_x0, ..] = arr; //~ ERROR cannot move out of `arr[..]` - drop(_x0_hold); - let [_, _, ref mut _x2, _x3, mut _x4] = arr; - //~^ ERROR cannot borrow `arr[..]` as mutable - //~| ERROR cannot move out of `arr[..]` because it is borrowed - //~| ERROR cannot move out of `arr[..]` because it is borrowed - drop(xs_hold); -} - -fn tuple() { - let mut tup = (U, U, U, U); - let (ref _x0, _x1, ref _x2, ..) = tup; - _x1 = U; //~ ERROR cannot assign twice to immutable variable - let _x0_hold = &mut tup.0; //~ ERROR cannot borrow `tup.0` as mutable because it is also - let (ref mut _x0_hold, ..) = tup; //~ ERROR cannot borrow `tup.0` as mutable because it is also - *_x0 = U; //~ ERROR cannot assign to `*_x0` which is behind a `&` reference - *_x2 = U; //~ ERROR cannot assign to `*_x2` which is behind a `&` reference - drop(tup.1); //~ ERROR use of moved value: `tup.1` - let _x1_hold = &tup.1; //~ ERROR borrow of moved value: `tup.1` - let (.., ref mut _x3) = tup; - let _x3_hold = &tup.3; //~ ERROR cannot borrow `tup.3` as immutable - let _x3_hold = &mut tup.3; //~ ERROR cannot borrow `tup.3` as mutable more - let (.., ref mut _x4_hold) = tup; //~ ERROR cannot borrow `tup.3` as mutable more - let (.., ref _x4_hold) = tup; //~ ERROR cannot borrow `tup.3` as immutable - drop(_x3); -} - -fn closure() { - let mut tup = (U, U, U); - let c1 = || { - let (ref _x0, _x1, _) = tup; - }; - let c2 = || { - //~^ ERROR use of moved value - let (ref mut _x0, _, _x2) = tup; - }; - drop(c1); -} diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr deleted file mode 100644 index 285c203f382df..0000000000000 --- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr +++ /dev/null @@ -1,208 +0,0 @@ -error[E0505]: cannot move out of `arr[..]` because it is borrowed - --> $DIR/borrowck-move-ref-pattern.rs:8:24 - | -LL | let hold_all = &arr; - | ---- borrow of `arr` occurs here -LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; - | ^^^ move out of `arr[..]` occurs here -LL | _x1 = U; -LL | drop(hold_all); - | -------- borrow later used here - -error[E0384]: cannot assign twice to immutable variable `_x1` - --> $DIR/borrowck-move-ref-pattern.rs:9:5 - | -LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; - | --- - | | - | first assignment to `_x1` - | help: make this binding mutable: `mut _x1` -LL | _x1 = U; - | ^^^^^^^ cannot assign twice to immutable variable - -error[E0505]: cannot move out of `arr[..]` because it is borrowed - --> $DIR/borrowck-move-ref-pattern.rs:11:10 - | -LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; - | ------------ borrow of `arr[..]` occurs here -... -LL | let [_x0, ..] = arr; - | ^^^ move out of `arr[..]` occurs here -LL | drop(_x0_hold); - | -------- borrow later used here - -error[E0502]: cannot borrow `arr[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-move-ref-pattern.rs:13:16 - | -LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; - | ---------------- immutable borrow occurs here -... -LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; - | ^^^^^^^^^^^ mutable borrow occurs here -... -LL | drop(xs_hold); - | ------- immutable borrow later used here - -error[E0505]: cannot move out of `arr[..]` because it is borrowed - --> $DIR/borrowck-move-ref-pattern.rs:13:29 - | -LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; - | ---------------- borrow of `arr[..]` occurs here -... -LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; - | ^^^ move out of `arr[..]` occurs here -... -LL | drop(xs_hold); - | ------- borrow later used here - -error[E0505]: cannot move out of `arr[..]` because it is borrowed - --> $DIR/borrowck-move-ref-pattern.rs:13:34 - | -LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; - | ---------------- borrow of `arr[..]` occurs here -... -LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; - | ^^^^^^^ move out of `arr[..]` occurs here -... -LL | drop(xs_hold); - | ------- borrow later used here - -error[E0384]: cannot assign twice to immutable variable `_x1` - --> $DIR/borrowck-move-ref-pattern.rs:23:5 - | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | --- - | | - | first assignment to `_x1` - | help: make this binding mutable: `mut _x1` -LL | _x1 = U; - | ^^^^^^^ cannot assign twice to immutable variable - -error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-move-ref-pattern.rs:24:20 - | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | ------- immutable borrow occurs here -LL | _x1 = U; -LL | let _x0_hold = &mut tup.0; - | ^^^^^^^^^^ mutable borrow occurs here -LL | let (ref mut _x0_hold, ..) = tup; -LL | *_x0 = U; - | -------- immutable borrow later used here - -error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-move-ref-pattern.rs:25:10 - | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | ------- immutable borrow occurs here -... -LL | let (ref mut _x0_hold, ..) = tup; - | ^^^^^^^^^^^^^^^^ mutable borrow occurs here -LL | *_x0 = U; - | -------- immutable borrow later used here - -error[E0594]: cannot assign to `*_x0` which is behind a `&` reference - --> $DIR/borrowck-move-ref-pattern.rs:26:5 - | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | ------- help: consider changing this to be a mutable reference: `ref mut _x0` -... -LL | *_x0 = U; - | ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written - -error[E0594]: cannot assign to `*_x2` which is behind a `&` reference - --> $DIR/borrowck-move-ref-pattern.rs:27:5 - | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | ------- help: consider changing this to be a mutable reference: `ref mut _x2` -... -LL | *_x2 = U; - | ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written - -error[E0382]: use of moved value: `tup.1` - --> $DIR/borrowck-move-ref-pattern.rs:28:10 - | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | --- value moved here -... -LL | drop(tup.1); - | ^^^^^ value used here after move - | - = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait - -error[E0382]: borrow of moved value: `tup.1` - --> $DIR/borrowck-move-ref-pattern.rs:29:20 - | -LL | drop(tup.1); - | ----- value moved here -LL | let _x1_hold = &tup.1; - | ^^^^^^ value borrowed here after move - | - = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait - -error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-move-ref-pattern.rs:31:20 - | -LL | let (.., ref mut _x3) = tup; - | ----------- mutable borrow occurs here -LL | let _x3_hold = &tup.3; - | ^^^^^^ immutable borrow occurs here -... -LL | drop(_x3); - | --- mutable borrow later used here - -error[E0499]: cannot borrow `tup.3` as mutable more than once at a time - --> $DIR/borrowck-move-ref-pattern.rs:32:20 - | -LL | let (.., ref mut _x3) = tup; - | ----------- first mutable borrow occurs here -LL | let _x3_hold = &tup.3; -LL | let _x3_hold = &mut tup.3; - | ^^^^^^^^^^ second mutable borrow occurs here -... -LL | drop(_x3); - | --- first borrow later used here - -error[E0499]: cannot borrow `tup.3` as mutable more than once at a time - --> $DIR/borrowck-move-ref-pattern.rs:33:14 - | -LL | let (.., ref mut _x3) = tup; - | ----------- first mutable borrow occurs here -... -LL | let (.., ref mut _x4_hold) = tup; - | ^^^^^^^^^^^^^^^^ second mutable borrow occurs here -LL | let (.., ref _x4_hold) = tup; -LL | drop(_x3); - | --- first borrow later used here - -error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-move-ref-pattern.rs:34:14 - | -LL | let (.., ref mut _x3) = tup; - | ----------- mutable borrow occurs here -... -LL | let (.., ref _x4_hold) = tup; - | ^^^^^^^^^^^^ immutable borrow occurs here -LL | drop(_x3); - | --- mutable borrow later used here - -error[E0382]: use of moved value: `tup` - --> $DIR/borrowck-move-ref-pattern.rs:43:14 - | -LL | let mut tup = (U, U, U); - | ------- move occurs because `tup` has type `(U, U, U)`, which does not implement the `Copy` trait -LL | let c1 = || { - | -- value moved into closure here -LL | let (ref _x0, _x1, _) = tup; - | --- variable moved due to use in closure -LL | }; -LL | let c2 = || { - | ^^ value used here after move -LL | -LL | let (ref mut _x0, _, _x2) = tup; - | --- use occurs due to use in closure - -error: aborting due to 18 previous errors - -Some errors have detailed explanations: E0382, E0384, E0499, E0502, E0505, E0594. -For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs deleted file mode 100644 index ebb1683af7de6..0000000000000 --- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs +++ /dev/null @@ -1,120 +0,0 @@ -fn main() { - struct S; // Not `Copy`. - - let mut tup0 = (S, S); - let mut tup1 = (S, S, S); - let tup2 = (S, S); - let tup3 = (S, S, S); - let tup4 = (S, S); - let mut arr0 = [S, S, S]; - let mut arr1 = [S, S, S, S, S]; - let arr2 = [S, S, S]; - let arr3 = [S, S, S, S, S]; - - // The `mov` bindings require that we capture the scrutinees by-move. - let mut closure = || { - // Tuples... - let (ref mut borrow, mov) = tup0; - let (mov, _, ref mut borrow) = tup1; - let (ref borrow, mov) = tup2; - let (mov, _, ref borrow) = tup3; - let (ref borrow, mov) = tup4; - // Arrays... - let [mov @ .., ref borrow] = arr0; - let [_, ref mut borrow @ .., _, mov] = arr1; - let [mov @ .., ref borrow] = arr2; - let [_, ref borrow @ .., _, mov] = arr3; - }; - - // Now we try to borrow and move the captures, which should result in errors... - // ...for tuples: - drop(&tup0); //~ ERROR borrow of moved value: `tup0` - drop(&tup1); //~ ERROR borrow of moved value: `tup1` - drop(&tup2); //~ ERROR borrow of moved value: `tup2` - drop(&tup3); //~ ERROR borrow of moved value: `tup3` - // Ostensibly this should compile. - // However, because closures don't capture individual fields, which is changed in RFC 2229, - // this won't compile because the entire product is moved into the closure. - // The same applies to the array patterns below. - drop(&tup4.0); //~ ERROR borrow of moved value: `tup4` - // ...for arrays: - drop(&arr0); //~ ERROR borrow of moved value: `arr0` - let [_, mov1, mov2, mov3, _] = &arr1; //~ ERROR borrow of moved value: `arr1` - drop(&arr2); //~ ERROR borrow of moved value: `arr2` - let [_, mov1, mov2, mov3, _] = &arr3; //~ ERROR borrow of moved value: `arr3` - - // Let's redo ^--- with a `match` + sum type: - macro_rules! m { - ($p:pat = $s:expr) => { - match $s { - Some($p) => {} - _ => {} - } - }; - } - let mut tup0: Option<(S, S)> = None; - let mut tup1: Option<(S, S, S)> = None; - let tup2: Option<(S, S)> = None; - let tup3: Option<(S, S, S)> = None; - let tup4: Option<(S, S)> = None; - let mut arr0: Option<[S; 3]> = None; - let mut arr1: Option<[S; 5]> = None; - let arr2: Option<[S; 3]> = None; - let arr3: Option<[S; 5]> = None; - let mut closure = || { - m!((ref mut borrow, mov) = tup0); - m!((mov, _, ref mut borrow) = tup1); - m!((ref borrow, mov) = tup2); - m!((mov, _, ref borrow) = tup3); - m!((ref borrow, mov) = tup4); - m!([mov @ .., ref borrow] = arr0); - m!([_, ref mut borrow @ .., _, mov] = arr1); - m!([mov @ .., ref borrow] = arr2); - m!([_, ref borrow @ .., _, mov] = arr3); - }; - drop(&tup0); //~ ERROR borrow of moved value: `tup0` - drop(&tup1); //~ ERROR borrow of moved value: `tup1` - drop(&tup2); //~ ERROR borrow of moved value: `tup2` - drop(&tup3); //~ ERROR borrow of moved value: `tup3` - m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4` - drop(&arr0); //~ ERROR borrow of moved value: `arr0` - m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1` - drop(&arr2); //~ ERROR borrow of moved value: `arr2` - m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3` - - // Let's redo ^--- with `if let` (which may diverge from `match` in the future): - macro_rules! m { - ($p:pat = $s:expr) => { - if let Some($p) = $s {} - }; - } - let mut tup0: Option<(S, S)> = None; - let mut tup1: Option<(S, S, S)> = None; - let tup2: Option<(S, S)> = None; - let tup3: Option<(S, S, S)> = None; - let tup4: Option<(S, S)> = None; - let mut arr0: Option<[S; 3]> = None; - let mut arr1: Option<[S; 5]> = None; - let arr2: Option<[S; 3]> = None; - let arr3: Option<[S; 5]> = None; - let mut closure = || { - m!((ref mut borrow, mov) = tup0); - m!((mov, _, ref mut borrow) = tup1); - m!((ref borrow, mov) = tup2); - m!((mov, _, ref borrow) = tup3); - m!((ref borrow, mov) = tup4); - m!([mov @ .., ref borrow] = arr0); - m!([_, ref mut borrow @ .., _, mov] = arr1); - m!([mov @ .., ref borrow] = arr2); - m!([_, ref borrow @ .., _, mov] = arr3); - }; - drop(&tup0); //~ ERROR borrow of moved value: `tup0` - drop(&tup1); //~ ERROR borrow of moved value: `tup1` - drop(&tup2); //~ ERROR borrow of moved value: `tup2` - drop(&tup3); //~ ERROR borrow of moved value: `tup3` - m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4` - drop(&arr0); //~ ERROR borrow of moved value: `arr0` - m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1` - drop(&arr2); //~ ERROR borrow of moved value: `arr2` - m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3` -} diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr deleted file mode 100644 index f19fed0891740..0000000000000 --- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr +++ /dev/null @@ -1,404 +0,0 @@ -error[E0382]: borrow of moved value: `tup0` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:31:10 - | -LL | let mut tup0 = (S, S); - | -------- move occurs because `tup0` has type `(S, S)`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -LL | // Tuples... -LL | let (ref mut borrow, mov) = tup0; - | ---- variable moved due to use in closure -... -LL | drop(&tup0); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup1` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:32:10 - | -LL | let mut tup1 = (S, S, S); - | -------- move occurs because `tup1` has type `(S, S, S)`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | let (mov, _, ref mut borrow) = tup1; - | ---- variable moved due to use in closure -... -LL | drop(&tup1); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup2` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10 - | -LL | let tup2 = (S, S); - | ---- move occurs because `tup2` has type `(S, S)`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | let (ref borrow, mov) = tup2; - | ---- variable moved due to use in closure -... -LL | drop(&tup2); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup3` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10 - | -LL | let tup3 = (S, S, S); - | ---- move occurs because `tup3` has type `(S, S, S)`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | let (mov, _, ref borrow) = tup3; - | ---- variable moved due to use in closure -... -LL | drop(&tup3); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup4` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:39:10 - | -LL | let tup4 = (S, S); - | ---- move occurs because `tup4` has type `(S, S)`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | let (ref borrow, mov) = tup4; - | ---- variable moved due to use in closure -... -LL | drop(&tup4.0); - | ^^^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr0` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10 - | -LL | let mut arr0 = [S, S, S]; - | -------- move occurs because `arr0` has type `[S; 3]`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | let [mov @ .., ref borrow] = arr0; - | ---- variable moved due to use in closure -... -LL | drop(&arr0); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr1` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:42:36 - | -LL | let mut arr1 = [S, S, S, S, S]; - | -------- move occurs because `arr1` has type `[S; 5]`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | let [_, ref mut borrow @ .., _, mov] = arr1; - | ---- variable moved due to use in closure -... -LL | let [_, mov1, mov2, mov3, _] = &arr1; - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr2` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10 - | -LL | let arr2 = [S, S, S]; - | ---- move occurs because `arr2` has type `[S; 3]`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | let [mov @ .., ref borrow] = arr2; - | ---- variable moved due to use in closure -... -LL | drop(&arr2); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr3` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36 - | -LL | let arr3 = [S, S, S, S, S]; - | ---- move occurs because `arr3` has type `[S; 5]`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | let [_, ref borrow @ .., _, mov] = arr3; - | ---- variable moved due to use in closure -... -LL | let [_, mov1, mov2, mov3, _] = &arr3; - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup0` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:75:10 - | -LL | let mut tup0: Option<(S, S)> = None; - | -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -LL | m!((ref mut borrow, mov) = tup0); - | ---- variable moved due to use in closure -... -LL | drop(&tup0); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup1` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:76:10 - | -LL | let mut tup1: Option<(S, S, S)> = None; - | -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -LL | m!((ref mut borrow, mov) = tup0); -LL | m!((mov, _, ref mut borrow) = tup1); - | ---- variable moved due to use in closure -... -LL | drop(&tup1); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup2` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10 - | -LL | let tup2: Option<(S, S)> = None; - | ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!((ref borrow, mov) = tup2); - | ---- variable moved due to use in closure -... -LL | drop(&tup2); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup3` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10 - | -LL | let tup3: Option<(S, S, S)> = None; - | ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!((mov, _, ref borrow) = tup3); - | ---- variable moved due to use in closure -... -LL | drop(&tup3); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup4` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:79:21 - | -LL | let tup4: Option<(S, S)> = None; - | ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!((ref borrow, mov) = tup4); - | ---- variable moved due to use in closure -... -LL | m!((ref x, _) = &tup4); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr0` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10 - | -LL | let mut arr0: Option<[S; 3]> = None; - | -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!([mov @ .., ref borrow] = arr0); - | ---- variable moved due to use in closure -... -LL | drop(&arr0); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr1` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:81:35 - | -LL | let mut arr1: Option<[S; 5]> = None; - | -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!([_, ref mut borrow @ .., _, mov] = arr1); - | ---- variable moved due to use in closure -... -LL | m!([_, mov1, mov2, mov3, _] = &arr1); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr2` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10 - | -LL | let arr2: Option<[S; 3]> = None; - | ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait -LL | let arr3: Option<[S; 5]> = None; -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!([mov @ .., ref borrow] = arr2); - | ---- variable moved due to use in closure -... -LL | drop(&arr2); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr3` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35 - | -LL | let arr3: Option<[S; 5]> = None; - | ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!([_, ref borrow @ .., _, mov] = arr3); - | ---- variable moved due to use in closure -... -LL | m!([_, mov1, mov2, mov3, _] = &arr3); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup0` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:111:10 - | -LL | let mut tup0: Option<(S, S)> = None; - | -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -LL | m!((ref mut borrow, mov) = tup0); - | ---- variable moved due to use in closure -... -LL | drop(&tup0); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup1` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:112:10 - | -LL | let mut tup1: Option<(S, S, S)> = None; - | -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -LL | m!((ref mut borrow, mov) = tup0); -LL | m!((mov, _, ref mut borrow) = tup1); - | ---- variable moved due to use in closure -... -LL | drop(&tup1); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup2` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10 - | -LL | let tup2: Option<(S, S)> = None; - | ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!((ref borrow, mov) = tup2); - | ---- variable moved due to use in closure -... -LL | drop(&tup2); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup3` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10 - | -LL | let tup3: Option<(S, S, S)> = None; - | ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!((mov, _, ref borrow) = tup3); - | ---- variable moved due to use in closure -... -LL | drop(&tup3); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `tup4` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:115:21 - | -LL | let tup4: Option<(S, S)> = None; - | ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!((ref borrow, mov) = tup4); - | ---- variable moved due to use in closure -... -LL | m!((ref x, _) = &tup4); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr0` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10 - | -LL | let mut arr0: Option<[S; 3]> = None; - | -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!([mov @ .., ref borrow] = arr0); - | ---- variable moved due to use in closure -... -LL | drop(&arr0); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr1` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:117:35 - | -LL | let mut arr1: Option<[S; 5]> = None; - | -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait -... -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!([_, ref mut borrow @ .., _, mov] = arr1); - | ---- variable moved due to use in closure -... -LL | m!([_, mov1, mov2, mov3, _] = &arr1); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr2` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10 - | -LL | let arr2: Option<[S; 3]> = None; - | ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait -LL | let arr3: Option<[S; 5]> = None; -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!([mov @ .., ref borrow] = arr2); - | ---- variable moved due to use in closure -... -LL | drop(&arr2); - | ^^^^^ value borrowed here after move - -error[E0382]: borrow of moved value: `arr3` - --> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35 - | -LL | let arr3: Option<[S; 5]> = None; - | ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait -LL | let mut closure = || { - | -- value moved into closure here -... -LL | m!([_, ref borrow @ .., _, mov] = arr3); - | ---- variable moved due to use in closure -... -LL | m!([_, mov1, mov2, mov3, _] = &arr3); - | ^^^^^ value borrowed here after move - -error: aborting due to 27 previous errors - -For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/span/dropck_misc_variants.rs b/src/test/ui/span/dropck_misc_variants.rs deleted file mode 100644 index 5818a94bcb1e3..0000000000000 --- a/src/test/ui/span/dropck_misc_variants.rs +++ /dev/null @@ -1,37 +0,0 @@ -// check that dropck does the right thing with misc. Ty variants - -use std::fmt; -struct NoisyDrop(T); -impl Drop for NoisyDrop { - fn drop(&mut self) { - let _ = vec!["0wned"]; - println!("dropping {:?}", self.0) - } -} - -trait Associator { - type As; -} -impl Associator for T { - type As = NoisyDrop; -} -struct Wrap(::As); - -fn projection() { - let (_w, bomb); - bomb = vec![""]; - _w = Wrap::<&[&str]>(NoisyDrop(&bomb)); -} -//~^^ ERROR `bomb` does not live long enough - -fn closure() { - let (_w,v); - v = vec![""]; - _w = { - let u = NoisyDrop(&v); - //~^ ERROR `v` does not live long enough - move || u.0.len() - }; -} - -fn main() { closure(); projection() } diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr deleted file mode 100644 index 5c32613de5f18..0000000000000 --- a/src/test/ui/span/dropck_misc_variants.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0597]: `bomb` does not live long enough - --> $DIR/dropck_misc_variants.rs:23:36 - | -LL | _w = Wrap::<&[&str]>(NoisyDrop(&bomb)); - | ^^^^^ borrowed value does not live long enough -LL | } - | - - | | - | `bomb` dropped here while still borrowed - | borrow might be used here, when `_w` is dropped and runs the destructor for type `Wrap<&[&str]>` - | - = note: values in a scope are dropped in the opposite order they are defined - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs deleted file mode 100644 index f1e043c30f213..0000000000000 --- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs +++ /dev/null @@ -1,159 +0,0 @@ -#[derive(Clone)] -enum Either { - One(X), - Two(X), -} - -#[derive(Clone)] -struct X(Y); - -#[derive(Clone)] -struct Y; - -fn consume_fn(_f: F) { } - -fn consume_fnmut(_f: F) { } - -pub fn main() { } - -fn move_into_fn() { - let e = Either::One(X(Y)); - let mut em = Either::One(X(Y)); - - let x = X(Y); - - // move into Fn - - consume_fn(|| { - let X(_t) = x; - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &x - if let Either::One(_t) = e { } - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &e - while let Either::One(_t) = e { } - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &e - match e { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &e - Either::One(_t) - | Either::Two(_t) => (), - } - match e { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &e - Either::One(_t) => (), - Either::Two(ref _t) => (), - // FIXME: should suggest removing `ref` too - } - - let X(mut _t) = x; - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &x - if let Either::One(mut _t) = em { } - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - while let Either::One(mut _t) = em { } - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - match em { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - Either::One(mut _t) - | Either::Two(mut _t) => (), - } - match em { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - Either::One(mut _t) => (), - Either::Two(ref _t) => (), - // FIXME: should suggest removing `ref` too - } - }); -} - -fn move_into_fnmut() { - let e = Either::One(X(Y)); - let mut em = Either::One(X(Y)); - - let x = X(Y); - - // move into FnMut - - consume_fnmut(|| { - let X(_t) = x; - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &x - if let Either::One(_t) = e { } - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &e - while let Either::One(_t) = e { } - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &e - match e { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &e - Either::One(_t) - | Either::Two(_t) => (), - } - match e { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &e - Either::One(_t) => (), - Either::Two(ref _t) => (), - // FIXME: should suggest removing `ref` too - } - - let X(mut _t) = x; - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &x - if let Either::One(mut _t) = em { } - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - while let Either::One(mut _t) = em { } - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - match em { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - Either::One(mut _t) - | Either::Two(mut _t) => (), - } - match em { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - Either::One(mut _t) => (), - Either::Two(ref _t) => (), - // FIXME: should suggest removing `ref` too - } - match em { - //~^ ERROR cannot move - //~| HELP consider borrowing here - //~| SUGGESTION &em - Either::One(mut _t) => (), - Either::Two(ref mut _t) => (), - // FIXME: should suggest removing `ref` too - } - }); -} diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr deleted file mode 100644 index c50cbcde85553..0000000000000 --- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr +++ /dev/null @@ -1,282 +0,0 @@ -error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:28:21 - | -LL | let x = X(Y); - | - captured outer variable -... -LL | let X(_t) = x; - | -- ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:32:34 - | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | if let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:36:37 - | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | while let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:40:15 - | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:47:15 - | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:56:25 - | -LL | let x = X(Y); - | - captured outer variable -... -LL | let X(mut _t) = x; - | ------ ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:60:38 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | if let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:64:41 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | while let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:68:15 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure - --> $DIR/move-into-closure.rs:75:15 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:95:21 - | -LL | let x = X(Y); - | - captured outer variable -... -LL | let X(_t) = x; - | -- ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:99:34 - | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | if let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:103:37 - | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | while let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:107:15 - | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:114:15 - | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:123:25 - | -LL | let x = X(Y); - | - captured outer variable -... -LL | let X(mut _t) = x; - | ------ ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:127:38 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | if let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:131:41 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | while let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:135:15 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:142:15 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure - --> $DIR/move-into-closure.rs:150:15 - | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait - -error: aborting due to 21 previous errors - -For more information about this error, try `rustc --explain E0507`. From 76488e7bb096b3f3ca2c0133279eecc8726c091b Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Fri, 4 Dec 2020 00:33:58 -0500 Subject: [PATCH 12/20] Enable feature --- compiler/rustc_typeck/src/check/upvar.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index f7e386e090eaf..c92b1b1946af9 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -129,7 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut capture_information: FxIndexMap, ty::CaptureInfo<'tcx>> = Default::default(); - if !self.tcx.features().capture_disjoint_fields && env::var("SG_NEW").is_err() { + if !self.tcx.features().capture_disjoint_fields && env::var("SG_NEW").is_ok() { if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { for (&var_hir_id, _) in upvars.iter() { let place = self.place_for_root_variable(local_def_id, var_hir_id); From 8c64f01a21f200cbc727c1fee27dca629523190c Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Fri, 4 Dec 2020 03:36:27 -0500 Subject: [PATCH 13/20] =?UTF-8?q?Make=20the=20compiler=20compile=20?= =?UTF-8?q?=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_interface/src/util.rs | 10 ++++++++-- compiler/rustc_typeck/src/expr_use_visitor.rs | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index f34990a1a1037..6d7197d61af26 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -120,8 +120,14 @@ pub fn scoped_thread R + Send, R: Send>(cfg: thread::Builder, f: let result_ptr = Ptr(&mut result as *mut _ as *mut ()); let thread = cfg.spawn(move || { - let run = unsafe { (*(run.0 as *mut Option)).take().unwrap() }; - let result = unsafe { &mut *(result_ptr.0 as *mut Option) }; + let run = unsafe { + let x = run; + (*(x.0 as *mut Option)).take().unwrap() + }; + let result = unsafe { + let x = result_ptr; + &mut *(x.0 as *mut Option) + }; *result = Some(run()); }); diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 8a324807417da..8fd73c066f5a4 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -405,6 +405,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { }; let with_place = return_if_err!(self.mc.cat_expr(&with_expr)); + self.delegate_consume(&with_place, with_place.hir_id); // Select just those fields of the `with` // expression that will actually be used @@ -531,6 +532,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let tcx = self.tcx(); let ExprUseVisitor { ref mc, body_owner: _, ref mut delegate } = *self; + delegate.borrow(discr_place, discr_place.hir_id, ty::ImmBorrow); + return_if_err!(mc.cat_pattern(discr_place.clone(), pat, |place, pat| { if let PatKind::Binding(_, canonical_id, ..) = pat.kind { debug!("walk_pat: binding place={:?} pat={:?}", place, pat,); From a88fb4a3d521ae82b442749114a12843bf1dc3ba Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Fri, 4 Dec 2020 03:55:14 -0500 Subject: [PATCH 14/20] Remove more failing tests :p --- .../2229_closure_analysis/capture-enums.rs | 64 ------- .../capture-enums.stderr | 122 ------------ .../destructure_patterns.rs | 77 -------- .../destructure_patterns.stderr | 177 ------------------ .../2229_closure_analysis/wild_patterns.rs | 75 -------- .../wild_patterns.stderr | 147 --------------- 6 files changed, 662 deletions(-) delete mode 100644 src/test/ui/closures/2229_closure_analysis/capture-enums.rs delete mode 100644 src/test/ui/closures/2229_closure_analysis/capture-enums.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs delete mode 100644 src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/wild_patterns.rs delete mode 100644 src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/capture-enums.rs b/src/test/ui/closures/2229_closure_analysis/capture-enums.rs deleted file mode 100644 index 8fb2f7f16d69c..0000000000000 --- a/src/test/ui/closures/2229_closure_analysis/capture-enums.rs +++ /dev/null @@ -1,64 +0,0 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 -#![feature(rustc_attrs)] - -enum Info { - Point(i32, i32, String), - Meta(String, Vec<(i32, i32)>) -} - -fn multi_variant_enum() { - let point = Info::Point(10, -10, "1".into()); - - let vec = Vec::new(); - let meta = Info::Meta("meta".into(), vec); - - let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: - if let Info::Point(_, _, str) = point { - //~^ NOTE: Capturing point[] -> ImmBorrow - //~| NOTE: Capturing point[(2, 0)] -> ByValue - //~| NOTE: Min Capture point[] -> ByValue - println!("{}", str); - } - - if let Info::Meta(_, v) = meta { - //~^ NOTE: Capturing meta[] -> ImmBorrow - //~| NOTE: Capturing meta[(1, 1)] -> ByValue - //~| NOTE: Min Capture meta[] -> ByValue - println!("{:?}", v); - } - }; - - c(); -} - -enum SingleVariant { - Point(i32, i32, String), -} - -fn single_variant_enum() { - let point = SingleVariant::Point(10, -10, "1".into()); - - let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: - let SingleVariant::Point(_, _, str) = point; - //~^ NOTE: Capturing point[(2, 0)] -> ByValue - //~| NOTE: Min Capture point[(2, 0)] -> ByValue - println!("{}", str); - }; - - c(); -} - -fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr b/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr deleted file mode 100644 index ebe1dcb98848b..0000000000000 --- a/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr +++ /dev/null @@ -1,122 +0,0 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/capture-enums.rs:18:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/capture-enums.rs:49:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-enums.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -error: First Pass analysis includes: - --> $DIR/capture-enums.rs:21:5 - | -LL | / || { -LL | | -LL | | -LL | | if let Info::Point(_, _, str) = point { -... | -LL | | } -LL | | }; - | |_____^ - | -note: Capturing point[] -> ImmBorrow - --> $DIR/capture-enums.rs:24:41 - | -LL | if let Info::Point(_, _, str) = point { - | ^^^^^ -note: Capturing point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:24:41 - | -LL | if let Info::Point(_, _, str) = point { - | ^^^^^ -note: Capturing meta[] -> ImmBorrow - --> $DIR/capture-enums.rs:31:35 - | -LL | if let Info::Meta(_, v) = meta { - | ^^^^ -note: Capturing meta[(1, 1)] -> ByValue - --> $DIR/capture-enums.rs:31:35 - | -LL | if let Info::Meta(_, v) = meta { - | ^^^^ - -error: Min Capture analysis includes: - --> $DIR/capture-enums.rs:21:5 - | -LL | / || { -LL | | -LL | | -LL | | if let Info::Point(_, _, str) = point { -... | -LL | | } -LL | | }; - | |_____^ - | -note: Min Capture point[] -> ByValue - --> $DIR/capture-enums.rs:24:41 - | -LL | if let Info::Point(_, _, str) = point { - | ^^^^^ -note: Min Capture meta[] -> ByValue - --> $DIR/capture-enums.rs:31:35 - | -LL | if let Info::Meta(_, v) = meta { - | ^^^^ - -error: First Pass analysis includes: - --> $DIR/capture-enums.rs:52:5 - | -LL | / || { -LL | | -LL | | -LL | | let SingleVariant::Point(_, _, str) = point; -... | -LL | | println!("{}", str); -LL | | }; - | |_____^ - | -note: Capturing point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 - | -LL | let SingleVariant::Point(_, _, str) = point; - | ^^^^^ - -error: Min Capture analysis includes: - --> $DIR/capture-enums.rs:52:5 - | -LL | / || { -LL | | -LL | | -LL | | let SingleVariant::Point(_, _, str) = point; -... | -LL | | println!("{}", str); -LL | | }; - | |_____^ - | -note: Min Capture point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 - | -LL | let SingleVariant::Point(_, _, str) = point; - | ^^^^^ - -error: aborting due to 6 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs deleted file mode 100644 index 080ca0405b477..0000000000000 --- a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs +++ /dev/null @@ -1,77 +0,0 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 -#![feature(rustc_attrs)] - -// Test to ensure Index projections are handled properly during capture analysis -// The array should be moved in entirety, even though only some elements are used. -fn arrays() { - let arr: [String; 5] = [format!("A"), format!("B"), format!("C"), format!("D"), format!("E")]; - - let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { - //~^ ERROR: First Pass analysis includes: - //~| ERROR: Min Capture analysis includes: - let [a, b, .., e] = arr; - //~^ NOTE: Capturing arr[Index] -> ByValue - //~| NOTE: Min Capture arr[] -> ByValue - assert_eq!(a, "A"); - assert_eq!(b, "B"); - assert_eq!(e, "E"); - }; - - c(); -} - -struct Point { - x: i32, - y: i32, - id: String, -} - -fn structs() { - let mut p = Point { x: 10, y: 10, id: String::new() }; - - let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { - //~^ ERROR: First Pass analysis includes: - //~| ERROR: Min Capture analysis includes: - let Point { x: ref mut x, y: _, id: moved_id } = p; - //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow - //~| NOTE: Capturing p[(2, 0)] -> ByValue - //~| NOTE: Min Capture p[(0, 0)] -> MutBorrow - //~| NOTE: Min Capture p[(2, 0)] -> ByValue - - println!("{}, {}", x, moved_id); - }; - c(); -} - -fn tuples() { - let mut t = (10, String::new(), (String::new(), 42)); - - let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { - //~^ ERROR: First Pass analysis includes: - //~| ERROR: Min Capture analysis includes: - let (ref mut x, ref ref_str, (moved_s, _)) = t; - //~^ NOTE: Capturing t[(0, 0)] -> MutBorrow - //~| NOTE: Capturing t[(1, 0)] -> ImmBorrow - //~| NOTE: Capturing t[(2, 0),(0, 0)] -> ByValue - //~| NOTE: Min Capture t[(0, 0)] -> MutBorrow - //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow - //~| NOTE: Min Capture t[(2, 0),(0, 0)] -> ByValue - - println!("{}, {} {}", x, ref_str, moved_s); - }; - c(); -} - -fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr deleted file mode 100644 index 06ccc2d7a88b4..0000000000000 --- a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr +++ /dev/null @@ -1,177 +0,0 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:12:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:38:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:58:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/destructure_patterns.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:15:5 - | -LL | / || { -LL | | -LL | | -LL | | let [a, b, .., e] = arr; -... | -LL | | assert_eq!(e, "E"); -LL | | }; - | |_____^ - | -note: Capturing arr[Index] -> ByValue - --> $DIR/destructure_patterns.rs:18:29 - | -LL | let [a, b, .., e] = arr; - | ^^^ - -error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:15:5 - | -LL | / || { -LL | | -LL | | -LL | | let [a, b, .., e] = arr; -... | -LL | | assert_eq!(e, "E"); -LL | | }; - | |_____^ - | -note: Min Capture arr[] -> ByValue - --> $DIR/destructure_patterns.rs:18:29 - | -LL | let [a, b, .., e] = arr; - | ^^^ - -error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:41:5 - | -LL | / || { -LL | | -LL | | -LL | | let Point { x: ref mut x, y: _, id: moved_id } = p; -... | -LL | | println!("{}, {}", x, moved_id); -LL | | }; - | |_____^ - | -note: Capturing p[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:44:58 - | -LL | let Point { x: ref mut x, y: _, id: moved_id } = p; - | ^ -note: Capturing p[(2, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:44:58 - | -LL | let Point { x: ref mut x, y: _, id: moved_id } = p; - | ^ - -error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:41:5 - | -LL | / || { -LL | | -LL | | -LL | | let Point { x: ref mut x, y: _, id: moved_id } = p; -... | -LL | | println!("{}, {}", x, moved_id); -LL | | }; - | |_____^ - | -note: Min Capture p[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:44:58 - | -LL | let Point { x: ref mut x, y: _, id: moved_id } = p; - | ^ -note: Min Capture p[(2, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:44:58 - | -LL | let Point { x: ref mut x, y: _, id: moved_id } = p; - | ^ - -error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:61:5 - | -LL | / || { -LL | | -LL | | -LL | | let (ref mut x, ref ref_str, (moved_s, _)) = t; -... | -LL | | println!("{}, {} {}", x, ref_str, moved_s); -LL | | }; - | |_____^ - | -note: Capturing t[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:64:54 - | -LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; - | ^ -note: Capturing t[(1, 0)] -> ImmBorrow - --> $DIR/destructure_patterns.rs:64:54 - | -LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; - | ^ -note: Capturing t[(2, 0),(0, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:64:54 - | -LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; - | ^ - -error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:61:5 - | -LL | / || { -LL | | -LL | | -LL | | let (ref mut x, ref ref_str, (moved_s, _)) = t; -... | -LL | | println!("{}, {} {}", x, ref_str, moved_s); -LL | | }; - | |_____^ - | -note: Min Capture t[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:64:54 - | -LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; - | ^ -note: Min Capture t[(1, 0)] -> ImmBorrow - --> $DIR/destructure_patterns.rs:64:54 - | -LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; - | ^ -note: Min Capture t[(2, 0),(0, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:64:54 - | -LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; - | ^ - -error: aborting due to 9 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs b/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs deleted file mode 100644 index 90b8033d074a1..0000000000000 --- a/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs +++ /dev/null @@ -1,75 +0,0 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 -#![feature(rustc_attrs)] - -// Test to ensure that we can handle cases where -// let statements create no bindings are intialized -// using a Place expression -// -// Note: Currently when feature `capture_disjoint_fields` is enabled -// we can't handle such cases. So the test current use `_x` instead of -// `_` until the issue is resolved. -// Check rust-lang/project-rfc-2229#24 for status. - -struct Point { - x: i32, - y: i32, -} - -fn wild_struct() { - let p = Point { x: 10, y: 20 }; - - let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { - //~^ ERROR: First Pass analysis includes: - //~| ERROR: Min Capture analysis includes: - // FIXME(arora-aman): Change `_x` to `_` - let Point { x: _x, y: _ } = p; - //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow - }; - - c(); -} - -fn wild_tuple() { - let t = (String::new(), 10); - - let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { - //~^ ERROR: First Pass analysis includes: - //~| ERROR: Min Capture analysis includes: - // FIXME(arora-aman): Change `_x` to `_` - let (_x, _) = t; - //~^ NOTE: Capturing t[(0, 0)] -> ByValue - //~| NOTE: Min Capture t[(0, 0)] -> ByValue - }; - - c(); -} - -fn wild_arr() { - let arr = [String::new(), String::new()]; - - let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { - //~^ ERROR: First Pass analysis includes: - //~| ERROR: Min Capture analysis includes: - // FIXME(arora-aman): Change `_x` to `_` - let [_x, _] = arr; - //~^ NOTE: Capturing arr[Index] -> ByValue - //~| NOTE: Min Capture arr[] -> ByValue - }; - - c(); -} - -fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr b/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr deleted file mode 100644 index 36be8431be508..0000000000000 --- a/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr +++ /dev/null @@ -1,147 +0,0 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:24:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:42:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:60:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/wild_patterns.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:27:5 - | -LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` -... | -LL | | -LL | | }; - | |_____^ - | -note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/wild_patterns.rs:31:37 - | -LL | let Point { x: _x, y: _ } = p; - | ^ - -error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:27:5 - | -LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` -... | -LL | | -LL | | }; - | |_____^ - | -note: Min Capture p[(0, 0)] -> ImmBorrow - --> $DIR/wild_patterns.rs:31:37 - | -LL | let Point { x: _x, y: _ } = p; - | ^ - -error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:45:5 - | -LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` -... | -LL | | -LL | | }; - | |_____^ - | -note: Capturing t[(0, 0)] -> ByValue - --> $DIR/wild_patterns.rs:49:23 - | -LL | let (_x, _) = t; - | ^ - -error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:45:5 - | -LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` -... | -LL | | -LL | | }; - | |_____^ - | -note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/wild_patterns.rs:49:23 - | -LL | let (_x, _) = t; - | ^ - -error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:63:5 - | -LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` -... | -LL | | -LL | | }; - | |_____^ - | -note: Capturing arr[Index] -> ByValue - --> $DIR/wild_patterns.rs:67:23 - | -LL | let [_x, _] = arr; - | ^^^ - -error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:63:5 - | -LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` -... | -LL | | -LL | | }; - | |_____^ - | -note: Min Capture arr[] -> ByValue - --> $DIR/wild_patterns.rs:67:23 - | -LL | let [_x, _] = arr; - | ^^^ - -error: aborting due to 9 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0658`. From 69cba8c8c35c7daa44c6216f5ff5a325a1ef16b6 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Sat, 5 Dec 2020 03:43:17 -0500 Subject: [PATCH 15/20] error code doc change --- compiler/rustc_error_codes/src/error_codes/E0504.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0504.md b/compiler/rustc_error_codes/src/error_codes/E0504.md index bcbd00a8690a4..0f0f4f0dfde4f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0504.md +++ b/compiler/rustc_error_codes/src/error_codes/E0504.md @@ -7,20 +7,20 @@ Erroneous code example: ```compile_fail struct FancyNum { - num: u8, + s: String, } fn main() { - let fancy_num = FancyNum { num: 5 }; + let fancy_num = FancyNum { s: "".into() }; let fancy_ref = &fancy_num; let x = move || { - println!("child function: {}", fancy_num.num); + println!("child function: {}", fancy_num.s); // error: cannot move `fancy_num` into closure because it is borrowed }; x(); - println!("main function: {}", fancy_ref.num); + println!("main function: {}", fancy_ref.s); } ``` From e2c96e9b423005928901156831b5e5fa0380b77c Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Sat, 5 Dec 2020 03:59:08 -0500 Subject: [PATCH 16/20] Remove it to be safe --- .../src/error_codes/E0504.md | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0504.md b/compiler/rustc_error_codes/src/error_codes/E0504.md index 0f0f4f0dfde4f..d9ea166b37354 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0504.md +++ b/compiler/rustc_error_codes/src/error_codes/E0504.md @@ -5,25 +5,6 @@ closure. Erroneous code example: -```compile_fail -struct FancyNum { - s: String, -} - -fn main() { - let fancy_num = FancyNum { s: "".into() }; - let fancy_ref = &fancy_num; - - let x = move || { - println!("child function: {}", fancy_num.s); - // error: cannot move `fancy_num` into closure because it is borrowed - }; - - x(); - println!("main function: {}", fancy_ref.s); -} -``` - Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into the closure `x`. There is no way to move a value into a closure while it is borrowed, as that would invalidate the borrow. From fda70bde176ea9e980190f8e01b2623f0f80afeb Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Sat, 5 Dec 2020 15:41:00 -0500 Subject: [PATCH 17/20] Rust analyzer migration for 2229 --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 0d03fe6ef57d3..509d76ddcc107 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 0d03fe6ef57d3956e92382e0e1f1a916015191cb +Subproject commit 509d76ddcc107d0b1522007a216c732749fd3419 From 20692cb032c425db94717786f9ca35978e65addf Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Sat, 5 Dec 2020 16:12:30 -0500 Subject: [PATCH 18/20] Point to personal rust analyzer --- .gitmodules | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 984113151de4d..ae5116f3a81d4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,7 +43,8 @@ url = https://github.com/rust-embedded/book.git [submodule "src/tools/rust-analyzer"] path = src/tools/rust-analyzer - url = https://github.com/rust-analyzer/rust-analyzer.git + url = https://github.com/arora-aman/rust-analyzer.git + branch = perf-2229 [submodule "library/backtrace"] path = library/backtrace url = https://github.com/rust-lang/backtrace-rs.git From 015c6a26b402dc58c3d2b206409a3f022a246982 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Sat, 5 Dec 2020 22:17:37 -0500 Subject: [PATCH 19/20] don't capture derefs in case of by value capture --- compiler/rustc_typeck/src/check/upvar.rs | 26 ++++++++++--------- .../borrowck-closures-slice-patterns.stderr | 4 +-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index c92b1b1946af9..d1b64b961b58e 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -385,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base => bug!("Expected upvar, found={:?}", base), }; - let place = truncate_projections_for_capture(place, inferred_info.capture_clause); + let place = truncate_projections_for_capture(place, capture_info.capture_kind); let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) { None => { @@ -933,7 +933,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { /// - No Index projections are captured, since arrays are captured completely. fn truncate_projections_for_capture<'tcx>( mut place: Place<'tcx>, - capture_clause: hir::CaptureBy, + capture_kind: ty::UpvarCapture<'tcx>, ) -> Place<'tcx> { if place.projections.is_empty() { // Nothing to do here @@ -948,7 +948,7 @@ fn truncate_projections_for_capture<'tcx>( let mut first_index_projection = None; let mut first_deref_projection = None; let mut first_raw_ptr = None; - let mut last_field_projection = None; + //let mut last_field_projection = None; for (i, proj) in place.projections.iter().enumerate() { if proj.ty.is_unsafe_ptr() { @@ -968,7 +968,7 @@ fn truncate_projections_for_capture<'tcx>( first_deref_projection.get_or_insert(i); } ProjectionKind::Field(..) => { - last_field_projection = Some(i); + //last_field_projection = Some(i); } ProjectionKind::Subslice => {} // We never capture this } @@ -983,16 +983,18 @@ fn truncate_projections_for_capture<'tcx>( length = first_index_projection.map_or(length, |idx| cmp::min(length, idx)); // In case of move closure, don't apply Deref or any further projections - length = match capture_clause { - hir::CaptureBy::Value => first_deref_projection.map_or(length, |idx| cmp::min(length, idx)), - hir::CaptureBy::Ref => length, + length = match capture_kind { + ty::UpvarCapture::ByValue(..) => { + first_deref_projection.map_or(length, |idx| cmp::min(length, idx)) + } + ty::UpvarCapture::ByRef(..) => length, }; - if env::var("SG_DROP_DEREFS").is_ok() { - // Since we will only have Field and Deref projections at this point. - // This will truncate trailing derefs. - length = last_field_projection.map_or(length, |idx| cmp::min(length, idx + 1)); - } + //if env::var("SG_DROP_DEREFS").is_ok() { + //// Since we will only have Field and Deref projections at this point. + //// This will truncate trailing derefs. + //length = last_field_projection.map_or(length, |idx| cmp::min(length, idx + 1)); + //} place.projections.truncate(length); diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr index 72675ee0814e2..fca48a1f17fb5 100644 --- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr @@ -70,6 +70,8 @@ LL | f(); error[E0382]: borrow of moved value: `x` --> $DIR/borrowck-closures-slice-patterns.rs:51:5 | +LL | fn arr_box_by_move(x: Box<[String; 3]>) { + | - move occurs because `x` has type `Box<[String; 3]>`, which does not implement the `Copy` trait LL | let f = || { | -- value moved into closure here LL | let [y, z @ ..] = *x; @@ -77,8 +79,6 @@ LL | let [y, z @ ..] = *x; LL | }; LL | &x; | ^^ value borrowed here after move - | - = note: move occurs because `*x` has type `[String; 3]`, which does not implement the `Copy` trait error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable --> $DIR/borrowck-closures-slice-patterns.rs:59:13 From acd732a5d92b8d545970dfde38ad3463fdd927c8 Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Sun, 6 Dec 2020 20:41:30 -0500 Subject: [PATCH 20/20] don't capture trailing derefs --- compiler/rustc_typeck/src/check/upvar.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index d1b64b961b58e..b5e294b81bbd4 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -948,7 +948,7 @@ fn truncate_projections_for_capture<'tcx>( let mut first_index_projection = None; let mut first_deref_projection = None; let mut first_raw_ptr = None; - //let mut last_field_projection = None; + let mut last_field_projection = None; for (i, proj) in place.projections.iter().enumerate() { if proj.ty.is_unsafe_ptr() { @@ -968,7 +968,7 @@ fn truncate_projections_for_capture<'tcx>( first_deref_projection.get_or_insert(i); } ProjectionKind::Field(..) => { - //last_field_projection = Some(i); + last_field_projection = Some(i); } ProjectionKind::Subslice => {} // We never capture this } @@ -990,11 +990,9 @@ fn truncate_projections_for_capture<'tcx>( ty::UpvarCapture::ByRef(..) => length, }; - //if env::var("SG_DROP_DEREFS").is_ok() { - //// Since we will only have Field and Deref projections at this point. - //// This will truncate trailing derefs. - //length = last_field_projection.map_or(length, |idx| cmp::min(length, idx + 1)); - //} + // Since we will only have Field and Deref projections at this point. + // This will truncate trailing derefs. + length = last_field_projection.map_or(length, |idx| cmp::min(length, idx + 1)); place.projections.truncate(length);