//! 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 crate::{
any::{TypeName, TypeNameable},
nameable,
protocol::{ControlFlowFor, Effect, SyncEffect, Visitor},
};
/// Meta information for the hint.
///
/// This gives the visitor more information to work from when selecting a hint.
pub trait HintMeta<'a, 'ctx: 'a> {
/// Information known by the walker.
///
/// This should be information easy to get without changing the state of the walker
/// in an irreversible way.
type Known;
/// Extra information the visitor can give to the walker about what it is expecting.
type Hint;
}
/// Object implementing the [`Hint`] protocol.
pub trait Hint<'ctx, Protocol: ?Sized + for<'a> HintMeta<'a, 'ctx>, E = SyncEffect>
where
E: Effect<'ctx> + Effect<'ctx, <Protocol as HintMeta<'a, 'ctx>>::Known>
{
/// Hint to the walker to use the `P` protocol.
///
/// This should only be called once per [`RequestHint`].
fn hint<'a>(
&'a mut self,
visitor: &'a mut Visitor<'a, 'ctx, E>,
hint: <Protocol as HintMeta<'a, 'ctx>>::Hint,
) -> ControlFlowFor<'a, 'ctx, E>;
/// Ask the walker for information about it's support of the protocol.
fn known<'a>(
&'a mut self,
hint: &'a <Protocol as HintMeta<'a, 'ctx>>::Hint,
) -> ControlFlowFor<'a, 'ctx, E, <Protocol as HintMeta<'a, 'ctx>>::Known>
where
'ctx: 'a;
}
nameable! {
pub struct Name['a, 'ctx, Protocol, E];
impl [Protocol::Name, E] for dyn Hint<'ctx, Protocol, E> + 'a where {
Protocol: TypeNameable<'a, 'ctx> + ?Sized,
E: Effect<'ctx>,
'ctx: 'a,
}
impl [Protocol, E] where dyn Hint<'ctx, Protocol::Nameable, E> + 'a {
Protocol: TypeName<'a, 'ctx> + ?Sized,
E: Effect<'ctx>,
'ctx: 'a,
}
}
#[cfg(test)]
mod test {
use core::ops::ControlFlow;
use crate::any::{LtTypeId, TypeNameable};
use super::*;
#[test]
fn demo() {
struct X;
struct Y;
nameable! {
struct Name['a, 'ctx];
impl for Y where {}
}
impl<'ctx, X> Hint<'ctx, Y> for X {
fn hint<'a>(
&'a mut self,
visitor: &'a mut Visitor<'a, 'ctx>,
hint: <Y as HintMeta<'ctx>>::Hint<'a>,
) -> ControlFlow<()> {
todo!()
}
fn known<'a>(
&'a mut self,
hint: &'a <Y as HintMeta<'ctx>>::Hint<'a>,
) -> ControlFlow<(), <Y as HintMeta<'ctx>>::Known<'a>>
where
'ctx: 'a,
{
todo!()
}
}
impl<'ctx> HintMeta<'ctx> for Y {
type Known<'a> = () where 'ctx: 'a;
type Hint<'a> = () where 'ctx: '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!();
}
}