use super::lifetimes::{Lifetimes, LinkedLifetimes};
use super::{
Borrow, EnumDef, EnumId, Everywhere, Mutability, OpaqueDef, OpaqueId, OpaqueOwner,
OutStructDef, OutputOnly, ReturnableStructDef, StructDef, TraitId, TyPosition, TypeContext,
TypeId,
};
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum ReturnableStructPath {
Struct(StructPath),
OutStruct(OutStructPath),
}
pub type OutStructPath = StructPath<OutputOnly>;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct StructPath<P: TyPosition = Everywhere> {
pub lifetimes: Lifetimes,
pub tcx_id: P::StructId,
pub owner: MaybeOwn,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct TraitPath {
pub lifetimes: Lifetimes,
pub tcx_id: TraitId,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum NoTraitPath {}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct OpaquePath<Opt, Owner> {
pub lifetimes: Lifetimes,
pub optional: Opt,
pub owner: Owner,
pub tcx_id: OpaqueId,
}
#[derive(Debug, Copy, Clone)]
pub struct Optional(pub(super) bool);
#[derive(Debug, Copy, Clone)]
#[allow(clippy::exhaustive_structs)] pub struct NonOptional;
impl<Owner: OpaqueOwner> OpaquePath<Optional, Owner> {
pub fn is_optional(&self) -> bool {
self.optional.0
}
pub fn is_owned(&self) -> bool {
self.owner.is_owned()
}
}
impl<Owner: OpaqueOwner> OpaquePath<NonOptional, Owner> {
pub fn wrap_optional(self) -> OpaquePath<Optional, Owner> {
OpaquePath {
lifetimes: self.lifetimes,
optional: Optional(false),
owner: self.owner,
tcx_id: self.tcx_id,
}
}
}
impl<Opt> OpaquePath<Opt, MaybeOwn> {
pub fn as_borrowed(&self) -> Option<&Borrow> {
self.owner.as_borrowed()
}
}
impl<Opt> OpaquePath<Opt, Borrow> {
pub fn borrowed(&self) -> &Borrow {
&self.owner
}
}
impl<Opt, Owner> OpaquePath<Opt, Owner> {
pub fn id(&self) -> TypeId {
self.tcx_id.into()
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct EnumPath {
pub tcx_id: EnumId,
}
#[derive(Copy, Clone, Debug)]
#[allow(clippy::exhaustive_enums)] pub enum MaybeOwn {
Own,
Borrow(Borrow),
}
impl MaybeOwn {
pub fn as_borrowed(&self) -> Option<&Borrow> {
match self {
MaybeOwn::Own => None,
MaybeOwn::Borrow(borrow) => Some(borrow),
}
}
pub fn is_owned(&self) -> bool {
matches!(*self, Self::Own)
}
pub fn mutability(&self) -> Mutability {
match *self {
Self::Own => Mutability::Mutable,
Self::Borrow(b) => b.mutability,
}
}
}
impl From<Option<Borrow>> for MaybeOwn {
fn from(other: Option<Borrow>) -> Self {
other.map(Self::Borrow).unwrap_or(Self::Own)
}
}
impl ReturnableStructPath {
pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> ReturnableStructDef<'tcx> {
match self {
ReturnableStructPath::Struct(path) => ReturnableStructDef::Struct(path.resolve(tcx)),
ReturnableStructPath::OutStruct(path) => {
ReturnableStructDef::OutStruct(path.resolve(tcx))
}
}
}
pub(crate) fn lifetimes(&self) -> &Lifetimes {
match self {
Self::Struct(p) => &p.lifetimes,
Self::OutStruct(p) => &p.lifetimes,
}
}
}
impl<P: TyPosition> StructPath<P> {
pub(super) fn new(lifetimes: Lifetimes, tcx_id: P::StructId, owner: MaybeOwn) -> Self {
Self {
lifetimes,
tcx_id,
owner,
}
}
}
impl StructPath {
pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> &'tcx StructDef {
tcx.resolve_struct(self.tcx_id)
}
}
impl OutStructPath {
pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> &'tcx OutStructDef {
tcx.resolve_out_struct(self.tcx_id)
}
pub fn link_lifetimes<'def, 'tcx>(
&'def self,
tcx: &'tcx TypeContext,
) -> LinkedLifetimes<'def, 'tcx> {
let struc = self.resolve(tcx);
let env = &struc.lifetimes;
LinkedLifetimes::new(env, None, &self.lifetimes)
}
}
impl<Opt, Owner> OpaquePath<Opt, Owner> {
pub(super) fn new(lifetimes: Lifetimes, optional: Opt, owner: Owner, tcx_id: OpaqueId) -> Self {
Self {
lifetimes,
optional,
owner,
tcx_id,
}
}
pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> &'tcx OpaqueDef {
tcx.resolve_opaque(self.tcx_id)
}
}
impl<Opt, Owner: OpaqueOwner> OpaquePath<Opt, Owner> {
pub fn link_lifetimes<'def, 'tcx>(
&'def self,
tcx: &'tcx TypeContext,
) -> LinkedLifetimes<'def, 'tcx> {
let opaque = self.resolve(tcx);
let env = &opaque.lifetimes;
LinkedLifetimes::new(env, self.owner.lifetime(), &self.lifetimes)
}
}
impl EnumPath {
pub(super) fn new(tcx_id: EnumId) -> Self {
Self { tcx_id }
}
pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> &'tcx EnumDef {
tcx.resolve_enum(self.tcx_id)
}
pub fn id(&self) -> TypeId {
self.tcx_id.into()
}
}
impl TraitPath {
pub(super) fn new(lifetimes: Lifetimes, tcx_id: TraitId) -> Self {
Self { lifetimes, tcx_id }
}
}