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 <wills.jenniferg@gmail.com> Co-authored-by: Logan Mosier <logmosier@gmail.com>
This commit is contained in:
parent
15eaa0020b
commit
76c68aa182
4 changed files with 94 additions and 64 deletions
|
@ -4,7 +4,18 @@ use crate::ty::Ty;
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
use rustc_target::abi::VariantIdx;
|
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 {
|
pub enum PlaceBase {
|
||||||
/// A temporary variable
|
/// A temporary variable
|
||||||
Rvalue,
|
Rvalue,
|
||||||
|
@ -16,7 +27,18 @@ pub enum PlaceBase {
|
||||||
Upvar(ty::UpvarId),
|
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 {
|
pub enum ProjectionKind {
|
||||||
/// A dereference of a pointer, reference or `Box<T>` of the given type
|
/// A dereference of a pointer, reference or `Box<T>` of the given type
|
||||||
Deref,
|
Deref,
|
||||||
|
@ -36,7 +58,18 @@ pub enum ProjectionKind {
|
||||||
Subslice,
|
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> {
|
pub struct Projection<'tcx> {
|
||||||
/// Type after the projection is being applied.
|
/// Type after the projection is being applied.
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
|
@ -48,7 +81,7 @@ pub struct Projection<'tcx> {
|
||||||
/// A `Place` represents how a value is located in memory.
|
/// A `Place` represents how a value is located in memory.
|
||||||
///
|
///
|
||||||
/// This is an HIR version of `mir::Place`
|
/// 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> {
|
pub struct Place<'tcx> {
|
||||||
/// The type of the `PlaceBase`
|
/// The type of the `PlaceBase`
|
||||||
pub base_ty: Ty<'tcx>,
|
pub base_ty: Ty<'tcx>,
|
||||||
|
@ -61,7 +94,7 @@ pub struct Place<'tcx> {
|
||||||
/// A `PlaceWithHirId` represents how a value is located in memory.
|
/// A `PlaceWithHirId` represents how a value is located in memory.
|
||||||
///
|
///
|
||||||
/// This is an HIR version of `mir::Place`
|
/// 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> {
|
pub struct PlaceWithHirId<'tcx> {
|
||||||
/// `HirId` of the expression or pattern producing this value.
|
/// `HirId` of the expression or pattern producing this value.
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
|
|
|
@ -672,7 +672,18 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
|
||||||
#[rustc_diagnostic_item = "Ty"]
|
#[rustc_diagnostic_item = "Ty"]
|
||||||
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
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 struct UpvarPath {
|
||||||
pub hir_id: hir::HirId,
|
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
|
/// 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
|
/// the original var ID (that is, the root variable that is referenced
|
||||||
/// by the upvar) and the ID of the closure expression.
|
/// 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 struct UpvarId {
|
||||||
pub var_path: UpvarPath,
|
pub var_path: UpvarPath,
|
||||||
pub closure_expr_id: LocalDefId,
|
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 {
|
pub enum BorrowKind {
|
||||||
/// Data must be immutable and is aliasable.
|
/// Data must be immutable and is aliasable.
|
||||||
ImmBorrow,
|
ImmBorrow,
|
||||||
|
@ -746,7 +757,7 @@ pub enum BorrowKind {
|
||||||
|
|
||||||
/// 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, HashStable)]
|
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
|
||||||
pub enum UpvarCapture<'tcx> {
|
pub enum UpvarCapture<'tcx> {
|
||||||
/// 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
|
||||||
|
@ -763,7 +774,7 @@ pub enum UpvarCapture<'tcx> {
|
||||||
ByRef(UpvarBorrow<'tcx>),
|
ByRef(UpvarBorrow<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, HashStable)]
|
#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
|
||||||
pub struct UpvarBorrow<'tcx> {
|
pub struct UpvarBorrow<'tcx> {
|
||||||
/// The kind of borrow: by-ref upvars have access to shared
|
/// The kind of borrow: by-ref upvars have access to shared
|
||||||
/// immutable borrows, which are not part of the normal language
|
/// immutable borrows, which are not part of the normal language
|
||||||
|
@ -790,7 +801,7 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis
|
||||||
pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;
|
pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;
|
||||||
|
|
||||||
/// A `Place` and the corresponding `CaptureInfo`.
|
/// 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 struct CapturedPlace<'tcx> {
|
||||||
pub place: HirPlace<'tcx>,
|
pub place: HirPlace<'tcx>,
|
||||||
pub info: CaptureInfo<'tcx>,
|
pub info: CaptureInfo<'tcx>,
|
||||||
|
@ -799,7 +810,7 @@ pub struct CapturedPlace<'tcx> {
|
||||||
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
|
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
|
||||||
/// 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, HashStable)]
|
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
|
||||||
pub struct CaptureInfo<'tcx> {
|
pub struct CaptureInfo<'tcx> {
|
||||||
/// 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
|
||||||
///
|
///
|
||||||
|
|
|
@ -55,6 +55,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
|
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
|
||||||
}
|
}
|
||||||
wbcx.visit_body(body);
|
wbcx.visit_body(body);
|
||||||
|
wbcx.visit_min_capture_map();
|
||||||
wbcx.visit_upvar_capture_map();
|
wbcx.visit_upvar_capture_map();
|
||||||
wbcx.visit_closures();
|
wbcx.visit_closures();
|
||||||
wbcx.visit_liberated_fn_sigs();
|
wbcx.visit_liberated_fn_sigs();
|
||||||
|
@ -331,6 +332,37 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'tcx> 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) {
|
fn visit_upvar_capture_map(&mut self) {
|
||||||
for (upvar_id, upvar_capture) in self.fcx.typeck_results.borrow().upvar_capture_map.iter() {
|
for (upvar_id, upvar_capture) in self.fcx.typeck_results.borrow().upvar_capture_map.iter() {
|
||||||
let new_upvar_capture = match *upvar_capture {
|
let new_upvar_capture = match *upvar_capture {
|
||||||
|
|
|
@ -15,7 +15,6 @@ use rustc_index::vec::Idx;
|
||||||
use rustc_infer::infer::InferCtxt;
|
use rustc_infer::infer::InferCtxt;
|
||||||
use rustc_middle::hir::place::ProjectionKind;
|
use rustc_middle::hir::place::ProjectionKind;
|
||||||
use rustc_middle::ty::{self, adjustment, TyCtxt};
|
use rustc_middle::ty::{self, adjustment, TyCtxt};
|
||||||
use rustc_span::Span;
|
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
|
|
||||||
use crate::mem_categorization as mc;
|
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.
|
/// 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
|
/// 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 place = &captured_place.place;
|
||||||
let capture_info = captured_place.info;
|
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
|
// 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 {
|
} 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(
|
let place_with_id = PlaceWithHirId::new(
|
||||||
capture_info.expr_id.unwrap_or(closure_expr.hir_id),
|
capture_info.expr_id.unwrap_or(closure_expr.hir_id),
|
||||||
place.base_ty,
|
place.base_ty,
|
||||||
PlaceBase::Upvar(upvar_id),
|
place_base,
|
||||||
place.projections.clone(),
|
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<PlaceWithHirId<'tcx>> {
|
|
||||||
// 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>(
|
fn copy_or_move<'a, 'tcx>(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue