use std::fmt::Debug;
use std::marker::PhantomData;
use crate::{
ast::{
expr::ConstExpr,
generic::{GenericParams, Lifetime},
ty::TyKind,
},
common::{GenericId, SpanId, SymbolId},
context::with_cx,
ffi::{FfiOption, FfiSlice},
private::Sealed,
span::Span,
};
use super::TyParamBound;
#[repr(C)]
#[derive(Debug)]
#[non_exhaustive]
pub enum GenericParamKind<'ast> {
Lifetime(&'ast LifetimeParam<'ast>),
Ty(&'ast TyParam<'ast>),
Const(&'ast ConstParam<'ast>),
}
impl<'ast> GenericParamKind<'ast> {
pub fn span(&self) -> Option<&Span<'ast>> {
match self {
GenericParamKind::Lifetime(lt) => lt.span(),
GenericParamKind::Ty(ty) => ty.span(),
GenericParamKind::Const(con) => con.span(),
}
}
pub fn id(&self) -> GenericId {
match self {
GenericParamKind::Ty(param) => param.id(),
GenericParamKind::Lifetime(param) => param.id(),
GenericParamKind::Const(param) => param.id(),
}
}
}
pub trait SynGenericParamData<'ast>: Debug + Sealed {
fn span(&self) -> Option<&Span<'ast>>;
}
#[repr(C)]
#[derive(Debug)]
pub struct TyParam<'ast> {
_data: PhantomData<&'ast ()>,
id: GenericId,
name: SymbolId,
span: FfiOption<SpanId>,
}
#[cfg(feature = "driver-api")]
impl<'ast> TyParam<'ast> {
pub fn new(span: Option<SpanId>, name: SymbolId, id: GenericId) -> Self {
Self {
_data: PhantomData,
id,
name,
span: span.into(),
}
}
}
impl<'ast> TyParam<'ast> {
pub fn id(&self) -> GenericId {
self.id
}
pub fn name(&self) -> &str {
with_cx(self, |cx| cx.symbol_str(self.name))
}
}
impl<'ast> SynGenericParamData<'ast> for TyParam<'ast> {
fn span(&self) -> Option<&Span<'ast>> {
self.span.get().map(|span| with_cx(self, |cx| cx.span(*span)))
}
}
impl<'ast> From<&'ast TyParam<'ast>> for GenericParamKind<'ast> {
fn from(src: &'ast TyParam<'ast>) -> Self {
Self::Ty(src)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct LifetimeParam<'ast> {
_data: PhantomData<&'ast ()>,
id: GenericId,
name: SymbolId,
span: FfiOption<SpanId>,
}
#[cfg(feature = "driver-api")]
impl<'ast> LifetimeParam<'ast> {
pub fn new(id: GenericId, name: SymbolId, span: Option<SpanId>) -> Self {
Self {
_data: PhantomData,
id,
name,
span: span.into(),
}
}
}
impl<'ast> LifetimeParam<'ast> {
pub fn id(&self) -> GenericId {
self.id
}
pub fn name(&self) -> &str {
with_cx(self, |cx| cx.symbol_str(self.name))
}
}
impl<'ast> SynGenericParamData<'ast> for LifetimeParam<'ast> {
fn span(&self) -> Option<&Span<'ast>> {
self.span.get().map(|span| with_cx(self, |cx| cx.span(*span)))
}
}
impl<'ast> From<&'ast LifetimeParam<'ast>> for GenericParamKind<'ast> {
fn from(src: &'ast LifetimeParam<'ast>) -> Self {
Self::Lifetime(src)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct ConstParam<'ast> {
id: GenericId,
name: SymbolId,
ty: TyKind<'ast>,
default: FfiOption<ConstExpr<'ast>>,
span: SpanId,
}
impl<'ast> ConstParam<'ast> {
pub fn id(&self) -> GenericId {
self.id
}
pub fn name(&self) -> &str {
with_cx(self, |cx| cx.symbol_str(self.name))
}
pub fn ty(&self) -> TyKind<'ast> {
self.ty
}
pub fn default(&self) -> Option<&ConstExpr<'ast>> {
self.default.get()
}
}
impl<'ast> SynGenericParamData<'ast> for ConstParam<'ast> {
fn span(&self) -> Option<&Span<'ast>> {
Some(with_cx(self, |cx| cx.span(self.span)))
}
}
#[cfg(feature = "driver-api")]
impl<'ast> ConstParam<'ast> {
pub fn new(
id: GenericId,
name: SymbolId,
ty: TyKind<'ast>,
default: Option<ConstExpr<'ast>>,
span: SpanId,
) -> Self {
Self {
id,
name,
ty,
default: default.into(),
span,
}
}
}
#[repr(C)]
#[derive(Debug)]
#[non_exhaustive]
pub enum WhereClauseKind<'ast> {
Lifetime(&'ast LifetimeClause<'ast>),
Ty(&'ast TyClause<'ast>),
}
#[repr(C)]
#[derive(Debug)]
pub struct LifetimeClause<'ast> {
lifetime: Lifetime<'ast>,
bounds: FfiSlice<'ast, Lifetime<'ast>>,
}
impl<'ast> LifetimeClause<'ast> {
pub fn lifetime(&self) -> &Lifetime<'ast> {
&self.lifetime
}
pub fn bounds(&self) -> &[Lifetime<'ast>] {
self.bounds.get()
}
}
#[cfg(feature = "driver-api")]
impl<'ast> LifetimeClause<'ast> {
pub fn new(lifetime: Lifetime<'ast>, bounds: &'ast [Lifetime<'ast>]) -> Self {
Self {
lifetime,
bounds: bounds.into(),
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct TyClause<'ast> {
params: FfiOption<GenericParams<'ast>>,
ty: TyKind<'ast>,
bounds: FfiSlice<'ast, TyParamBound<'ast>>,
}
impl<'ast> TyClause<'ast> {
pub fn params(&self) -> Option<&GenericParams<'ast>> {
self.params.get()
}
pub fn ty(&self) -> TyKind<'ast> {
self.ty
}
pub fn bounds(&self) -> &'ast [TyParamBound<'ast>] {
self.bounds.get()
}
}
#[cfg(feature = "driver-api")]
impl<'ast> TyClause<'ast> {
pub fn new(params: Option<GenericParams<'ast>>, ty: TyKind<'ast>, bounds: &'ast [TyParamBound<'ast>]) -> Self {
Self {
params: params.into(),
ty,
bounds: bounds.into(),
}
}
}