Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/closure/analysis.rs')
| -rw-r--r-- | crates/hir-ty/src/infer/closure/analysis.rs | 345 |
1 files changed, 171 insertions, 174 deletions
diff --git a/crates/hir-ty/src/infer/closure/analysis.rs b/crates/hir-ty/src/infer/closure/analysis.rs index 763b145812..b25901cc3b 100644 --- a/crates/hir-ty/src/infer/closure/analysis.rs +++ b/crates/hir-ty/src/infer/closure/analysis.rs @@ -1,24 +1,21 @@ //! Post-inference closure analysis: captures and closure kind. -use std::{cmp, convert::Infallible, mem}; +use std::{cmp, mem}; -use either::Either; +use base_db::Crate; use hir_def::{ - DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId, + DefWithBodyId, FieldId, HasModule, VariantId, expr_store::path::Path, hir::{ Array, AsmOperand, BinaryOp, BindingId, CaptureBy, Expr, ExprId, ExprOrPatId, Pat, PatId, Statement, UnaryOp, }, item_tree::FieldsShape, - lang_item::LangItem, resolver::ValueNs, }; -use hir_expand::name::Name; -use intern::sym; use rustc_ast_ir::Mutability; use rustc_hash::{FxHashMap, FxHashSet}; -use rustc_type_ir::inherent::{IntoKind, SliceLike, Ty as _}; +use rustc_type_ir::inherent::{GenericArgs as _, IntoKind, Ty as _}; use smallvec::{SmallVec, smallvec}; use stdx::{format_to, never}; use syntax::utils::is_raw_identifier; @@ -26,32 +23,97 @@ use syntax::utils::is_raw_identifier; use crate::{ Adjust, Adjustment, BindingMode, db::{HirDatabase, InternedClosure, InternedClosureId}, + display::{DisplayTarget, HirDisplay as _}, infer::InferenceContext, - mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, - next_solver::{DbInterner, EarlyBinder, GenericArgs, Ty, TyKind}, + mir::{BorrowKind, MirSpan, MutBorrowKind}, + next_solver::{ + DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, StoredEarlyBinder, StoredTy, Ty, + TyKind, + infer::{InferCtxt, traits::ObligationCause}, + obligation_ctxt::ObligationCtxt, + }, traits::FnTrait, }; // The below functions handle capture and closure kind (Fn, FnMut, ..) -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) struct HirPlace<'db> { +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) enum HirPlaceProjection { + Deref, + Field(FieldId), + TupleField(u32), +} + +impl HirPlaceProjection { + fn projected_ty<'db>( + self, + infcx: &InferCtxt<'db>, + env: ParamEnv<'db>, + mut base: Ty<'db>, + krate: Crate, + ) -> Ty<'db> { + let interner = infcx.interner; + let db = interner.db; + if base.is_ty_error() { + return Ty::new_error(interner, ErrorGuaranteed); + } + + if matches!(base.kind(), TyKind::Alias(..)) { + let mut ocx = ObligationCtxt::new(infcx); + match ocx.structurally_normalize_ty(&ObligationCause::dummy(), env, base) { + Ok(it) => base = it, + Err(_) => return Ty::new_error(interner, ErrorGuaranteed), + } + } + match self { + HirPlaceProjection::Deref => match base.kind() { + TyKind::RawPtr(inner, _) | TyKind::Ref(_, inner, _) => inner, + TyKind::Adt(adt_def, subst) if adt_def.is_box() => subst.type_at(0), + _ => { + never!( + "Overloaded deref on type {} is not a projection", + base.display(db, DisplayTarget::from_crate(db, krate)) + ); + Ty::new_error(interner, ErrorGuaranteed) + } + }, + HirPlaceProjection::Field(f) => match base.kind() { + TyKind::Adt(_, subst) => { + db.field_types(f.parent)[f.local_id].get().instantiate(interner, subst) + } + ty => { + never!("Only adt has field, found {:?}", ty); + Ty::new_error(interner, ErrorGuaranteed) + } + }, + HirPlaceProjection::TupleField(idx) => match base.kind() { + TyKind::Tuple(subst) => { + subst.as_slice().get(idx as usize).copied().unwrap_or_else(|| { + never!("Out of bound tuple field"); + Ty::new_error(interner, ErrorGuaranteed) + }) + } + ty => { + never!("Only tuple has tuple field: {:?}", ty); + Ty::new_error(interner, ErrorGuaranteed) + } + }, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, salsa::Update)] +pub(crate) struct HirPlace { pub(crate) local: BindingId, - pub(crate) projections: Vec<ProjectionElem<Infallible, Ty<'db>>>, + pub(crate) projections: Vec<HirPlaceProjection>, } -impl<'db> HirPlace<'db> { - fn ty(&self, ctx: &mut InferenceContext<'_, 'db>) -> Ty<'db> { - let mut ty = ctx.table.resolve_completely(ctx.result[self.local]); +impl HirPlace { + fn ty<'db>(&self, ctx: &mut InferenceContext<'_, 'db>) -> Ty<'db> { + let krate = ctx.krate(); + let mut ty = ctx.table.resolve_completely(ctx.result.binding_ty(self.local)); for p in &self.projections { - ty = p.projected_ty( - &ctx.table.infer_ctxt, - ty, - |_, _, _| { - unreachable!("Closure field only happens in MIR"); - }, - ctx.owner.module(ctx.db).krate(), - ); + ty = p.projected_ty(ctx.infcx(), ctx.table.param_env, ty, krate); } ty } @@ -64,7 +126,7 @@ impl<'db> HirPlace<'db> { if let CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow, }) = current_capture - && self.projections[len..].contains(&ProjectionElem::Deref) + && self.projections[len..].contains(&HirPlaceProjection::Deref) { current_capture = CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }); @@ -79,9 +141,9 @@ pub enum CaptureKind { ByValue, } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct CapturedItem<'db> { - pub(crate) place: HirPlace<'db>, +#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)] +pub struct CapturedItem { + pub(crate) place: HirPlace, pub(crate) kind: CaptureKind, /// The inner vec is the stacks; the outer vec is for each capture reference. /// @@ -90,22 +152,22 @@ pub struct CapturedItem<'db> { /// copy all captures of the inner closure to the outer closure, and then we may /// truncate them, and we want the correct span to be reported. span_stacks: SmallVec<[SmallVec<[MirSpan; 3]>; 3]>, - pub(crate) ty: EarlyBinder<'db, Ty<'db>>, + pub(crate) ty: StoredEarlyBinder<StoredTy>, } -impl<'db> CapturedItem<'db> { +impl CapturedItem { pub fn local(&self) -> BindingId { self.place.local } /// Returns whether this place has any field (aka. non-deref) projections. pub fn has_field_projections(&self) -> bool { - self.place.projections.iter().any(|it| !matches!(it, ProjectionElem::Deref)) + self.place.projections.iter().any(|it| !matches!(it, HirPlaceProjection::Deref)) } - pub fn ty(&self, db: &'db dyn HirDatabase, subst: GenericArgs<'db>) -> Ty<'db> { - let interner = DbInterner::new_with(db, None, None); - self.ty.instantiate(interner, subst.split_closure_args_untupled().parent_args) + pub fn ty<'db>(&self, db: &'db dyn HirDatabase, subst: GenericArgs<'db>) -> Ty<'db> { + let interner = DbInterner::new_no_crate(db); + self.ty.get().instantiate(interner, subst.as_closure().parent_args()) } pub fn kind(&self) -> CaptureKind { @@ -122,8 +184,8 @@ impl<'db> CapturedItem<'db> { let mut result = body[self.place.local].name.as_str().to_owned(); for proj in &self.place.projections { match proj { - ProjectionElem::Deref => {} - ProjectionElem::Field(Either::Left(f)) => { + HirPlaceProjection::Deref => {} + HirPlaceProjection::Field(f) => { let variant_data = f.parent.fields(db); match variant_data.shape { FieldsShape::Record => { @@ -140,18 +202,12 @@ impl<'db> CapturedItem<'db> { FieldsShape::Unit => {} } } - ProjectionElem::Field(Either::Right(f)) => format_to!(result, "_{}", f.index), - &ProjectionElem::ClosureField(field) => format_to!(result, "_{field}"), - ProjectionElem::Index(_) - | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::OpaqueCast(_) => { - never!("Not happen in closure capture"); - continue; + HirPlaceProjection::TupleField(idx) => { + format_to!(result, "_{idx}") } } } - if is_raw_identifier(&result, owner.module(db).krate().data(db).edition) { + if is_raw_identifier(&result, owner.module(db).krate(db).data(db).edition) { result.insert_str(0, "r#"); } result @@ -165,8 +221,8 @@ impl<'db> CapturedItem<'db> { for proj in &self.place.projections { match proj { // In source code autoderef kicks in. - ProjectionElem::Deref => {} - ProjectionElem::Field(Either::Left(f)) => { + HirPlaceProjection::Deref => {} + HirPlaceProjection::Field(f) => { let variant_data = f.parent.fields(db); match variant_data.shape { FieldsShape::Record => format_to!( @@ -186,19 +242,8 @@ impl<'db> CapturedItem<'db> { FieldsShape::Unit => {} } } - ProjectionElem::Field(Either::Right(f)) => { - let field = f.index; - format_to!(result, ".{field}"); - } - &ProjectionElem::ClosureField(field) => { - format_to!(result, ".{field}"); - } - ProjectionElem::Index(_) - | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::OpaqueCast(_) => { - never!("Not happen in closure capture"); - continue; + HirPlaceProjection::TupleField(idx) => { + format_to!(result, ".{idx}") } } } @@ -207,7 +252,7 @@ impl<'db> CapturedItem<'db> { .projections .iter() .rev() - .take_while(|proj| matches!(proj, ProjectionElem::Deref)) + .take_while(|proj| matches!(proj, HirPlaceProjection::Deref)) .count(); result.insert_str(0, &"*".repeat(final_derefs_count)); result @@ -221,11 +266,11 @@ impl<'db> CapturedItem<'db> { let mut field_need_paren = false; for proj in &self.place.projections { match proj { - ProjectionElem::Deref => { + HirPlaceProjection::Deref => { result = format!("*{result}"); field_need_paren = true; } - ProjectionElem::Field(Either::Left(f)) => { + HirPlaceProjection::Field(f) => { if field_need_paren { result = format!("({result})"); } @@ -245,28 +290,13 @@ impl<'db> CapturedItem<'db> { result = format!("{result}.{field}"); field_need_paren = false; } - ProjectionElem::Field(Either::Right(f)) => { - let field = f.index; + HirPlaceProjection::TupleField(idx) => { if field_need_paren { result = format!("({result})"); } - result = format!("{result}.{field}"); - field_need_paren = false; - } - &ProjectionElem::ClosureField(field) => { - if field_need_paren { - result = format!("({result})"); - } - result = format!("{result}.{field}"); + result = format!("{result}.{idx}"); field_need_paren = false; } - ProjectionElem::Index(_) - | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::OpaqueCast(_) => { - never!("Not happen in closure capture"); - continue; - } } } result @@ -274,15 +304,15 @@ impl<'db> CapturedItem<'db> { } #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) struct CapturedItemWithoutTy<'db> { - pub(crate) place: HirPlace<'db>, +pub(crate) struct CapturedItemWithoutTy { + pub(crate) place: HirPlace, pub(crate) kind: CaptureKind, /// The inner vec is the stacks; the outer vec is for each capture reference. pub(crate) span_stacks: SmallVec<[SmallVec<[MirSpan; 3]>; 3]>, } -impl<'db> CapturedItemWithoutTy<'db> { - fn with_ty(self, ctx: &mut InferenceContext<'_, 'db>) -> CapturedItem<'db> { +impl CapturedItemWithoutTy { + fn with_ty(self, ctx: &mut InferenceContext<'_, '_>) -> CapturedItem { let ty = self.place.ty(ctx); let ty = match &self.kind { CaptureKind::ByValue => ty, @@ -291,20 +321,20 @@ impl<'db> CapturedItemWithoutTy<'db> { BorrowKind::Mut { .. } => Mutability::Mut, _ => Mutability::Not, }; - Ty::new_ref(ctx.interner(), ctx.types.re_error, ty, m) + Ty::new_ref(ctx.interner(), ctx.types.regions.error, ty, m) } }; CapturedItem { place: self.place, kind: self.kind, span_stacks: self.span_stacks, - ty: EarlyBinder::bind(ty), + ty: StoredEarlyBinder::bind(ty.store()), } } } impl<'db> InferenceContext<'_, 'db> { - fn place_of_expr(&mut self, tgt_expr: ExprId) -> Option<HirPlace<'db>> { + fn place_of_expr(&mut self, tgt_expr: ExprId) -> Option<HirPlace> { let r = self.place_of_expr_without_adjust(tgt_expr)?; let adjustments = self.result.expr_adjustments.get(&tgt_expr).map(|it| &**it).unwrap_or_default(); @@ -312,7 +342,7 @@ impl<'db> InferenceContext<'_, 'db> { } /// Pushes the span into `current_capture_span_stack`, *without clearing it first*. - fn path_place(&mut self, path: &Path, id: ExprOrPatId) -> Option<HirPlace<'db>> { + fn path_place(&mut self, path: &Path, id: ExprOrPatId) -> Option<HirPlace> { if path.type_anchor().is_some() { return None; } @@ -333,7 +363,7 @@ impl<'db> InferenceContext<'_, 'db> { } /// Changes `current_capture_span_stack` to contain the stack of spans for this expr. - fn place_of_expr_without_adjust(&mut self, tgt_expr: ExprId) -> Option<HirPlace<'db>> { + fn place_of_expr_without_adjust(&mut self, tgt_expr: ExprId) -> Option<HirPlace> { self.current_capture_span_stack.clear(); match &self.body[tgt_expr] { Expr::Path(p) => { @@ -347,17 +377,21 @@ impl<'db> InferenceContext<'_, 'db> { let mut place = self.place_of_expr(*expr)?; let field = self.result.field_resolution(tgt_expr)?; self.current_capture_span_stack.push(MirSpan::ExprId(tgt_expr)); - place.projections.push(ProjectionElem::Field(field)); + place.projections.push(field.either(HirPlaceProjection::Field, |f| { + HirPlaceProjection::TupleField(f.index) + })); return Some(place); } Expr::UnaryOp { expr, op: UnaryOp::Deref } => { - if matches!( - self.expr_ty_after_adjustments(*expr).kind(), - TyKind::Ref(..) | TyKind::RawPtr(..) - ) { + let is_builtin_deref = match self.expr_ty(*expr).kind() { + TyKind::Ref(..) | TyKind::RawPtr(..) => true, + TyKind::Adt(adt_def, _) if adt_def.is_box() => true, + _ => false, + }; + if is_builtin_deref { let mut place = self.place_of_expr(*expr)?; self.current_capture_span_stack.push(MirSpan::ExprId(tgt_expr)); - place.projections.push(ProjectionElem::Deref); + place.projections.push(HirPlaceProjection::Deref); return Some(place); } } @@ -366,7 +400,7 @@ impl<'db> InferenceContext<'_, 'db> { None } - fn push_capture(&mut self, place: HirPlace<'db>, kind: CaptureKind) { + fn push_capture(&mut self, place: HirPlace, kind: CaptureKind) { self.current_captures.push(CapturedItemWithoutTy { place, kind, @@ -374,11 +408,7 @@ impl<'db> InferenceContext<'_, 'db> { }); } - fn truncate_capture_spans( - &self, - capture: &mut CapturedItemWithoutTy<'db>, - mut truncate_to: usize, - ) { + fn truncate_capture_spans(&self, capture: &mut CapturedItemWithoutTy, mut truncate_to: usize) { // The first span is the identifier, and it must always remain. truncate_to += 1; for span_stack in &mut capture.span_stacks { @@ -403,14 +433,14 @@ impl<'db> InferenceContext<'_, 'db> { } } - fn ref_expr(&mut self, expr: ExprId, place: Option<HirPlace<'db>>) { + fn ref_expr(&mut self, expr: ExprId, place: Option<HirPlace>) { if let Some(place) = place { self.add_capture(place, CaptureKind::ByRef(BorrowKind::Shared)); } self.walk_expr(expr); } - fn add_capture(&mut self, place: HirPlace<'db>, kind: CaptureKind) { + fn add_capture(&mut self, place: HirPlace, kind: CaptureKind) { if self.is_upvar(&place) { self.push_capture(place, kind); } @@ -426,7 +456,7 @@ impl<'db> InferenceContext<'_, 'db> { } } - fn mutate_expr(&mut self, expr: ExprId, place: Option<HirPlace<'db>>) { + fn mutate_expr(&mut self, expr: ExprId, place: Option<HirPlace>) { if let Some(place) = place { self.add_capture( place, @@ -443,7 +473,7 @@ impl<'db> InferenceContext<'_, 'db> { self.walk_expr(expr); } - fn consume_place(&mut self, place: HirPlace<'db>) { + fn consume_place(&mut self, place: HirPlace) { if self.is_upvar(&place) { let ty = place.ty(self); let kind = if self.is_ty_copy(ty) { @@ -455,7 +485,7 @@ impl<'db> InferenceContext<'_, 'db> { } } - fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment<'db>]) { + fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment]) { if let Some((last, rest)) = adjustment.split_last() { match &last.kind { Adjust::NeverToAny | Adjust::Deref(None) | Adjust::Pointer(_) => { @@ -476,12 +506,7 @@ impl<'db> InferenceContext<'_, 'db> { } } - fn ref_capture_with_adjusts( - &mut self, - m: Mutability, - tgt_expr: ExprId, - rest: &[Adjustment<'db>], - ) { + fn ref_capture_with_adjusts(&mut self, m: Mutability, tgt_expr: ExprId, rest: &[Adjustment]) { let capture_kind = match m { Mutability::Mut => CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::Default }), Mutability::Not => CaptureKind::ByRef(BorrowKind::Shared), @@ -609,28 +634,19 @@ impl<'db> InferenceContext<'_, 'db> { } Expr::Field { expr, name: _ } => self.select_from_expr(*expr), Expr::UnaryOp { expr, op: UnaryOp::Deref } => { - if matches!( - self.expr_ty_after_adjustments(*expr).kind(), - TyKind::Ref(..) | TyKind::RawPtr(..) - ) { - self.select_from_expr(*expr); - } else if let Some((f, _)) = self.result.method_resolution(tgt_expr) { - let mutability = 'b: { - if let Some(deref_trait) = - self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait()) - && let Some(deref_fn) = deref_trait - .trait_items(self.db) - .method_by_name(&Name::new_symbol_root(sym::deref_mut)) - { - break 'b deref_fn == f; + if self.result.method_resolution(tgt_expr).is_some() { + // Overloaded deref. + match self.expr_ty_after_adjustments(*expr).kind() { + TyKind::Ref(_, _, mutability) => { + let place = self.place_of_expr(*expr); + match mutability { + Mutability::Mut => self.mutate_expr(*expr, place), + Mutability::Not => self.ref_expr(*expr, place), + } } - false - }; - let place = self.place_of_expr(*expr); - if mutability { - self.mutate_expr(*expr, place); - } else { - self.ref_expr(*expr, place); + // FIXME: Is this correct wrt. raw pointer derefs? + TyKind::RawPtr(..) => self.select_from_expr(*expr), + _ => never!("deref adjustments should include taking a mutable reference"), } } else { self.select_from_expr(*expr); @@ -788,7 +804,7 @@ impl<'db> InferenceContext<'_, 'db> { } Pat::Bind { id, .. } => match self.result.binding_modes[p] { crate::BindingMode::Move => { - if self.is_ty_copy(self.result.type_of_binding[*id]) { + if self.is_ty_copy(self.result.binding_ty(*id)) { update_result(CaptureKind::ByRef(BorrowKind::Shared)); } else { update_result(CaptureKind::ByValue); @@ -806,21 +822,7 @@ impl<'db> InferenceContext<'_, 'db> { self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut)); } - fn expr_ty(&self, expr: ExprId) -> Ty<'db> { - self.result[expr] - } - - fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> { - let mut ty = None; - if let Some(it) = self.result.expr_adjustments.get(&e) - && let Some(it) = it.last() - { - ty = Some(it.target); - } - ty.unwrap_or_else(|| self.expr_ty(e)) - } - - fn is_upvar(&self, place: &HirPlace<'db>) -> bool { + fn is_upvar(&self, place: &HirPlace) -> bool { if let Some(c) = self.current_closure { let InternedClosure(_, root) = self.db.lookup_intern_closure(c); return self.body.is_binding_upvar(place.local, root); @@ -852,7 +854,7 @@ impl<'db> InferenceContext<'_, 'db> { // FIXME: Borrow checker problems without this. let mut current_captures = std::mem::take(&mut self.current_captures); for capture in &mut current_captures { - let mut ty = self.table.resolve_completely(self.result[capture.place.local]); + let mut ty = self.table.resolve_completely(self.result.binding_ty(capture.place.local)); if ty.is_raw_ptr() || ty.is_union() { capture.kind = CaptureKind::ByRef(BorrowKind::Shared); self.truncate_capture_spans(capture, 0); @@ -862,11 +864,9 @@ impl<'db> InferenceContext<'_, 'db> { for (i, p) in capture.place.projections.iter().enumerate() { ty = p.projected_ty( &self.table.infer_ctxt, + self.table.param_env, ty, - |_, _, _| { - unreachable!("Closure field only happens in MIR"); - }, - self.owner.module(self.db).krate(), + self.owner.module(self.db).krate(self.db), ); if ty.is_raw_ptr() || ty.is_union() { capture.kind = CaptureKind::ByRef(BorrowKind::Shared); @@ -884,7 +884,7 @@ impl<'db> InferenceContext<'_, 'db> { let mut current_captures = std::mem::take(&mut self.current_captures); for capture in &mut current_captures { if let Some(first_deref) = - capture.place.projections.iter().position(|proj| *proj == ProjectionElem::Deref) + capture.place.projections.iter().position(|proj| *proj == HirPlaceProjection::Deref) { self.truncate_capture_spans(capture, first_deref); capture.place.projections.truncate(first_deref); @@ -896,7 +896,7 @@ impl<'db> InferenceContext<'_, 'db> { fn minimize_captures(&mut self) { self.current_captures.sort_unstable_by_key(|it| it.place.projections.len()); - let mut hash_map = FxHashMap::<HirPlace<'db>, usize>::default(); + let mut hash_map = FxHashMap::<HirPlace, usize>::default(); let result = mem::take(&mut self.current_captures); for mut item in result { let mut lookup_place = HirPlace { local: item.place.local, projections: vec![] }; @@ -907,7 +907,7 @@ impl<'db> InferenceContext<'_, 'db> { } match it.next() { Some(it) => { - lookup_place.projections.push(it.clone()); + lookup_place.projections.push(*it); } None => break None, } @@ -931,10 +931,10 @@ impl<'db> InferenceContext<'_, 'db> { } } - fn consume_with_pat(&mut self, mut place: HirPlace<'db>, tgt_pat: PatId) { + fn consume_with_pat(&mut self, mut place: HirPlace, tgt_pat: PatId) { let adjustments_count = self.result.pat_adjustments.get(&tgt_pat).map(|it| it.len()).unwrap_or_default(); - place.projections.extend((0..adjustments_count).map(|_| ProjectionElem::Deref)); + place.projections.extend((0..adjustments_count).map(|_| HirPlaceProjection::Deref)); self.current_capture_span_stack .extend((0..adjustments_count).map(|_| MirSpan::PatId(tgt_pat))); 'reset_span_stack: { @@ -942,7 +942,7 @@ impl<'db> InferenceContext<'_, 'db> { Pat::Missing | Pat::Wild => (), Pat::Tuple { args, ellipsis } => { let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize)); - let field_count = match self.result[tgt_pat].kind() { + let field_count = match self.result.pat_ty(tgt_pat).kind() { TyKind::Tuple(s) => s.len(), _ => break 'reset_span_stack, }; @@ -951,10 +951,7 @@ impl<'db> InferenceContext<'_, 'db> { for (&arg, i) in it { let mut p = place.clone(); self.current_capture_span_stack.push(MirSpan::PatId(arg)); - p.projections.push(ProjectionElem::Field(Either::Right(TupleFieldId { - tuple: TupleId(!0), // dummy this, as its unused anyways - index: i as u32, - }))); + p.projections.push(HirPlaceProjection::TupleField(i as u32)); self.consume_with_pat(p, arg); self.current_capture_span_stack.pop(); } @@ -981,10 +978,10 @@ impl<'db> InferenceContext<'_, 'db> { }; let mut p = place.clone(); self.current_capture_span_stack.push(MirSpan::PatId(arg)); - p.projections.push(ProjectionElem::Field(Either::Left(FieldId { + p.projections.push(HirPlaceProjection::Field(FieldId { parent: variant, local_id, - }))); + })); self.consume_with_pat(p, arg); self.current_capture_span_stack.pop(); } @@ -1036,10 +1033,10 @@ impl<'db> InferenceContext<'_, 'db> { for (&arg, (i, _)) in it { let mut p = place.clone(); self.current_capture_span_stack.push(MirSpan::PatId(arg)); - p.projections.push(ProjectionElem::Field(Either::Left(FieldId { + p.projections.push(HirPlaceProjection::Field(FieldId { parent: variant, local_id: i, - }))); + })); self.consume_with_pat(p, arg); self.current_capture_span_stack.pop(); } @@ -1048,7 +1045,7 @@ impl<'db> InferenceContext<'_, 'db> { } Pat::Ref { pat, mutability: _ } => { self.current_capture_span_stack.push(MirSpan::PatId(tgt_pat)); - place.projections.push(ProjectionElem::Deref); + place.projections.push(HirPlaceProjection::Deref); self.consume_with_pat(place, *pat); self.current_capture_span_stack.pop(); } @@ -1102,7 +1099,7 @@ impl<'db> InferenceContext<'_, 'db> { CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow }) - ) && !item.place.projections.contains(&ProjectionElem::Deref) + ) && !item.place.projections.contains(&HirPlaceProjection::Deref) { // FIXME: remove the `mutated_bindings_in_closure` completely and add proper fake reads in // MIR. I didn't do that due duplicate diagnostics. @@ -1242,17 +1239,17 @@ impl<'db> InferenceContext<'_, 'db> { } /// Call this only when the last span in the stack isn't a split. -fn apply_adjusts_to_place<'db>( +fn apply_adjusts_to_place( current_capture_span_stack: &mut Vec<MirSpan>, - mut r: HirPlace<'db>, - adjustments: &[Adjustment<'db>], -) -> Option<HirPlace<'db>> { + mut r: HirPlace, + adjustments: &[Adjustment], +) -> Option<HirPlace> { let span = *current_capture_span_stack.last().expect("empty capture span stack"); for adj in adjustments { match &adj.kind { Adjust::Deref(None) => { current_capture_span_stack.push(span); - r.projections.push(ProjectionElem::Deref); + r.projections.push(HirPlaceProjection::Deref); } _ => return None, } |