Remove region from UpvarCapture and move it to CapturedPlace
Region info is completely unnecessary for upvar capture kind computation and is only needed to create the final upvar tuple ty. Doing so makes creation of UpvarCapture very cheap and expose further cleanup opportunity.
This commit is contained in:
parent
3698e03fb6
commit
48258ffe5a
9 changed files with 103 additions and 116 deletions
|
@ -706,10 +706,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
&origin_projection,
|
&origin_projection,
|
||||||
) {
|
) {
|
||||||
match captured_place.info.capture_kind {
|
match captured_place.info.capture_kind {
|
||||||
ty::UpvarCapture::ByRef(ty::UpvarBorrow {
|
ty::UpvarCapture::ByRef(
|
||||||
kind: ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
|
ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
|
||||||
..
|
) => {
|
||||||
}) => {
|
|
||||||
capture_reason = format!("mutable borrow of `{}`", upvar);
|
capture_reason = format!("mutable borrow of `{}`", upvar);
|
||||||
}
|
}
|
||||||
ty::UpvarCapture::ByValue => {
|
ty::UpvarCapture::ByValue => {
|
||||||
|
|
|
@ -52,29 +52,18 @@ impl UpvarId {
|
||||||
/// Information describing the capture of an upvar. This is computed
|
/// Information describing the capture of an upvar. This is computed
|
||||||
/// during `typeck`, specifically by `regionck`.
|
/// during `typeck`, specifically by `regionck`.
|
||||||
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
|
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
|
||||||
pub enum UpvarCapture<'tcx> {
|
pub enum UpvarCapture {
|
||||||
/// Upvar is captured by value. This is always true when the
|
/// Upvar is captured by value. This is always true when the
|
||||||
/// closure is labeled `move`, but can also be true in other cases
|
/// closure is labeled `move`, but can also be true in other cases
|
||||||
/// depending on inference.
|
/// depending on inference.
|
||||||
ByValue,
|
ByValue,
|
||||||
|
|
||||||
/// Upvar is captured by reference.
|
/// Upvar is captured by reference.
|
||||||
ByRef(UpvarBorrow<'tcx>),
|
ByRef(BorrowKind),
|
||||||
}
|
|
||||||
|
|
||||||
#[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
|
|
||||||
/// syntax.
|
|
||||||
pub kind: BorrowKind,
|
|
||||||
|
|
||||||
/// Region of the resulting reference.
|
|
||||||
pub region: ty::Region<'tcx>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
|
pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
|
||||||
pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
|
pub type UpvarCaptureMap = FxHashMap<UpvarId, UpvarCapture>;
|
||||||
|
|
||||||
/// Given the closure DefId this map provides a map of root variables to minimum
|
/// Given the closure DefId this map provides a map of root variables to minimum
|
||||||
/// set of `CapturedPlace`s that need to be tracked to support all captures of that closure.
|
/// set of `CapturedPlace`s that need to be tracked to support all captures of that closure.
|
||||||
|
@ -144,10 +133,13 @@ pub struct CapturedPlace<'tcx> {
|
||||||
pub place: HirPlace<'tcx>,
|
pub place: HirPlace<'tcx>,
|
||||||
|
|
||||||
/// `CaptureKind` and expression(s) that resulted in such capture of `place`.
|
/// `CaptureKind` and expression(s) that resulted in such capture of `place`.
|
||||||
pub info: CaptureInfo<'tcx>,
|
pub info: CaptureInfo,
|
||||||
|
|
||||||
/// Represents if `place` can be mutated or not.
|
/// Represents if `place` can be mutated or not.
|
||||||
pub mutability: hir::Mutability,
|
pub mutability: hir::Mutability,
|
||||||
|
|
||||||
|
/// Region of the resulting reference if the upvar is captured by ref.
|
||||||
|
pub region: Option<ty::Region<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> CapturedPlace<'tcx> {
|
impl<'tcx> CapturedPlace<'tcx> {
|
||||||
|
@ -281,7 +273,7 @@ pub fn is_ancestor_or_same_capture(
|
||||||
/// for a particular capture as well as identifying the part of the source code
|
/// for a particular capture as well as identifying the part of the source code
|
||||||
/// that triggered this capture to occur.
|
/// that triggered this capture to occur.
|
||||||
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
|
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
|
||||||
pub struct CaptureInfo<'tcx> {
|
pub struct CaptureInfo {
|
||||||
/// Expr Id pointing to use that resulted in selecting the current capture kind
|
/// Expr Id pointing to use that resulted in selecting the current capture kind
|
||||||
///
|
///
|
||||||
/// Eg:
|
/// Eg:
|
||||||
|
@ -319,7 +311,7 @@ pub struct CaptureInfo<'tcx> {
|
||||||
pub path_expr_id: Option<hir::HirId>,
|
pub path_expr_id: Option<hir::HirId>,
|
||||||
|
|
||||||
/// Capture mode that was selected
|
/// Capture mode that was selected
|
||||||
pub capture_kind: UpvarCapture<'tcx>,
|
pub capture_kind: UpvarCapture,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
|
pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
|
||||||
|
|
|
@ -56,8 +56,8 @@ pub use self::binding::BindingMode::*;
|
||||||
pub use self::closure::{
|
pub use self::closure::{
|
||||||
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
|
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
|
||||||
CapturedPlace, ClosureKind, MinCaptureInformationMap, MinCaptureList,
|
CapturedPlace, ClosureKind, MinCaptureInformationMap, MinCaptureList,
|
||||||
RootVariableMinCaptureList, UpvarBorrow, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap,
|
RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath,
|
||||||
UpvarPath, CAPTURE_STRUCT_LOCAL,
|
CAPTURE_STRUCT_LOCAL,
|
||||||
};
|
};
|
||||||
pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Unevaluated, ValTree};
|
pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Unevaluated, ValTree};
|
||||||
pub use self::context::{
|
pub use self::context::{
|
||||||
|
|
|
@ -47,12 +47,6 @@ impl fmt::Debug for ty::UpvarId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "UpvarBorrow({:?}, {:?})", self.kind, self.region)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
|
impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
with_no_trimmed_paths(|| fmt::Display::fmt(self, f))
|
with_no_trimmed_paths(|| fmt::Display::fmt(self, f))
|
||||||
|
|
|
@ -1110,7 +1110,7 @@ impl<'tcx> Cx<'tcx> {
|
||||||
match upvar_capture {
|
match upvar_capture {
|
||||||
ty::UpvarCapture::ByValue => captured_place_expr,
|
ty::UpvarCapture::ByValue => captured_place_expr,
|
||||||
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
||||||
let borrow_kind = match upvar_borrow.kind {
|
let borrow_kind = match upvar_borrow {
|
||||||
ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
|
ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
|
||||||
ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
|
ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
|
||||||
ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false },
|
ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||||
|
|
|
@ -859,9 +859,9 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||||
self.sub_regions(
|
self.sub_regions(
|
||||||
infer::ReborrowUpvar(span, upvar_id),
|
infer::ReborrowUpvar(span, upvar_id),
|
||||||
borrow_region,
|
borrow_region,
|
||||||
upvar_borrow.region,
|
captured_place.region.unwrap(),
|
||||||
);
|
);
|
||||||
if let ty::ImmBorrow = upvar_borrow.kind {
|
if let ty::ImmBorrow = upvar_borrow {
|
||||||
debug!("link_upvar_region: capture by shared ref");
|
debug!("link_upvar_region: capture by shared ref");
|
||||||
} else {
|
} else {
|
||||||
all_captures_are_imm_borrow = false;
|
all_captures_are_imm_borrow = false;
|
||||||
|
|
|
@ -72,7 +72,7 @@ enum PlaceAncestryRelation {
|
||||||
/// Intermediate format to store a captured `Place` and associated `ty::CaptureInfo`
|
/// Intermediate format to store a captured `Place` and associated `ty::CaptureInfo`
|
||||||
/// during capture analysis. Information in this map feeds into the minimum capture
|
/// during capture analysis. Information in this map feeds into the minimum capture
|
||||||
/// analysis pass.
|
/// analysis pass.
|
||||||
type InferredCaptureInformation<'tcx> = FxIndexMap<Place<'tcx>, ty::CaptureInfo<'tcx>>;
|
type InferredCaptureInformation<'tcx> = FxIndexMap<Place<'tcx>, ty::CaptureInfo>;
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
|
pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
|
||||||
|
@ -208,7 +208,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let mut delegate = InferBorrowKind {
|
let mut delegate = InferBorrowKind {
|
||||||
fcx: self,
|
fcx: self,
|
||||||
closure_def_id,
|
closure_def_id,
|
||||||
closure_span: span,
|
|
||||||
capture_information: Default::default(),
|
capture_information: Default::default(),
|
||||||
fake_reads: Default::default(),
|
fake_reads: Default::default(),
|
||||||
};
|
};
|
||||||
|
@ -231,7 +230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let (capture_information, closure_kind, origin) = self
|
let (capture_information, closure_kind, origin) = self
|
||||||
.process_collected_capture_information(capture_clause, delegate.capture_information);
|
.process_collected_capture_information(capture_clause, delegate.capture_information);
|
||||||
|
|
||||||
self.compute_min_captures(closure_def_id, capture_information);
|
self.compute_min_captures(closure_def_id, capture_information, span);
|
||||||
|
|
||||||
let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
|
let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
|
||||||
|
|
||||||
|
@ -252,9 +251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
debug!("seed place {:?}", place);
|
debug!("seed place {:?}", place);
|
||||||
|
|
||||||
let upvar_id = ty::UpvarId::new(*var_hir_id, local_def_id);
|
let capture_kind = self.init_capture_kind_for_place(&place, capture_clause);
|
||||||
let capture_kind =
|
|
||||||
self.init_capture_kind_for_place(&place, capture_clause, upvar_id, span);
|
|
||||||
let fake_info = ty::CaptureInfo {
|
let fake_info = ty::CaptureInfo {
|
||||||
capture_kind_expr_id: None,
|
capture_kind_expr_id: None,
|
||||||
path_expr_id: None,
|
path_expr_id: None,
|
||||||
|
@ -266,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will update the min captures based on this new fake information.
|
// This will update the min captures based on this new fake information.
|
||||||
self.compute_min_captures(closure_def_id, capture_information);
|
self.compute_min_captures(closure_def_id, capture_information, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
let before_feature_tys = self.final_upvar_tys(closure_def_id);
|
let before_feature_tys = self.final_upvar_tys(closure_def_id);
|
||||||
|
@ -362,7 +359,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
captured_place.place, upvar_ty, capture, captured_place.mutability,
|
captured_place.place, upvar_ty, capture, captured_place.mutability,
|
||||||
);
|
);
|
||||||
|
|
||||||
apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture)
|
apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -417,10 +414,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
ty::ClosureKind::FnOnce => (closure_kind, origin),
|
ty::ClosureKind::FnOnce => (closure_kind, origin),
|
||||||
},
|
},
|
||||||
|
|
||||||
ty::UpvarCapture::ByRef(ty::UpvarBorrow {
|
ty::UpvarCapture::ByRef(
|
||||||
kind: ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
|
ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
|
||||||
..
|
) => {
|
||||||
}) => {
|
|
||||||
match closure_kind {
|
match closure_kind {
|
||||||
ty::ClosureKind::Fn => {
|
ty::ClosureKind::Fn => {
|
||||||
(ty::ClosureKind::FnMut, Some((usage_span, place.clone())))
|
(ty::ClosureKind::FnMut, Some((usage_span, place.clone())))
|
||||||
|
@ -535,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
closure_def_id: DefId,
|
closure_def_id: DefId,
|
||||||
capture_information: InferredCaptureInformation<'tcx>,
|
capture_information: InferredCaptureInformation<'tcx>,
|
||||||
|
closure_span: Span,
|
||||||
) {
|
) {
|
||||||
if capture_information.is_empty() {
|
if capture_information.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
@ -554,8 +551,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) {
|
let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) {
|
||||||
None => {
|
None => {
|
||||||
let mutability = self.determine_capture_mutability(&typeck_results, &place);
|
let mutability = self.determine_capture_mutability(&typeck_results, &place);
|
||||||
let min_cap_list =
|
let min_cap_list = vec![ty::CapturedPlace {
|
||||||
vec![ty::CapturedPlace { place, info: capture_info, mutability }];
|
place,
|
||||||
|
info: capture_info,
|
||||||
|
mutability,
|
||||||
|
region: None,
|
||||||
|
}];
|
||||||
root_var_min_capture_list.insert(var_hir_id, min_cap_list);
|
root_var_min_capture_list.insert(var_hir_id, min_cap_list);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -640,12 +641,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// Only need to insert when we don't have an ancestor in the existing min capture list
|
// Only need to insert when we don't have an ancestor in the existing min capture list
|
||||||
if !ancestor_found {
|
if !ancestor_found {
|
||||||
let mutability = self.determine_capture_mutability(&typeck_results, &place);
|
let mutability = self.determine_capture_mutability(&typeck_results, &place);
|
||||||
let captured_place =
|
let captured_place = ty::CapturedPlace {
|
||||||
ty::CapturedPlace { place, info: updated_capture_info, mutability };
|
place,
|
||||||
|
info: updated_capture_info,
|
||||||
|
mutability,
|
||||||
|
region: None,
|
||||||
|
};
|
||||||
min_cap_list.push(captured_place);
|
min_cap_list.push(captured_place);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For each capture that is determined to be captured by ref, add region info.
|
||||||
|
for (_, captures) in &mut root_var_min_capture_list {
|
||||||
|
for capture in captures {
|
||||||
|
match capture.info.capture_kind {
|
||||||
|
ty::UpvarCapture::ByRef(_) => {
|
||||||
|
let PlaceBase::Upvar(upvar_id) = capture.place.base else { bug!("expected upvar") };
|
||||||
|
let origin = UpvarRegion(upvar_id, closure_span);
|
||||||
|
let upvar_region = self.next_region_var(origin);
|
||||||
|
capture.region = Some(upvar_region);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"For closure={:?}, min_captures before sorting={:?}",
|
"For closure={:?}, min_captures before sorting={:?}",
|
||||||
closure_def_id, root_var_min_capture_list
|
closure_def_id, root_var_min_capture_list
|
||||||
|
@ -947,7 +967,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
max_capture_info = determine_capture_info(max_capture_info, capture.info);
|
max_capture_info = determine_capture_info(max_capture_info, capture.info);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_capture_kind_on_capture_ty(self.tcx, ty, max_capture_info.capture_kind)
|
apply_capture_kind_on_capture_ty(
|
||||||
|
self.tcx,
|
||||||
|
ty,
|
||||||
|
max_capture_info.capture_kind,
|
||||||
|
Some(&ty::ReErased),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -977,6 +1002,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.tcx,
|
self.tcx,
|
||||||
capture.place.ty(),
|
capture.place.ty(),
|
||||||
capture.info.capture_kind,
|
capture.info.capture_kind,
|
||||||
|
Some(&ty::ReErased),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Checks if a capture implements any of the auto traits
|
// Checks if a capture implements any of the auto traits
|
||||||
|
@ -1470,9 +1496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
place: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
capture_clause: hir::CaptureBy,
|
capture_clause: hir::CaptureBy,
|
||||||
upvar_id: ty::UpvarId,
|
) -> ty::UpvarCapture {
|
||||||
closure_span: Span,
|
|
||||||
) -> ty::UpvarCapture<'tcx> {
|
|
||||||
match capture_clause {
|
match capture_clause {
|
||||||
// In case of a move closure if the data is accessed through a reference we
|
// In case of a move closure if the data is accessed through a reference we
|
||||||
// want to capture by ref to allow precise capture using reborrows.
|
// want to capture by ref to allow precise capture using reborrows.
|
||||||
|
@ -1483,12 +1507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
hir::CaptureBy::Value if !place.deref_tys().any(ty::TyS::is_ref) => {
|
hir::CaptureBy::Value if !place.deref_tys().any(ty::TyS::is_ref) => {
|
||||||
ty::UpvarCapture::ByValue
|
ty::UpvarCapture::ByValue
|
||||||
}
|
}
|
||||||
hir::CaptureBy::Value | hir::CaptureBy::Ref => {
|
hir::CaptureBy::Value | hir::CaptureBy::Ref => ty::UpvarCapture::ByRef(ty::ImmBorrow),
|
||||||
let origin = UpvarRegion(upvar_id, closure_span);
|
|
||||||
let upvar_region = self.next_region_var(origin);
|
|
||||||
let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: upvar_region };
|
|
||||||
ty::UpvarCapture::ByRef(upvar_borrow)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1513,7 +1532,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
fn log_capture_analysis_first_pass(
|
fn log_capture_analysis_first_pass(
|
||||||
&self,
|
&self,
|
||||||
closure_def_id: rustc_hir::def_id::DefId,
|
closure_def_id: rustc_hir::def_id::DefId,
|
||||||
capture_information: &FxIndexMap<Place<'tcx>, ty::CaptureInfo<'tcx>>,
|
capture_information: &FxIndexMap<Place<'tcx>, ty::CaptureInfo>,
|
||||||
closure_span: Span,
|
closure_span: Span,
|
||||||
) {
|
) {
|
||||||
if self.should_log_capture_analysis(closure_def_id) {
|
if self.should_log_capture_analysis(closure_def_id) {
|
||||||
|
@ -1630,8 +1649,8 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
place: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
mut curr_borrow_kind: ty::UpvarCapture<'tcx>,
|
mut curr_borrow_kind: ty::UpvarCapture,
|
||||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
) -> (Place<'tcx>, ty::UpvarCapture) {
|
||||||
let pos = place.projections.iter().enumerate().position(|(i, p)| {
|
let pos = place.projections.iter().enumerate().position(|(i, p)| {
|
||||||
let ty = place.ty_before_projection(i);
|
let ty = place.ty_before_projection(i);
|
||||||
|
|
||||||
|
@ -1675,12 +1694,14 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
|
||||||
fn apply_capture_kind_on_capture_ty<'tcx>(
|
fn apply_capture_kind_on_capture_ty<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
capture_kind: UpvarCapture<'tcx>,
|
capture_kind: UpvarCapture,
|
||||||
|
region: Option<ty::Region<'tcx>>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
match capture_kind {
|
match capture_kind {
|
||||||
ty::UpvarCapture::ByValue => ty,
|
ty::UpvarCapture::ByValue => ty,
|
||||||
ty::UpvarCapture::ByRef(borrow) => tcx
|
ty::UpvarCapture::ByRef(kind) => {
|
||||||
.mk_ref(borrow.region, ty::TypeAndMut { ty: ty, mutbl: borrow.kind.to_mutbl_lossy() }),
|
tcx.mk_ref(region.unwrap(), ty::TypeAndMut { ty: ty, mutbl: kind.to_mutbl_lossy() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1710,8 +1731,6 @@ struct InferBorrowKind<'a, 'tcx> {
|
||||||
// The def-id of the closure whose kind and upvar accesses are being inferred.
|
// The def-id of the closure whose kind and upvar accesses are being inferred.
|
||||||
closure_def_id: DefId,
|
closure_def_id: DefId,
|
||||||
|
|
||||||
closure_span: Span,
|
|
||||||
|
|
||||||
/// For each Place that is captured by the closure, we track the minimal kind of
|
/// For each Place that is captured by the closure, we track the minimal kind of
|
||||||
/// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
|
/// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
|
||||||
///
|
///
|
||||||
|
@ -1749,7 +1768,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||||
place_with_id: &PlaceWithHirId<'tcx>,
|
place_with_id: &PlaceWithHirId<'tcx>,
|
||||||
diag_expr_id: hir::HirId,
|
diag_expr_id: hir::HirId,
|
||||||
) {
|
) {
|
||||||
let tcx = self.fcx.tcx;
|
|
||||||
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else {
|
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -1842,15 +1860,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||||
if let ty::UpvarCapture::ByValue = curr_capture_info.capture_kind {
|
if let ty::UpvarCapture::ByValue = curr_capture_info.capture_kind {
|
||||||
// It's already captured by value, we don't need to do anything here
|
// It's already captured by value, we don't need to do anything here
|
||||||
return;
|
return;
|
||||||
} else if let ty::UpvarCapture::ByRef(curr_upvar_borrow) = curr_capture_info.capture_kind {
|
} else if let ty::UpvarCapture::ByRef(_) = curr_capture_info.capture_kind {
|
||||||
// Use the same region as the current capture information
|
|
||||||
// Doesn't matter since only one of the UpvarBorrow will be used.
|
|
||||||
let new_upvar_borrow = ty::UpvarBorrow { kind, region: curr_upvar_borrow.region };
|
|
||||||
|
|
||||||
let capture_info = ty::CaptureInfo {
|
let capture_info = ty::CaptureInfo {
|
||||||
capture_kind_expr_id: Some(diag_expr_id),
|
capture_kind_expr_id: Some(diag_expr_id),
|
||||||
path_expr_id: Some(diag_expr_id),
|
path_expr_id: Some(diag_expr_id),
|
||||||
capture_kind: ty::UpvarCapture::ByRef(new_upvar_borrow),
|
capture_kind: ty::UpvarCapture::ByRef(kind),
|
||||||
};
|
};
|
||||||
let updated_info = determine_capture_info(curr_capture_info, capture_info);
|
let updated_info = determine_capture_info(curr_capture_info, capture_info);
|
||||||
self.capture_information[&place_with_id.place] = updated_info;
|
self.capture_information[&place_with_id.place] = updated_info;
|
||||||
|
@ -1868,10 +1882,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||||
|
|
||||||
// Initialize to ImmBorrow
|
// Initialize to ImmBorrow
|
||||||
// We will escalate the CaptureKind based on any uses we see or in `process_collected_capture_information`.
|
// We will escalate the CaptureKind based on any uses we see or in `process_collected_capture_information`.
|
||||||
let origin = UpvarRegion(upvar_id, self.closure_span);
|
let capture_kind = ty::UpvarCapture::ByRef(ty::ImmBorrow);
|
||||||
let upvar_region = self.fcx.next_region_var(origin);
|
|
||||||
let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: upvar_region };
|
|
||||||
let capture_kind = ty::UpvarCapture::ByRef(upvar_borrow);
|
|
||||||
|
|
||||||
let expr_id = Some(diag_expr_id);
|
let expr_id = Some(diag_expr_id);
|
||||||
let capture_info = ty::CaptureInfo {
|
let capture_info = ty::CaptureInfo {
|
||||||
|
@ -1894,10 +1905,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
||||||
if let PlaceBase::Upvar(_) = place.base {
|
if let PlaceBase::Upvar(_) = place.base {
|
||||||
// We need to restrict Fake Read precision to avoid fake reading unsafe code,
|
// We need to restrict Fake Read precision to avoid fake reading unsafe code,
|
||||||
// such as deref of a raw pointer.
|
// such as deref of a raw pointer.
|
||||||
let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::UpvarBorrow {
|
let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow);
|
||||||
kind: ty::BorrowKind::ImmBorrow,
|
|
||||||
region: &ty::ReErased,
|
|
||||||
});
|
|
||||||
|
|
||||||
let (place, _) = restrict_capture_precision(place, dummy_capture_kind);
|
let (place, _) = restrict_capture_precision(place, dummy_capture_kind);
|
||||||
|
|
||||||
|
@ -1928,8 +1936,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
||||||
bk: ty::BorrowKind,
|
bk: ty::BorrowKind,
|
||||||
) {
|
) {
|
||||||
// The region here will get discarded/ignored
|
// The region here will get discarded/ignored
|
||||||
let dummy_capture_kind =
|
let dummy_capture_kind = ty::UpvarCapture::ByRef(bk);
|
||||||
ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: bk, region: &ty::ReErased });
|
|
||||||
|
|
||||||
// We only want repr packed restriction to be applied to reading references into a packed
|
// We only want repr packed restriction to be applied to reading references into a packed
|
||||||
// struct, and not when the data is being moved. Therefore we call this method here instead
|
// struct, and not when the data is being moved. Therefore we call this method here instead
|
||||||
|
@ -1948,7 +1955,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match updated_kind {
|
match updated_kind {
|
||||||
ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind, .. }) => match kind {
|
ty::UpvarCapture::ByRef(kind) => match kind {
|
||||||
ty::ImmBorrow => {}
|
ty::ImmBorrow => {}
|
||||||
ty::UniqueImmBorrow => {
|
ty::UniqueImmBorrow => {
|
||||||
self.adjust_upvar_borrow_kind_for_unique(&place_with_id, diag_expr_id);
|
self.adjust_upvar_borrow_kind_for_unique(&place_with_id, diag_expr_id);
|
||||||
|
@ -1973,9 +1980,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
||||||
fn restrict_precision_for_drop_types<'a, 'tcx>(
|
fn restrict_precision_for_drop_types<'a, 'tcx>(
|
||||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||||
mut place: Place<'tcx>,
|
mut place: Place<'tcx>,
|
||||||
mut curr_mode: ty::UpvarCapture<'tcx>,
|
mut curr_mode: ty::UpvarCapture,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
) -> (Place<'tcx>, ty::UpvarCapture) {
|
||||||
let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty(), span);
|
let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty(), span);
|
||||||
|
|
||||||
if let (false, UpvarCapture::ByValue) = (is_copy_type, curr_mode) {
|
if let (false, UpvarCapture::ByValue) = (is_copy_type, curr_mode) {
|
||||||
|
@ -1999,8 +2006,8 @@ fn restrict_precision_for_drop_types<'a, 'tcx>(
|
||||||
/// - No projections are applied on top of Union ADTs, since these require unsafe blocks.
|
/// - No projections are applied on top of Union ADTs, since these require unsafe blocks.
|
||||||
fn restrict_precision_for_unsafe<'tcx>(
|
fn restrict_precision_for_unsafe<'tcx>(
|
||||||
mut place: Place<'tcx>,
|
mut place: Place<'tcx>,
|
||||||
mut curr_mode: ty::UpvarCapture<'tcx>,
|
mut curr_mode: ty::UpvarCapture,
|
||||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
) -> (Place<'tcx>, ty::UpvarCapture) {
|
||||||
if place.base_ty.is_unsafe_ptr() {
|
if place.base_ty.is_unsafe_ptr() {
|
||||||
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
|
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
|
||||||
}
|
}
|
||||||
|
@ -2032,8 +2039,8 @@ fn restrict_precision_for_unsafe<'tcx>(
|
||||||
/// Returns the truncated place and updated cature mode.
|
/// Returns the truncated place and updated cature mode.
|
||||||
fn restrict_capture_precision<'tcx>(
|
fn restrict_capture_precision<'tcx>(
|
||||||
place: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
curr_mode: ty::UpvarCapture<'tcx>,
|
curr_mode: ty::UpvarCapture,
|
||||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
) -> (Place<'tcx>, ty::UpvarCapture) {
|
||||||
let (mut place, mut curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
|
let (mut place, mut curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
|
||||||
|
|
||||||
if place.projections.is_empty() {
|
if place.projections.is_empty() {
|
||||||
|
@ -2060,8 +2067,8 @@ fn restrict_capture_precision<'tcx>(
|
||||||
/// Truncate deref of any reference.
|
/// Truncate deref of any reference.
|
||||||
fn adjust_for_move_closure<'tcx>(
|
fn adjust_for_move_closure<'tcx>(
|
||||||
mut place: Place<'tcx>,
|
mut place: Place<'tcx>,
|
||||||
mut kind: ty::UpvarCapture<'tcx>,
|
mut kind: ty::UpvarCapture,
|
||||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
) -> (Place<'tcx>, ty::UpvarCapture) {
|
||||||
let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
|
let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
|
||||||
|
|
||||||
if let Some(idx) = first_deref {
|
if let Some(idx) = first_deref {
|
||||||
|
@ -2075,8 +2082,8 @@ fn adjust_for_move_closure<'tcx>(
|
||||||
/// from enclosing stack frame.
|
/// from enclosing stack frame.
|
||||||
fn adjust_for_non_move_closure<'tcx>(
|
fn adjust_for_non_move_closure<'tcx>(
|
||||||
mut place: Place<'tcx>,
|
mut place: Place<'tcx>,
|
||||||
mut kind: ty::UpvarCapture<'tcx>,
|
mut kind: ty::UpvarCapture,
|
||||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
) -> (Place<'tcx>, ty::UpvarCapture) {
|
||||||
let contains_deref =
|
let contains_deref =
|
||||||
place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
|
place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
|
||||||
|
|
||||||
|
@ -2119,13 +2126,13 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
|
||||||
fn construct_capture_kind_reason_string<'tcx>(
|
fn construct_capture_kind_reason_string<'tcx>(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
place: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
capture_info: &ty::CaptureInfo<'tcx>,
|
capture_info: &ty::CaptureInfo,
|
||||||
) -> String {
|
) -> String {
|
||||||
let place_str = construct_place_string(tcx, place);
|
let place_str = construct_place_string(tcx, place);
|
||||||
|
|
||||||
let capture_kind_str = match capture_info.capture_kind {
|
let capture_kind_str = match capture_info.capture_kind {
|
||||||
ty::UpvarCapture::ByValue => "ByValue".into(),
|
ty::UpvarCapture::ByValue => "ByValue".into(),
|
||||||
ty::UpvarCapture::ByRef(borrow) => format!("{:?}", borrow.kind),
|
ty::UpvarCapture::ByRef(kind) => format!("{:?}", kind),
|
||||||
};
|
};
|
||||||
|
|
||||||
format!("{} captured as {} here", place_str, capture_kind_str)
|
format!("{} captured as {} here", place_str, capture_kind_str)
|
||||||
|
@ -2140,13 +2147,13 @@ fn construct_path_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
|
||||||
fn construct_capture_info_string<'tcx>(
|
fn construct_capture_info_string<'tcx>(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
place: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
capture_info: &ty::CaptureInfo<'tcx>,
|
capture_info: &ty::CaptureInfo,
|
||||||
) -> String {
|
) -> String {
|
||||||
let place_str = construct_place_string(tcx, place);
|
let place_str = construct_place_string(tcx, place);
|
||||||
|
|
||||||
let capture_kind_str = match capture_info.capture_kind {
|
let capture_kind_str = match capture_info.capture_kind {
|
||||||
ty::UpvarCapture::ByValue => "ByValue".into(),
|
ty::UpvarCapture::ByValue => "ByValue".into(),
|
||||||
ty::UpvarCapture::ByRef(borrow) => format!("{:?}", borrow.kind),
|
ty::UpvarCapture::ByRef(kind) => format!("{:?}", kind),
|
||||||
};
|
};
|
||||||
format!("{} -> {}", place_str, capture_kind_str)
|
format!("{} -> {}", place_str, capture_kind_str)
|
||||||
}
|
}
|
||||||
|
@ -2229,17 +2236,15 @@ fn migration_suggestion_for_2229(
|
||||||
/// would've already handled `E1`, and have an existing capture_information for it.
|
/// would've already handled `E1`, and have an existing capture_information for it.
|
||||||
/// Calling `determine_capture_info(existing_info_e1, current_info_e2)` will return
|
/// Calling `determine_capture_info(existing_info_e1, current_info_e2)` will return
|
||||||
/// `existing_info_e1` in this case, allowing us to point to `E1` in case of diagnostics.
|
/// `existing_info_e1` in this case, allowing us to point to `E1` in case of diagnostics.
|
||||||
fn determine_capture_info<'tcx>(
|
fn determine_capture_info(
|
||||||
capture_info_a: ty::CaptureInfo<'tcx>,
|
capture_info_a: ty::CaptureInfo,
|
||||||
capture_info_b: ty::CaptureInfo<'tcx>,
|
capture_info_b: ty::CaptureInfo,
|
||||||
) -> ty::CaptureInfo<'tcx> {
|
) -> ty::CaptureInfo {
|
||||||
// If the capture kind is equivalent then, we don't need to escalate and can compare the
|
// If the capture kind is equivalent then, we don't need to escalate and can compare the
|
||||||
// expressions.
|
// expressions.
|
||||||
let eq_capture_kind = match (capture_info_a.capture_kind, capture_info_b.capture_kind) {
|
let eq_capture_kind = match (capture_info_a.capture_kind, capture_info_b.capture_kind) {
|
||||||
(ty::UpvarCapture::ByValue, ty::UpvarCapture::ByValue) => true,
|
(ty::UpvarCapture::ByValue, ty::UpvarCapture::ByValue) => true,
|
||||||
(ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => {
|
(ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => ref_a == ref_b,
|
||||||
ref_a.kind == ref_b.kind
|
|
||||||
}
|
|
||||||
(ty::UpvarCapture::ByValue, _) | (ty::UpvarCapture::ByRef(_), _) => false,
|
(ty::UpvarCapture::ByValue, _) | (ty::UpvarCapture::ByRef(_), _) => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2255,7 +2260,7 @@ fn determine_capture_info<'tcx>(
|
||||||
(ty::UpvarCapture::ByValue, _) => capture_info_a,
|
(ty::UpvarCapture::ByValue, _) => capture_info_a,
|
||||||
(_, ty::UpvarCapture::ByValue) => capture_info_b,
|
(_, ty::UpvarCapture::ByValue) => capture_info_b,
|
||||||
(ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => {
|
(ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => {
|
||||||
match (ref_a.kind, ref_b.kind) {
|
match (ref_a, ref_b) {
|
||||||
// Take LHS:
|
// Take LHS:
|
||||||
(ty::UniqueImmBorrow | ty::MutBorrow, ty::ImmBorrow)
|
(ty::UniqueImmBorrow | ty::MutBorrow, ty::ImmBorrow)
|
||||||
| (ty::MutBorrow, ty::UniqueImmBorrow) => capture_info_a,
|
| (ty::MutBorrow, ty::UniqueImmBorrow) => capture_info_a,
|
||||||
|
@ -2283,7 +2288,7 @@ fn determine_capture_info<'tcx>(
|
||||||
/// contained `Deref` of `&mut`.
|
/// contained `Deref` of `&mut`.
|
||||||
fn truncate_place_to_len_and_update_capture_kind<'tcx>(
|
fn truncate_place_to_len_and_update_capture_kind<'tcx>(
|
||||||
place: &mut Place<'tcx>,
|
place: &mut Place<'tcx>,
|
||||||
curr_mode: &mut ty::UpvarCapture<'tcx>,
|
curr_mode: &mut ty::UpvarCapture,
|
||||||
len: usize,
|
len: usize,
|
||||||
) {
|
) {
|
||||||
let is_mut_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Mut));
|
let is_mut_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Mut));
|
||||||
|
@ -2293,15 +2298,12 @@ fn truncate_place_to_len_and_update_capture_kind<'tcx>(
|
||||||
// Note that if the place contained Deref of a raw pointer it would've not been MutBorrow, so
|
// Note that if the place contained Deref of a raw pointer it would've not been MutBorrow, so
|
||||||
// we don't need to worry about that case here.
|
// we don't need to worry about that case here.
|
||||||
match curr_mode {
|
match curr_mode {
|
||||||
ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: ty::BorrowKind::MutBorrow, region }) => {
|
ty::UpvarCapture::ByRef(ty::BorrowKind::MutBorrow) => {
|
||||||
for i in len..place.projections.len() {
|
for i in len..place.projections.len() {
|
||||||
if place.projections[i].kind == ProjectionKind::Deref
|
if place.projections[i].kind == ProjectionKind::Deref
|
||||||
&& is_mut_ref(place.ty_before_projection(i))
|
&& is_mut_ref(place.ty_before_projection(i))
|
||||||
{
|
{
|
||||||
*curr_mode = ty::UpvarCapture::ByRef(ty::UpvarBorrow {
|
*curr_mode = ty::UpvarCapture::ByRef(ty::BorrowKind::UniqueImmBorrow);
|
||||||
kind: ty::BorrowKind::UniqueImmBorrow,
|
|
||||||
region,
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2379,8 +2381,8 @@ fn determine_place_ancestry_relation<'tcx>(
|
||||||
/// ```
|
/// ```
|
||||||
fn truncate_capture_for_optimization<'tcx>(
|
fn truncate_capture_for_optimization<'tcx>(
|
||||||
mut place: Place<'tcx>,
|
mut place: Place<'tcx>,
|
||||||
mut curr_mode: ty::UpvarCapture<'tcx>,
|
mut curr_mode: ty::UpvarCapture,
|
||||||
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
|
) -> (Place<'tcx>, ty::UpvarCapture) {
|
||||||
let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not));
|
let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not));
|
||||||
|
|
||||||
// Find the right-most deref (if any). All the projections that come after this
|
// Find the right-most deref (if any). All the projections that come after this
|
||||||
|
|
|
@ -803,7 +803,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||||
self.delegate.borrow(
|
self.delegate.borrow(
|
||||||
&place_with_id,
|
&place_with_id,
|
||||||
place_with_id.hir_id,
|
place_with_id.hir_id,
|
||||||
upvar_borrow.kind,
|
upvar_borrow,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -970,7 +970,7 @@ pub fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) ->
|
||||||
if !self.locals.contains(&local_id) {
|
if !self.locals.contains(&local_id) {
|
||||||
let capture = match capture.info.capture_kind {
|
let capture = match capture.info.capture_kind {
|
||||||
UpvarCapture::ByValue => CaptureKind::Value,
|
UpvarCapture::ByValue => CaptureKind::Value,
|
||||||
UpvarCapture::ByRef(borrow) => match borrow.kind {
|
UpvarCapture::ByRef(kind) => match kind {
|
||||||
BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
|
BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
|
||||||
BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
|
BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
|
||||||
CaptureKind::Ref(Mutability::Mut)
|
CaptureKind::Ref(Mutability::Mut)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue