//! Protocol for giving a hint to a walker.
//!
//! Sometimes a walker has multiple protocols it could use,
//! this module gives a protocol by which a visitor can give a hint
//! to the walker about what it is expecting.
use core::marker::PhantomData;
use crate::{
any::{TypeName, TypeNameable},
nameable,
protocol::Implementer,
};
/// Meta information for the hint.
///
/// This gives the visitor more information to work from when selecting a hint.
pub trait Meta<'ctx> {
/// Information known by the walker.
///
/// This should be information easy to get without changing the state of the walker
/// in an irreversable way.
type Known<'a>;
/// Extra information the visitor can give to the walker about what it is expecting.
type Hint<'a>;
}
/// Object implementing the [`Hint`] protocol.
pub trait Hint<'ctx, P: Meta<'ctx>> {
/// Hint to the walker to use the `P` protocol.
///
/// This should only be called once per [`RequestHint`].
fn hint(&mut self, visitor: &mut dyn Implementer<'ctx>, hint: P::Hint<'_>) -> Result<(), ()>;
/// Ask the walker for information about it's support of the protocol.
fn known(&mut self, hint: &P::Hint<'_>) -> Result<P::Known<'_>, ()>;
}
// nameable!(['a, 'ctx, P: Meta<'ctx> + TypeNameable<'a, 'ctx>]: dyn Hint<'ctx, P> + 'a => dyn Hint<'static, P::Name>);
const _: () = {
impl<'a, 'ctx: 'a, P: TypeNameable<'a, 'ctx>>
crate::any::TypeNameable<'a, 'ctx> for dyn Hint<'ctx, P> + 'a
where
P: ?Sized
// where
// P: Meta<'ctx>
{
type Name = Name<P::Name>;
}
pub struct Name<T: ?Sized>(PhantomData<fn() -> *const T>);
impl<'a, 'ctx: 'a, T: TypeName<'a, 'ctx>> crate::any::TypeName<'a, 'ctx> for Name<T>
where
T: ?Sized
// where
// T::Nameable: Meta<'ctx>,
{
type Nameable = dyn Hint<'ctx, T::Nameable> + 'a;
}
};
#[cfg(test)]
mod test {
use crate::any::LtTypeId;
use super::*;
#[test]
fn demo() {
struct X;
struct Y;
nameable!(['a, 'ctx]: Y => Y);
impl<'ctx, X> Hint<'ctx, Y> for X {
fn hint(
&mut self,
visitor: &mut dyn Implementer<'ctx>,
hint: <Y as Meta>::Hint<'_>,
) -> Result<(), ()> {
todo!()
}
fn known(
&mut self,
hint: &<Y as Meta>::Hint<'_>,
) -> Result<<Y as Meta>::Known<'_>, ()> {
todo!()
}
}
impl<'ctx> Meta<'ctx> for Y {
type Known<'a> = ();
type Hint<'a> = ();
}
let x = X;
let y: &dyn Hint<Y> = &x;
fn id<'a, 'ctx, T: ?Sized + TypeNameable<'a, 'ctx>>(x: &T) {
dbg!(LtTypeId::of::<T>());
}
id(y);
todo!();
}
}