Rollup merge of #74424 - sexxi-goose:move_hir_place, r=nikomatsakis
Move hir::Place to librustc_middle/hir Needed to support https://github.com/rust-lang/project-rfc-2229/issues/7 Currently rustc_typeck depends on rustc_middle for definition TypeckTables, etc. For supporting project-rfc-2229#7, rustc_middle would've to depend on rustc_typeck for Place -- introducing a circular dependency. This resembles the MIR equivalent of `Place` located in `lbrustc_middle/mir`. Separate PR for this move will make the actual PR for using Places to represent captures cleaner/more focused. r? @nikomatsakis @matthewjasper
This commit is contained in:
commit
222d250837
@ -4,6 +4,7 @@
|
||||
|
||||
pub mod exports;
|
||||
pub mod map;
|
||||
pub mod place;
|
||||
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::ty::query::Providers;
|
||||
|
115
src/librustc_middle/hir/place.rs
Normal file
115
src/librustc_middle/hir/place.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use crate::ty;
|
||||
use crate::ty::Ty;
|
||||
|
||||
use rustc_hir::HirId;
|
||||
use rustc_target::abi::VariantIdx;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub enum PlaceBase {
|
||||
/// A temporary variable
|
||||
Rvalue,
|
||||
/// A named `static` item
|
||||
StaticItem,
|
||||
/// A named local variable
|
||||
Local(HirId),
|
||||
/// An upvar referenced by closure env
|
||||
Upvar(ty::UpvarId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub enum ProjectionKind {
|
||||
/// A dereference of a pointer, reference or `Box<T>` of the given type
|
||||
Deref,
|
||||
|
||||
/// `B.F` where `B` is the base expression and `F` is
|
||||
/// the field. The field is identified by which variant
|
||||
/// it appears in along with a field index. The variant
|
||||
/// is used for enums.
|
||||
Field(u32, VariantIdx),
|
||||
|
||||
/// Some index like `B[x]`, where `B` is the base
|
||||
/// expression. We don't preserve the index `x` because
|
||||
/// we won't need it.
|
||||
Index,
|
||||
|
||||
/// A subslice covering a range of values like `B[x..y]`.
|
||||
Subslice,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct Projection<'tcx> {
|
||||
/// Type after the projection is being applied.
|
||||
pub ty: Ty<'tcx>,
|
||||
|
||||
/// Defines the type of access
|
||||
pub kind: ProjectionKind,
|
||||
}
|
||||
|
||||
/// A `Place` represents how a value is located in memory.
|
||||
///
|
||||
/// This is an HIR version of `mir::Place`
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct Place<'tcx> {
|
||||
/// The type of the `PlaceBase`
|
||||
pub base_ty: Ty<'tcx>,
|
||||
/// The "outermost" place that holds this value.
|
||||
pub base: PlaceBase,
|
||||
/// How this place is derived from the base place.
|
||||
pub projections: Vec<Projection<'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, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct PlaceWithHirId<'tcx> {
|
||||
/// `HirId` of the expression or pattern producing this value.
|
||||
pub hir_id: HirId,
|
||||
|
||||
/// Information about the `Place`
|
||||
pub place: Place<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> PlaceWithHirId<'tcx> {
|
||||
pub fn new(
|
||||
hir_id: HirId,
|
||||
base_ty: Ty<'tcx>,
|
||||
base: PlaceBase,
|
||||
projections: Vec<Projection<'tcx>>,
|
||||
) -> PlaceWithHirId<'tcx> {
|
||||
PlaceWithHirId {
|
||||
hir_id: hir_id,
|
||||
place: Place { base_ty: base_ty, base: base, projections: projections },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Place<'tcx> {
|
||||
/// Returns an iterator of the types that have to be dereferenced to access
|
||||
/// the `Place`.
|
||||
///
|
||||
/// The types are in the reverse order that they are applied. So if
|
||||
/// `x: &*const u32` and the `Place` is `**x`, then the types returned are
|
||||
///`*const u32` then `&*const u32`.
|
||||
pub fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
|
||||
self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
|
||||
if ProjectionKind::Deref == proj.kind {
|
||||
Some(self.ty_before_projection(index))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the type of this `Place` after all projections have been applied.
|
||||
pub fn ty(&self) -> Ty<'tcx> {
|
||||
self.projections.last().map_or_else(|| self.base_ty, |proj| proj.ty)
|
||||
}
|
||||
|
||||
/// Returns the type of this `Place` immediately before `projection_index`th projection
|
||||
/// is applied.
|
||||
pub fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> {
|
||||
assert!(projection_index < self.projections.len());
|
||||
if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty }
|
||||
}
|
||||
}
|
@ -82,6 +82,7 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::PatKind;
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{self, RegionObligation, RegionckMode};
|
||||
use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId};
|
||||
use rustc_middle::ty::adjustment;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
@ -442,7 +443,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
fn constrain_adjustments(
|
||||
&mut self,
|
||||
expr: &hir::Expr<'_>,
|
||||
) -> mc::McResult<mc::PlaceWithHirId<'tcx>> {
|
||||
) -> mc::McResult<PlaceWithHirId<'tcx>> {
|
||||
debug!("constrain_adjustments(expr={:?})", expr);
|
||||
|
||||
let mut place = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
|
||||
@ -483,10 +484,10 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
|
||||
fn check_safety_of_rvalue_destructor_if_necessary(
|
||||
&mut self,
|
||||
place_with_id: &mc::PlaceWithHirId<'tcx>,
|
||||
place_with_id: &PlaceWithHirId<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
if let mc::PlaceBase::Rvalue = place_with_id.place.base {
|
||||
if let PlaceBase::Rvalue = place_with_id.place.base {
|
||||
if place_with_id.place.projections.is_empty() {
|
||||
let typ = self.resolve_type(place_with_id.place.ty());
|
||||
let body_id = self.body_id;
|
||||
@ -573,7 +574,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
|
||||
/// Link lifetimes of any ref bindings in `root_pat` to the pointers found
|
||||
/// in the discriminant, if needed.
|
||||
fn link_pattern(&self, discr_cmt: mc::PlaceWithHirId<'tcx>, root_pat: &hir::Pat<'_>) {
|
||||
fn link_pattern(&self, discr_cmt: PlaceWithHirId<'tcx>, root_pat: &hir::Pat<'_>) {
|
||||
debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat);
|
||||
ignore_err!(self.with_mc(|mc| {
|
||||
mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, hir::Pat { kind, span, hir_id }| {
|
||||
@ -594,7 +595,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
fn link_autoref(
|
||||
&self,
|
||||
expr: &hir::Expr<'_>,
|
||||
expr_cmt: &mc::PlaceWithHirId<'tcx>,
|
||||
expr_cmt: &PlaceWithHirId<'tcx>,
|
||||
autoref: &adjustment::AutoBorrow<'tcx>,
|
||||
) {
|
||||
debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt);
|
||||
@ -615,7 +616,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
span: Span,
|
||||
id: hir::HirId,
|
||||
mutbl: hir::Mutability,
|
||||
cmt_borrowed: &mc::PlaceWithHirId<'tcx>,
|
||||
cmt_borrowed: &PlaceWithHirId<'tcx>,
|
||||
) {
|
||||
debug!(
|
||||
"link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
|
||||
@ -638,7 +639,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
span: Span,
|
||||
borrow_region: ty::Region<'tcx>,
|
||||
borrow_kind: ty::BorrowKind,
|
||||
borrow_place: &mc::PlaceWithHirId<'tcx>,
|
||||
borrow_place: &PlaceWithHirId<'tcx>,
|
||||
) {
|
||||
let origin = infer::DataBorrowed(borrow_place.place.ty(), span);
|
||||
self.type_must_outlive(origin, borrow_place.place.ty(), borrow_region);
|
||||
@ -659,7 +660,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
_ => assert!(pointer_ty.is_box(), "unexpected built-in deref type {}", pointer_ty),
|
||||
}
|
||||
}
|
||||
if let mc::PlaceBase::Upvar(upvar_id) = borrow_place.place.base {
|
||||
if let PlaceBase::Upvar(upvar_id) = borrow_place.place.base {
|
||||
self.link_upvar_region(span, borrow_region, upvar_id);
|
||||
}
|
||||
}
|
||||
|
@ -33,14 +33,13 @@
|
||||
use super::FnCtxt;
|
||||
|
||||
use crate::expr_use_visitor as euv;
|
||||
use crate::mem_categorization as mc;
|
||||
use crate::mem_categorization::PlaceBase;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||
use rustc_infer::infer::UpvarRegion;
|
||||
use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
@ -276,7 +275,7 @@ struct InferBorrowKind<'a, 'tcx> {
|
||||
impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||
fn adjust_upvar_borrow_kind_for_consume(
|
||||
&mut self,
|
||||
place_with_id: &mc::PlaceWithHirId<'tcx>,
|
||||
place_with_id: &PlaceWithHirId<'tcx>,
|
||||
mode: euv::ConsumeMode,
|
||||
) {
|
||||
debug!(
|
||||
@ -315,7 +314,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||
/// Indicates that `place_with_id` is being directly mutated (e.g., assigned
|
||||
/// to). If the place is based on a by-ref upvar, this implies that
|
||||
/// the upvar must be borrowed using an `&mut` borrow.
|
||||
fn adjust_upvar_borrow_kind_for_mut(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>) {
|
||||
fn adjust_upvar_borrow_kind_for_mut(&mut self, place_with_id: &PlaceWithHirId<'tcx>) {
|
||||
debug!("adjust_upvar_borrow_kind_for_mut(place_with_id={:?})", place_with_id);
|
||||
|
||||
if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
|
||||
@ -340,7 +339,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_upvar_borrow_kind_for_unique(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>) {
|
||||
fn adjust_upvar_borrow_kind_for_unique(&mut self, place_with_id: &PlaceWithHirId<'tcx>) {
|
||||
debug!("adjust_upvar_borrow_kind_for_unique(place_with_id={:?})", place_with_id);
|
||||
|
||||
if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
|
||||
@ -470,12 +469,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
||||
fn consume(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, mode: euv::ConsumeMode) {
|
||||
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, mode: euv::ConsumeMode) {
|
||||
debug!("consume(place_with_id={:?},mode={:?})", place_with_id, mode);
|
||||
self.adjust_upvar_borrow_kind_for_consume(place_with_id, mode);
|
||||
}
|
||||
|
||||
fn borrow(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, bk: ty::BorrowKind) {
|
||||
fn borrow(&mut self, place_with_id: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) {
|
||||
debug!("borrow(place_with_id={:?}, bk={:?})", place_with_id, bk);
|
||||
|
||||
match bk {
|
||||
@ -489,7 +488,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn mutate(&mut self, assignee_place: &mc::PlaceWithHirId<'tcx>) {
|
||||
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>) {
|
||||
debug!("mutate(assignee_place={:?})", assignee_place);
|
||||
|
||||
self.adjust_upvar_borrow_kind_for_mut(assignee_place);
|
||||
|
@ -5,7 +5,7 @@
|
||||
pub use self::ConsumeMode::*;
|
||||
|
||||
// Export these here so that Clippy can use them.
|
||||
pub use mc::{PlaceBase, PlaceWithHirId, Projection};
|
||||
pub use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId, Projection};
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
@ -13,6 +13,7 @@ use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::PatKind;
|
||||
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_target::abi::VariantIdx;
|
||||
|
||||
@ -27,13 +28,13 @@ use rustc_span::Span;
|
||||
pub trait Delegate<'tcx> {
|
||||
// The value found at `place` is either copied or moved, depending
|
||||
// on mode.
|
||||
fn consume(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, mode: ConsumeMode);
|
||||
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, mode: ConsumeMode);
|
||||
|
||||
// The value found at `place` is being borrowed with kind `bk`.
|
||||
fn borrow(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, bk: ty::BorrowKind);
|
||||
fn borrow(&mut self, place_with_id: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind);
|
||||
|
||||
// The path at `place_with_id` is being assigned to.
|
||||
fn mutate(&mut self, assignee_place: &mc::PlaceWithHirId<'tcx>);
|
||||
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>);
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
@ -398,7 +399,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
&*with_expr,
|
||||
with_place.clone(),
|
||||
with_field.ty(self.tcx(), substs),
|
||||
mc::ProjectionKind::Field(f_index as u32, VariantIdx::new(0)),
|
||||
ProjectionKind::Field(f_index as u32, VariantIdx::new(0)),
|
||||
);
|
||||
self.delegate_consume(&field_place);
|
||||
}
|
||||
@ -462,7 +463,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
fn walk_autoref(
|
||||
&mut self,
|
||||
expr: &hir::Expr<'_>,
|
||||
base_place: &mc::PlaceWithHirId<'tcx>,
|
||||
base_place: &PlaceWithHirId<'tcx>,
|
||||
autoref: &adjustment::AutoBorrow<'tcx>,
|
||||
) {
|
||||
debug!(
|
||||
@ -575,7 +576,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
closure_hir_id: hir::HirId,
|
||||
closure_span: Span,
|
||||
var_id: hir::HirId,
|
||||
) -> mc::McResult<mc::PlaceWithHirId<'tcx>> {
|
||||
) -> 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)?;
|
||||
|
@ -48,6 +48,7 @@
|
||||
//! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
|
||||
//! tied to `x`. The type of `x'` will be a borrowed pointer.
|
||||
|
||||
use rustc_middle::hir::place::*;
|
||||
use rustc_middle::ty::adjustment;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
@ -64,116 +65,6 @@ use rustc_span::Span;
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PlaceBase {
|
||||
/// A temporary variable
|
||||
Rvalue,
|
||||
/// A named `static` item
|
||||
StaticItem,
|
||||
/// A named local variable
|
||||
Local(hir::HirId),
|
||||
/// An upvar referenced by closure env
|
||||
Upvar(ty::UpvarId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ProjectionKind {
|
||||
/// A dereference of a pointer, reference or `Box<T>` of the given type
|
||||
Deref,
|
||||
|
||||
/// `B.F` where `B` is the base expression and `F` is
|
||||
/// the field. The field is identified by which variant
|
||||
/// it appears in along with a field index. The variant
|
||||
/// is used for enums.
|
||||
Field(u32, VariantIdx),
|
||||
|
||||
/// Some index like `B[x]`, where `B` is the base
|
||||
/// expression. We don't preserve the index `x` because
|
||||
/// we won't need it.
|
||||
Index,
|
||||
|
||||
/// A subslice covering a range of values like `B[x..y]`.
|
||||
Subslice,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Projection<'tcx> {
|
||||
// Type after the projection is being applied.
|
||||
ty: Ty<'tcx>,
|
||||
|
||||
/// Defines the type of access
|
||||
kind: ProjectionKind,
|
||||
}
|
||||
|
||||
/// A `Place` represents how a value is located in memory.
|
||||
///
|
||||
/// This is an HIR version of `mir::Place`
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Place<'tcx> {
|
||||
/// The type of the `PlaceBase`
|
||||
pub base_ty: Ty<'tcx>,
|
||||
/// The "outermost" place that holds this value.
|
||||
pub base: PlaceBase,
|
||||
/// How this place is derived from the base place.
|
||||
pub projections: Vec<Projection<'tcx>>,
|
||||
}
|
||||
|
||||
/// A `PlaceWithHirId` represents how a value is located in memory.
|
||||
///
|
||||
/// This is an HIR version of `mir::Place`
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PlaceWithHirId<'tcx> {
|
||||
/// `HirId` of the expression or pattern producing this value.
|
||||
pub hir_id: hir::HirId,
|
||||
|
||||
/// Information about the `Place`
|
||||
pub place: Place<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> PlaceWithHirId<'tcx> {
|
||||
crate fn new(
|
||||
hir_id: hir::HirId,
|
||||
base_ty: Ty<'tcx>,
|
||||
base: PlaceBase,
|
||||
projections: Vec<Projection<'tcx>>,
|
||||
) -> PlaceWithHirId<'tcx> {
|
||||
PlaceWithHirId {
|
||||
hir_id: hir_id,
|
||||
place: Place { base_ty: base_ty, base: base, projections: projections },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Place<'tcx> {
|
||||
/// Returns an iterator of the types that have to be dereferenced to access
|
||||
/// the `Place`.
|
||||
///
|
||||
/// The types are in the reverse order that they are applied. So if
|
||||
/// `x: &*const u32` and the `Place` is `**x`, then the types returned are
|
||||
///`*const u32` then `&*const u32`.
|
||||
crate fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
|
||||
self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
|
||||
if ProjectionKind::Deref == proj.kind {
|
||||
Some(self.ty_before_projection(index))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Returns the type of this `Place` after all projections have been applied.
|
||||
pub fn ty(&self) -> Ty<'tcx> {
|
||||
self.projections.last().map_or_else(|| self.base_ty, |proj| proj.ty)
|
||||
}
|
||||
|
||||
// Returns the type of this `Place` immediately before `projection_index`th projection
|
||||
// is applied.
|
||||
crate fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> {
|
||||
assert!(projection_index < self.projections.len());
|
||||
if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty }
|
||||
}
|
||||
}
|
||||
|
||||
crate trait HirNode {
|
||||
fn hir_id(&self) -> hir::HirId;
|
||||
fn span(&self) -> Span;
|
||||
|
Loading…
x
Reference in New Issue
Block a user