use super::lifetimes::{Lifetime, Lifetimes, MaybeStatic};
use super::{
Borrow, Callback, CallbackInstantiationFunctionality, LinkedLifetimes, MaybeOwn, Mutability,
NoCallback, NoTraitPath, OutStructId, ReturnableStructPath, StructDef, StructId, StructPath,
TraitId, TraitPath, TypeContext, TypeDef, TypeId,
};
use core::fmt::Debug;
pub trait Sealed {}
pub trait TyPosition: Debug + Copy + Sealed
where
for<'tcx> TypeDef<'tcx>: From<&'tcx StructDef<Self>>,
{
const IN_OUT_STATUS: InputOrOutput;
type CallbackInstantiation: Debug + CallbackInstantiationFunctionality + Clone;
type OpaqueOwnership: Debug + OpaqueOwner + Clone;
type StructId: Debug + Copy + Into<TypeId>;
type StructPath: Debug + StructPathLike + Clone;
type TraitPath: Debug + TraitIdGetter + Clone;
fn wrap_struct_def<'tcx>(def: &'tcx StructDef<Self>) -> TypeDef<'tcx>;
fn build_callback(cb: Callback) -> Self::CallbackInstantiation;
fn build_trait_path(trait_path: TraitPath) -> Self::TraitPath;
fn resolve_struct(tcx: &TypeContext, id: Self::StructId) -> &StructDef<Self>;
fn get_fields<'tcx>(
def: &'tcx StructDef<Self>,
) -> impl Iterator<Item = &'tcx crate::hir::StructField<Self>> {
def.fields.iter()
}
}
#[non_exhaustive]
pub enum InputOrOutput {
Input,
Output,
InputOutput,
}
pub trait TraitIdGetter: Sealed {
fn id(&self) -> TraitId;
}
#[derive(Debug, Copy, Clone)]
#[non_exhaustive]
pub struct Everywhere;
#[derive(Debug, Copy, Clone)]
#[non_exhaustive]
pub struct OutputOnly;
#[derive(Debug, Copy, Clone)]
#[non_exhaustive]
pub struct InputOnly;
impl Sealed for Everywhere {}
impl Sealed for OutputOnly {}
impl Sealed for InputOnly {}
impl TyPosition for Everywhere {
const IN_OUT_STATUS: InputOrOutput = InputOrOutput::InputOutput;
type OpaqueOwnership = Borrow;
type StructId = StructId;
type StructPath = StructPath;
type CallbackInstantiation = NoCallback;
type TraitPath = NoTraitPath;
fn wrap_struct_def<'tcx>(def: &'tcx StructDef<Self>) -> TypeDef<'tcx> {
TypeDef::Struct(def)
}
fn build_callback(_cb: Callback) -> Self::CallbackInstantiation {
panic!("Callbacks must be input-only");
}
fn build_trait_path(_trait_path: TraitPath) -> Self::TraitPath {
panic!("Traits must be input-only");
}
fn resolve_struct(tcx: &TypeContext, id: StructId) -> &StructDef<Self> {
tcx.resolve_struct(id)
}
}
impl TyPosition for OutputOnly {
const IN_OUT_STATUS: InputOrOutput = InputOrOutput::Output;
type OpaqueOwnership = MaybeOwn;
type StructId = OutStructId;
type StructPath = ReturnableStructPath;
type CallbackInstantiation = NoCallback;
type TraitPath = NoTraitPath;
fn wrap_struct_def<'tcx>(def: &'tcx StructDef<Self>) -> TypeDef<'tcx> {
TypeDef::OutStruct(def)
}
fn build_callback(_cb: Callback) -> Self::CallbackInstantiation {
panic!("Callbacks must be input-only");
}
fn build_trait_path(_trait_path: TraitPath) -> Self::TraitPath {
panic!("Traits must be input-only");
}
fn resolve_struct(tcx: &TypeContext, id: OutStructId) -> &StructDef<Self> {
tcx.resolve_out_struct(id)
}
}
impl TyPosition for InputOnly {
const IN_OUT_STATUS: InputOrOutput = InputOrOutput::Input;
type OpaqueOwnership = Borrow;
type StructId = StructId;
type StructPath = StructPath;
type CallbackInstantiation = Callback;
type TraitPath = TraitPath;
fn wrap_struct_def<'tcx>(_def: &'tcx StructDef<Self>) -> TypeDef<'tcx> {
panic!("Input-only structs are not currently supported");
}
fn build_callback(cb: Callback) -> Self::CallbackInstantiation {
cb
}
fn build_trait_path(trait_path: TraitPath) -> Self::TraitPath {
trait_path
}
fn resolve_struct(_: &TypeContext, _: StructId) -> &StructDef<Self> {
panic!("Type Context does not store InputOnly structdefs");
}
}
pub trait StructPathLike: Sealed {
fn lifetimes(&self) -> &Lifetimes;
fn id(&self) -> TypeId;
fn owner(&self) -> MaybeOwn;
fn link_lifetimes<'def, 'tcx>(
&'def self,
tcx: &'tcx TypeContext,
) -> LinkedLifetimes<'def, 'tcx>;
}
impl Sealed for StructPath {}
impl Sealed for ReturnableStructPath {}
impl StructPathLike for StructPath {
fn lifetimes(&self) -> &Lifetimes {
&self.lifetimes
}
fn id(&self) -> TypeId {
self.tcx_id.into()
}
fn owner(&self) -> MaybeOwn {
self.owner
}
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 StructPathLike for ReturnableStructPath {
fn lifetimes(&self) -> &Lifetimes {
self.lifetimes()
}
fn id(&self) -> TypeId {
match self {
ReturnableStructPath::Struct(p) => p.tcx_id.into(),
ReturnableStructPath::OutStruct(p) => p.tcx_id.into(),
}
}
fn owner(&self) -> MaybeOwn {
MaybeOwn::Own
}
fn link_lifetimes<'def, 'tcx>(
&'def self,
tcx: &'tcx TypeContext,
) -> LinkedLifetimes<'def, 'tcx> {
match self {
Self::Struct(p) => p.link_lifetimes(tcx),
Self::OutStruct(p) => p.link_lifetimes(tcx),
}
}
}
impl Sealed for TraitPath {}
impl Sealed for NoTraitPath {}
impl TraitIdGetter for TraitPath {
fn id(&self) -> TraitId {
self.tcx_id
}
}
impl TraitIdGetter for NoTraitPath {
fn id(&self) -> TraitId {
panic!("Trait path not allowed here, no trait ID valid");
}
}
pub trait OpaqueOwner: Sealed {
fn mutability(&self) -> Option<Mutability>;
fn is_owned(&self) -> bool;
fn lifetime(&self) -> Option<MaybeStatic<Lifetime>>;
}
impl Sealed for MaybeOwn {}
impl Sealed for Borrow {}
impl OpaqueOwner for MaybeOwn {
fn mutability(&self) -> Option<Mutability> {
match self {
MaybeOwn::Own => None,
MaybeOwn::Borrow(b) => b.mutability(),
}
}
fn is_owned(&self) -> bool {
match self {
MaybeOwn::Own => true,
MaybeOwn::Borrow(_) => false,
}
}
fn lifetime(&self) -> Option<MaybeStatic<Lifetime>> {
match self {
MaybeOwn::Own => None,
MaybeOwn::Borrow(b) => b.lifetime(),
}
}
}
impl OpaqueOwner for Borrow {
fn mutability(&self) -> Option<Mutability> {
Some(self.mutability)
}
fn is_owned(&self) -> bool {
false
}
fn lifetime(&self) -> Option<MaybeStatic<Lifetime>> {
Some(self.lifetime)
}
}