Skip to main content

pliron/
type.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) The pliron contributors
3
4//! Every SSA value, such as operation results or block arguments
5//! has a type defined by the type system.
6//!
7//! The type system is open, with no fixed list of types,
8//! and there are no restrictions on the abstractions they represent.
9//!
10//! See [MLIR Types](https://mlir.llvm.org/docs/DefiningDialects/TypesAndTypes/#types)
11//!
12//! The [pliron_type](pliron::derive::pliron_type) proc macro from [pliron-derive]
13//! can be used to implement [Type] for a rust type.
14//!
15//! Common semantics, API and behaviour of [Type]s are
16//! abstracted into interfaces. Interfaces in pliron capture MLIR
17//! functionality of both [Traits](https://mlir.llvm.org/docs/Traits/)
18//! and [Interfaces](https://mlir.llvm.org/docs/Interfaces/).
19//! Interfaces must all implement an associated function named `verify` with
20//! the type [TypeInterfaceVerifier].
21//!
22//! Interfaces are rust Trait definitions annotated with the attribute macro
23//! [type_interface](pliron::derive::type_interface). The attribute ensures that any
24//! verifiers of super-interfaces are run prior to the verifier of this interface.
25//! Note: Super-interface verifiers *may* run multiple times for the same type.
26//!
27//! [Type]s that implement an interface must annotate the implementation with
28//! [type_interface_impl](pliron::derive::type_interface_impl) macro to ensure that
29//! the interface verifier is automatically called during verification
30//! and that a `&dyn Type` object can be [cast](type_cast) into an interface object,
31//! (or that it can be checked if the interface is [implemented](type_impls))
32//! with ease.
33//!
34//! Use [verify_type] to verify a [Type] object.
35//! This function verifies all interfaces implemented by the type, and then the type itself.
36//! The type's verifier must explicitly invoke verifiers on any sub-objects it contains.
37//!
38//! [TypeHandle]s can be [TypeHandle::deref]'d and downcasted to their concrete types using
39//! [downcast_rs](https://docs.rs/downcast-rs/latest/downcast_rs/#example-without-generics).
40
41use crate::{
42    arg_err_noloc,
43    combine::{Parser, parser},
44    common_traits::Verify,
45    context::{Context, collect_deduped_interface_verifiers},
46    dialect::{Dialect, DialectName},
47    identifier::Identifier,
48    impl_printable_for_display, input_err,
49    irfmt::parsers::spaced,
50    parsable::{IntoParseResult, Parsable, ParseResult, StateStream, StreamLocation},
51    printable::{self, Printable},
52    result::{Error, Result},
53    std_deps::sync::LazyLock,
54    storage_uniquer::TypeValueHash,
55    utils::{table::HMap, trait_cast::impls_trait_static},
56};
57
58use alloc::{
59    boxed::Box,
60    string::{String, ToString},
61    vec::Vec,
62};
63use core::{
64    cell::{Ref, RefCell, RefMut},
65    fmt::{Debug, Display},
66    hash::{Hash, Hasher},
67    marker::PhantomData,
68};
69use downcast_rs::{Downcast, impl_downcast};
70use pliron_derive::format;
71use thiserror::Error;
72
73/// Basic functionality that every type in the IR must implement.
74/// Type objects (instances of a Type) are (mostly) immutable once created,
75/// and are uniqued globally. Uniquing is based on the type name (i.e.,
76/// the rust type being defined) and its contents.
77///
78/// So, for example, if we have
79/// ```rust
80///     # use pliron::derive::pliron_type;
81///     #[pliron_type(
82///         name = "test.intty",
83///         format,
84///         verifier = "succ"
85///     )]
86///     #[derive(Debug, PartialEq, Eq, Hash)]
87///     struct IntType {
88///         width: u64
89///     }
90/// ```
91/// the uniquing will include
92///   - [`core::any::TypeId::of::<IntType>()`](core::any::TypeId)
93///   - `width`
94///
95/// Types *can* have mutable contents that can be modified *after*
96/// the type is created. This enables creation of recursive types.
97/// In such a case, it is up to the type definition to ensure that
98///   1. It manually implements Hash, ignoring these mutable fields.
99///   2. A proper distinguisher content (such as a string), that is part
100///      of the hash, is used so that uniquing still works.
101pub trait Type: Printable + Verify + Downcast + Sync + Send + Debug {
102    /// Compute and get the hash for this instance of Self.
103    /// Hash collisions can be a possibility.
104    fn hash_type(&self) -> TypeValueHash;
105    /// Is self equal to an other Type?
106    fn eq_type(&self, other: &dyn Type) -> bool;
107
108    /// Get a copyable handle to this type.
109    // Unlike in [ArenaObj]s, we do not store a self handle inside the object itself
110    // because that can upset taking automatic hashes of the object.
111    fn get_self_handle(&self, ctx: &Context) -> TypeHandle {
112        let is = |other: &TypeObj| self.eq_type(&**other.0.borrow());
113        let idx = ctx
114            .type_store
115            .get(self.hash_type(), &is)
116            .expect("Unregistered type object in existence");
117        TypeHandle(idx)
118    }
119
120    /// Instantiate a type in the provided [Context], returning a [TypeHandle] to self.
121    fn instantiate(t: Self, ctx: &Context) -> TypedHandle<Self>
122    where
123        Self: Sized,
124    {
125        let hash = t.hash_type();
126        let idx = ctx.type_store.get_or_create_unique(
127            TypeObj(RefCell::new(Box::new(t))),
128            hash,
129            &TypeObj::eq,
130        );
131        TypedHandle(TypeHandle(idx), PhantomData::<Self>)
132    }
133
134    /// Get a Type's static name. This is *not* per instantiation of the type.
135    /// It is mostly useful for printing and parsing the type.
136    /// Uniquing does *not* use this, but instead uses [core::any::TypeId].
137    fn get_type_id(&self) -> TypeId;
138
139    /// Same as [get_type_id](Self::get_type_id), but without the self reference.
140    fn get_type_id_static() -> TypeId
141    where
142        Self: Sized;
143
144    #[doc(hidden)]
145    /// Verify all interfaces implemented by this Type.
146    fn verify_interfaces(&self, ctx: &Context) -> Result<()>;
147
148    /// Register this Type's [TypeId] in the dialect it belongs to.
149    fn register(ctx: &mut Context)
150    where
151        Self: Sized + Parsable<Arg = (), Parsed = TypedHandle<Self>>,
152    {
153        let ptr_parser: TypeParserFn = |parsable_state, &()| {
154            Self::parse(parsable_state, ())
155                .map(|(typtr, r)| -> (TypeHandle, _) { (typtr.to_handle(), r) })
156        };
157        let typeid = Self::get_type_id_static();
158        Dialect::register(ctx, &typeid.dialect.clone()).add_type(typeid, ptr_parser);
159    }
160}
161impl_downcast!(Type);
162
163/// A storable function pointer to parse a specific [Type].
164/// The [Type]'s [Dialect] maps a [TypeId] to such a parser.
165pub(crate) type TypeParserFn =
166    for<'a> fn(&mut StateStream<'a>, &'a ()) -> ParseResult<'a, TypeHandle>;
167
168/// Trait for IR entities that have a direct type.
169pub trait Typed {
170    /// Get the [Type] of the current entity.
171    fn get_type(&self, ctx: &Context) -> TypeHandle;
172}
173
174impl Typed for TypeHandle {
175    fn get_type(&self, _ctx: &Context) -> TypeHandle {
176        *self
177    }
178}
179
180impl Typed for dyn Type {
181    fn get_type(&self, ctx: &Context) -> TypeHandle {
182        self.get_self_handle(ctx)
183    }
184}
185
186impl<T: Typed + ?Sized> Typed for &T {
187    fn get_type(&self, ctx: &Context) -> TypeHandle {
188        (*self).get_type(ctx)
189    }
190}
191
192impl<T: Typed + ?Sized> Typed for &mut T {
193    fn get_type(&self, ctx: &Context) -> TypeHandle {
194        (**self).get_type(ctx)
195    }
196}
197
198impl<T: Typed + ?Sized> Typed for Box<T> {
199    fn get_type(&self, ctx: &Context) -> TypeHandle {
200        (**self).get_type(ctx)
201    }
202}
203
204#[derive(Clone, Hash, PartialEq, Eq)]
205/// A Type's name (not including it's dialect).
206pub struct TypeName(Identifier);
207
208impl TypeName {
209    /// Create a new TypeName.
210    pub fn try_new(name: &str) -> Result<TypeName> {
211        Identifier::try_from(name).map(TypeName)
212    }
213}
214
215impl From<Identifier> for TypeName {
216    fn from(name: Identifier) -> Self {
217        TypeName(name)
218    }
219}
220
221impl From<TypeName> for Identifier {
222    fn from(name: TypeName) -> Self {
223        name.0
224    }
225}
226
227impl TryFrom<&str> for TypeName {
228    type Error = Error;
229
230    fn try_from(value: &str) -> Result<Self> {
231        Identifier::try_from(value).map(TypeName)
232    }
233}
234
235impl TryFrom<String> for TypeName {
236    type Error = Error;
237
238    fn try_from(value: String) -> Result<Self> {
239        Identifier::try_from(value).map(TypeName)
240    }
241}
242
243impl AsRef<str> for TypeName {
244    fn as_ref(&self) -> &str {
245        self.0.as_ref()
246    }
247}
248
249impl AsRef<Identifier> for TypeName {
250    fn as_ref(&self) -> &Identifier {
251        &self.0
252    }
253}
254
255impl_printable_for_display!(TypeName);
256
257impl Display for TypeName {
258    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
259        write!(f, "{}", self.0)
260    }
261}
262
263impl Parsable for TypeName {
264    type Arg = ();
265    type Parsed = TypeName;
266
267    fn parse<'a>(
268        state_stream: &mut crate::parsable::StateStream<'a>,
269        _arg: Self::Arg,
270    ) -> ParseResult<'a, Self::Parsed>
271    where
272        Self: Sized,
273    {
274        Identifier::parser(())
275            .map(TypeName)
276            .parse_stream(state_stream)
277            .into()
278    }
279}
280
281/// A combination of a Type's name and its dialect.
282#[derive(Clone, Hash, PartialEq, Eq)]
283pub struct TypeId {
284    pub dialect: DialectName,
285    pub name: TypeName,
286}
287
288impl Parsable for TypeId {
289    type Arg = ();
290    type Parsed = TypeId;
291
292    // Parses (but does not validate) a TypeId.
293    fn parse<'a>(
294        state_stream: &mut StateStream<'a>,
295        _arg: Self::Arg,
296    ) -> ParseResult<'a, Self::Parsed>
297    where
298        Self: Sized,
299    {
300        let mut parser = DialectName::parser(())
301            .skip(parser::char::char('.'))
302            .and(TypeName::parser(()))
303            .map(|(dialect, name)| TypeId { dialect, name });
304        parser.parse_stream(state_stream).into()
305    }
306}
307
308impl_printable_for_display!(TypeId);
309
310impl Display for TypeId {
311    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
312        write!(f, "{}.{}", self.dialect, self.name)
313    }
314}
315
316/// An instance of a [Type] stored in the [Context]'s type store.
317pub(crate) struct TypeObj(RefCell<Box<dyn Type>>);
318
319impl PartialEq for TypeObj {
320    fn eq(&self, other: &Self) -> bool {
321        self.0.borrow().eq_type(&**other.0.borrow())
322    }
323}
324
325impl Eq for TypeObj {}
326
327impl Hash for TypeObj {
328    fn hash<H: Hasher>(&self, state: &mut H) {
329        state.write(&u64::from(self.0.borrow().hash_type()).to_ne_bytes())
330    }
331}
332
333/// A handle to the uniqued [Type] objects stored in the [Context].
334#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
335pub struct TypeHandle(usize);
336
337impl TypeHandle {
338    /// Get a reference to the underlying [Type] object.
339    pub fn deref<'a>(&self, ctx: &'a Context) -> Ref<'a, dyn Type> {
340        Ref::map(
341            ctx.type_store.unique_store.get(self.0).unwrap().0.borrow(),
342            |t| &**t,
343        )
344    }
345
346    /// Get a mutable reference to the underlying [Type] object.
347    /// This is useful when building recursive types, and the caller must ensure
348    /// that the mutation does not change the hash-relevant contents of the type.
349    pub fn deref_mut<'a>(&self, ctx: &'a Context) -> RefMut<'a, dyn Type> {
350        RefMut::map(
351            ctx.type_store
352                .unique_store
353                .get(self.0)
354                .unwrap()
355                .0
356                .borrow_mut(),
357            |t| &mut **t,
358        )
359    }
360}
361
362impl Printable for TypeHandle {
363    fn fmt(
364        &self,
365        ctx: &Context,
366        state: &printable::State,
367        f: &mut core::fmt::Formatter<'_>,
368    ) -> core::fmt::Result {
369        write!(f, "{} ", self.deref(ctx).get_type_id())?;
370        Printable::fmt(&*self.deref(ctx), ctx, state, f)
371    }
372}
373
374impl Verify for TypeHandle {
375    fn verify(&self, ctx: &Context) -> Result<()> {
376        verify_type(&*self.deref(ctx), ctx)
377    }
378}
379
380impl Parsable for TypeHandle {
381    type Arg = ();
382    type Parsed = Self;
383
384    fn parse<'a>(
385        state_stream: &mut StateStream<'a>,
386        _arg: Self::Arg,
387    ) -> ParseResult<'a, Self::Parsed> {
388        let loc = state_stream.loc();
389        let type_id_parser = spaced(TypeId::parser(()));
390
391        let mut type_parser = type_id_parser.then(move |type_id: TypeId| {
392            // This clone is to satify the borrow checker.
393            let loc = loc.clone();
394            combine::parser(move |parsable_state: &mut StateStream<'a>| {
395                let state = &parsable_state.state;
396                let dialect = state
397                    .ctx
398                    .dialects
399                    .get(&type_id.dialect)
400                    .expect("Dialect name parsed but dialect isn't registered");
401                let Some(type_parser) = dialect.types.get(&type_id) else {
402                    input_err!(loc.clone(), "Unregistered type {}", type_id.disp(state.ctx))?
403                };
404                type_parser(parsable_state, &())
405            })
406        });
407
408        type_parser.parse_stream(state_stream).into_result()
409    }
410}
411
412/// Verify a [Type] object:
413/// 1. All interfaces it implements are verified
414/// 2. The type itself is verified.
415pub fn verify_type(ty: &dyn Type, ctx: &Context) -> Result<()> {
416    // Verify all interfaces implemented by this Type.
417    ty.verify_interfaces(ctx)?;
418
419    // Verify the type itself.
420    Verify::verify(ty, ctx)
421}
422
423impl Verify for TypeObj {
424    fn verify(&self, ctx: &Context) -> Result<()> {
425        verify_type(self.0.borrow().as_ref(), ctx)
426    }
427}
428
429/// A wrapper around [TypeHandle] with the underlying [Type] statically marked.
430#[derive(Debug)]
431pub struct TypedHandle<T: Type>(TypeHandle, PhantomData<T>);
432
433#[derive(Error, Debug)]
434#[error("TypedHandle mismatch: expected {expected} but provided {provided}")]
435pub struct TypedHandleErr {
436    pub expected: String,
437    pub provided: String,
438}
439
440impl<T: Type> TypedHandle<T> {
441    /// Return a [Ref] to the [Type]
442    pub fn deref<'a>(&self, ctx: &'a Context) -> Ref<'a, T> {
443        Ref::map(self.0.deref(ctx), |t| {
444            t.downcast_ref::<T>()
445                .expect("Type mistmatch, inconsistent TypedHandle")
446        })
447    }
448
449    /// Create a new [TypedHandle] from a [TypeHandle].
450    pub fn from_handle(handle: TypeHandle, ctx: &Context) -> Result<TypedHandle<T>> {
451        if handle.deref(ctx).is::<T>() {
452            Ok(TypedHandle(handle, PhantomData::<T>))
453        } else {
454            arg_err_noloc!(TypedHandleErr {
455                expected: T::get_type_id_static().disp(ctx).to_string(),
456                provided: handle.disp(ctx).to_string()
457            })
458        }
459    }
460
461    /// Erase the static Rust type and return the underlying [TypeHandle].
462    pub fn to_handle(&self) -> TypeHandle {
463        self.0
464    }
465}
466
467impl<T: Type> From<TypedHandle<T>> for TypeHandle {
468    fn from(value: TypedHandle<T>) -> Self {
469        value.to_handle()
470    }
471}
472
473impl<T: Type> Clone for TypedHandle<T> {
474    fn clone(&self) -> TypedHandle<T> {
475        *self
476    }
477}
478
479impl<T: Type> Copy for TypedHandle<T> {}
480
481impl<T: Type> PartialEq for TypedHandle<T> {
482    fn eq(&self, other: &Self) -> bool {
483        self.0 == other.0
484    }
485}
486
487impl<T: Type> Eq for TypedHandle<T> {}
488
489impl<T: Type> Hash for TypedHandle<T> {
490    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
491        self.0.hash(state);
492    }
493}
494
495impl<T: Type> Printable for TypedHandle<T> {
496    fn fmt(
497        &self,
498        ctx: &Context,
499        state: &printable::State,
500        f: &mut core::fmt::Formatter<'_>,
501    ) -> core::fmt::Result {
502        Printable::fmt(&self.0, ctx, state, f)
503    }
504}
505
506impl<T: Type + Parsable<Arg = (), Parsed = TypedHandle<T>>> Parsable for TypedHandle<T> {
507    type Arg = ();
508    type Parsed = Self;
509
510    fn parse<'a>(
511        state_stream: &mut StateStream<'a>,
512        arg: Self::Arg,
513    ) -> ParseResult<'a, Self::Parsed> {
514        let loc = state_stream.loc();
515        spaced(TypeId::parser(()))
516            .then(move |type_id| {
517                let loc = loc.clone();
518                combine::parser(move |parsable_state: &mut StateStream<'a>| {
519                    if type_id != T::get_type_id_static() {
520                        let ctx = &*parsable_state.state.ctx;
521                        input_err!(
522                            loc.clone(),
523                            TypedHandleErr {
524                                expected: T::get_type_id_static().disp(ctx).to_string(),
525                                provided: type_id.disp(ctx).to_string()
526                            }
527                        )?
528                    }
529                    T::parser(arg).parse_stream(parsable_state).into()
530                })
531            })
532            .parse_stream(state_stream)
533            .into_result()
534    }
535}
536
537impl<T: Type> Verify for TypedHandle<T> {
538    fn verify(&self, ctx: &Context) -> Result<()> {
539        self.0.deref(ctx).verify(ctx)
540    }
541}
542
543/// Marker trait for type interface trait objects.
544///
545/// This is auto-implemented by the `#[type_interface]` macro for `dyn Interface`
546/// objects and is used to restrict [type_cast] and [type_impls] to interface casts.
547#[diagnostic::on_unimplemented(
548    message = "`{Self}` not a type interface.",
549    label = "If `{Self}` is a trait, annotate it with #[type_interface] to be able to cast to it from a `&dyn Type`",
550    note = "If you want to cast to a concrete `Type`, use `downcast_ref` instead."
551)]
552pub trait TypeInterfaceMarker {}
553
554/// Cast reference to a [Type] object to an interface reference.
555///
556/// Right usage: cast to an interface trait object.
557/// ```
558/// use pliron::builtin::type_interfaces::FunctionTypeInterface;
559/// use pliron::r#type::{Type, type_cast};
560///
561/// fn right_cast(ty: &dyn Type) {
562///     let _ = type_cast::<dyn FunctionTypeInterface>(ty);
563/// }
564/// ```
565///
566/// Casting to concrete [Type] types are intentionally rejected.
567/// ```compile_fail
568/// use pliron::builtin::types::IntegerType;
569/// use pliron::r#type::{Type, type_cast};
570///
571/// fn wrong_cast(ty: &dyn Type) {
572///     let _ = type_cast::<IntegerType>(ty);
573/// }
574/// ```
575/// Use [downcast_rs](https://docs.rs/downcast-rs/latest/downcast_rs/#example-without-generics)
576/// to cast to concrete [Type] types.
577pub fn type_cast<T: ?Sized + TypeInterfaceMarker + 'static>(ty: &dyn Type) -> Option<&T> {
578    crate::utils::trait_cast::any_to_trait::<T>(ty.as_any())
579}
580
581/// Does this [Type] object implement interface `T`?
582///
583/// Right usage: query using an interface trait object.
584/// ```
585/// use pliron::builtin::type_interfaces::FunctionTypeInterface;
586/// use pliron::r#type::{Type, type_impls};
587///
588/// fn right_query(ty: &dyn Type) {
589///     let _ = type_impls::<dyn FunctionTypeInterface>(ty);
590/// }
591/// ```
592///
593/// Querying with a concrete [Type] type is intentionally rejected.
594/// ```compile_fail
595/// use pliron::builtin::types::IntegerType;
596/// use pliron::r#type::{Type, type_impls};
597///
598/// fn wrong_query(ty: &dyn Type) {
599///     let _ = type_impls::<IntegerType>(ty);
600/// }
601/// ```
602pub fn type_impls<T: ?Sized + TypeInterfaceMarker + 'static>(ty: &dyn Type) -> bool {
603    type_cast::<T>(ty).is_some()
604}
605
606/// Does [Type] `T` implement interface `I`?
607/// See also: [`type_impls`]
608///
609/// Example:
610/// ```
611/// use pliron::builtin::type_interfaces::{FunctionTypeInterface, FloatTypeInterface};
612/// use pliron::builtin::types::FunctionType;
613/// use pliron::r#type::{Type, type_impls_static};
614/// assert!(type_impls_static::<FunctionType, dyn FunctionTypeInterface>());
615/// assert!(!type_impls_static::<FunctionType, dyn FloatTypeInterface>());
616/// ```
617pub fn type_impls_static<T: Type, I: ?Sized + TypeInterfaceMarker + 'static>() -> bool {
618    impls_trait_static::<T, I>()
619}
620
621/// A wrapper around [TypeHandle] whose underlying [Type] is statically known to
622/// implement the type interface `I`.
623///
624/// ```
625/// use pliron::{
626///     builtin::{type_interfaces::FloatTypeInterface, types::FP32Type},
627///     context::Context,
628///     r#type::TypeInterfaceHandle,
629/// };
630///
631/// let ctx = &mut Context::new();
632/// let fp32 = FP32Type::get(ctx);
633/// let handle: TypeInterfaceHandle<dyn FloatTypeInterface> = fp32.into();
634/// assert_eq!(handle.deref(ctx).get_semantics().bits, 32);
635/// ```
636pub struct TypeInterfaceHandle<I: ?Sized + TypeInterfaceMarker + 'static>(
637    TypeHandle,
638    PhantomData<I>,
639);
640
641#[derive(Error, Debug)]
642#[error("TypeInterfaceHandle mismatch: {provided} does not implement interface {interface}")]
643pub struct TypeInterfaceHandleErr {
644    pub interface: String,
645    pub provided: String,
646}
647
648/// A static promise that the [Type] `Self` implements the type interface `I`.
649///
650/// This is auto implemented by [type_interface_impl](pliron::derive::type_interface_impl)
651/// for every [Type] that implements an interface. A manual implementation making a false
652/// promise will trigger a runtime panic.
653///
654/// See also [type_impls_static], which answers the same question at run time.
655///
656/// Example:
657///
658/// ```compile_fail
659/// use pliron::{
660///     builtin::{type_interfaces::FloatTypeInterface, types::IntegerType},
661///     context::Context,
662///     r#type::TypeInterfaceHandle,
663/// };
664///
665/// let ctx = &mut Context::new();
666/// let i32_ty = IntegerType::get(ctx, 32, pliron::builtin::types::Signedness::Signed);
667/// // Compilation fails: `IntegerType` does not implement `FloatTypeInterface`.
668/// let handle: TypeInterfaceHandle<dyn FloatTypeInterface> = i32_ty.into();
669/// ```
670#[diagnostic::on_unimplemented(
671    message = "`{Self}` does not implement the type interface `{I}`.",
672    label = "Annotate `{Self}`'s implementation of this interface with #[type_interface_impl]",
673    note = "Use `TypeInterfaceHandle::from_handle` to check this at run time instead."
674)]
675pub trait TypeImplsInterface<I: ?Sized + TypeInterfaceMarker + 'static>: Type {}
676
677impl<I: ?Sized + TypeInterfaceMarker + 'static> TypeInterfaceHandle<I> {
678    /// Return a [Ref] to the [Type], as an object of the interface `I`.
679    pub fn deref<'a>(&self, ctx: &'a Context) -> Ref<'a, I> {
680        Ref::map(self.0.deref(ctx), |ty| {
681            type_cast::<I>(ty).expect("Interface mismatch, inconsistent TypeInterfaceHandle")
682        })
683    }
684
685    /// Create a new [TypeInterfaceHandle] from a [TypeHandle].
686    pub fn from_handle(handle: TypeHandle, ctx: &Context) -> Result<TypeInterfaceHandle<I>> {
687        if type_impls::<I>(&*handle.deref(ctx)) {
688            Ok(TypeInterfaceHandle(handle, PhantomData::<I>))
689        } else {
690            arg_err_noloc!(TypeInterfaceHandleErr {
691                interface: core::any::type_name::<I>().to_string(),
692                provided: handle.disp(ctx).to_string()
693            })
694        }
695    }
696
697    /// Erase the static interface and return the underlying [TypeHandle].
698    pub fn to_handle(&self) -> TypeHandle {
699        self.0
700    }
701}
702
703impl<T: TypeImplsInterface<I>, I: ?Sized + TypeInterfaceMarker + 'static> From<TypedHandle<T>>
704    for TypeInterfaceHandle<I>
705{
706    fn from(value: TypedHandle<T>) -> Self {
707        assert!(
708            type_impls_static::<T, I>(),
709            "{} does not implement interface {}. \
710             Use the `type_interface_impl` macro",
711            core::any::type_name::<T>(),
712            core::any::type_name::<I>()
713        );
714        TypeInterfaceHandle(value.to_handle(), PhantomData::<I>)
715    }
716}
717
718impl<I: ?Sized + TypeInterfaceMarker + 'static> From<TypeInterfaceHandle<I>> for TypeHandle {
719    fn from(value: TypeInterfaceHandle<I>) -> Self {
720        value.to_handle()
721    }
722}
723
724impl<I: ?Sized + TypeInterfaceMarker + 'static> Clone for TypeInterfaceHandle<I> {
725    fn clone(&self) -> TypeInterfaceHandle<I> {
726        *self
727    }
728}
729
730impl<I: ?Sized + TypeInterfaceMarker + 'static> Copy for TypeInterfaceHandle<I> {}
731
732impl<I: ?Sized + TypeInterfaceMarker + 'static> PartialEq for TypeInterfaceHandle<I> {
733    fn eq(&self, other: &Self) -> bool {
734        self.0 == other.0
735    }
736}
737
738impl<I: ?Sized + TypeInterfaceMarker + 'static> Eq for TypeInterfaceHandle<I> {}
739
740impl<I: ?Sized + TypeInterfaceMarker + 'static> Hash for TypeInterfaceHandle<I> {
741    fn hash<H: Hasher>(&self, state: &mut H) {
742        self.0.hash(state);
743    }
744}
745
746impl<I: ?Sized + TypeInterfaceMarker + 'static> Debug for TypeInterfaceHandle<I> {
747    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
748        Debug::fmt(&self.0, f)
749    }
750}
751
752impl<I: ?Sized + TypeInterfaceMarker + 'static> Printable for TypeInterfaceHandle<I> {
753    fn fmt(
754        &self,
755        ctx: &Context,
756        state: &printable::State,
757        f: &mut core::fmt::Formatter<'_>,
758    ) -> core::fmt::Result {
759        Printable::fmt(&self.0, ctx, state, f)
760    }
761}
762
763impl<I: ?Sized + TypeInterfaceMarker + 'static> Parsable for TypeInterfaceHandle<I> {
764    type Arg = ();
765    type Parsed = Self;
766
767    fn parse<'a>(
768        state_stream: &mut StateStream<'a>,
769        _arg: Self::Arg,
770    ) -> ParseResult<'a, Self::Parsed> {
771        let loc = state_stream.loc();
772        TypeHandle::parser(())
773            .then(move |handle| {
774                let loc = loc.clone();
775                combine::parser(move |parsable_state: &mut StateStream<'a>| {
776                    let ctx = &*parsable_state.state.ctx;
777                    if !type_impls::<I>(&*handle.deref(ctx)) {
778                        input_err!(
779                            loc.clone(),
780                            TypeInterfaceHandleErr {
781                                interface: core::any::type_name::<I>().to_string(),
782                                provided: handle.disp(ctx).to_string()
783                            }
784                        )?
785                    }
786                    Ok(TypeInterfaceHandle(handle, PhantomData::<I>)).into_parse_result()
787                })
788            })
789            .parse_stream(state_stream)
790            .into_result()
791    }
792}
793
794impl<I: ?Sized + TypeInterfaceMarker + 'static> Verify for TypeInterfaceHandle<I> {
795    fn verify(&self, ctx: &Context) -> Result<()> {
796        self.0.verify(ctx)
797    }
798}
799
800/// Every type interface must have a function named `verify` with this type.
801pub type TypeInterfaceVerifier = fn(&dyn Type, &Context) -> Result<()>;
802/// Function returns the list of super verifiers, followed by a self verifier, for an interface.
803pub type TypeInterfaceAllVerifiers = fn() -> Vec<TypeInterfaceVerifier>;
804
805#[doc(hidden)]
806/// A [Type] paired with an interface it implements
807/// (specifically the verifiers (including super verifiers) for that interface).
808type TypeInterfaceVerifierInfo = &'static [(core::any::TypeId, TypeInterfaceAllVerifiers)];
809
810#[doc(hidden)]
811#[cfg(not(target_family = "wasm"))]
812pub mod statics {
813    use super::*;
814
815    #[::pliron::linkme::distributed_slice]
816    pub static TYPE_INTERFACE_VERIFIERS: [TypeInterfaceVerifierInfo] = [..];
817
818    pub(super) fn get_type_interface_verifiers()
819    -> impl Iterator<Item = &'static TypeInterfaceVerifierInfo> {
820        TYPE_INTERFACE_VERIFIERS.iter()
821    }
822}
823#[doc(hidden)]
824#[cfg(not(target_family = "wasm"))]
825pub use statics::TYPE_INTERFACE_VERIFIERS;
826
827#[doc(hidden)]
828#[cfg(target_family = "wasm")]
829pub mod statics {
830    use super::*;
831    use crate::InventoryWrapper;
832
833    ::pliron::inventory::collect!(InventoryWrapper<TypeInterfaceVerifierInfo>);
834
835    pub(super) fn get_type_interface_verifiers()
836    -> impl Iterator<Item = &'static TypeInterfaceVerifierInfo> {
837        ::pliron::inventory::iter::<InventoryWrapper<TypeInterfaceVerifierInfo>>().map(|llw| llw.0)
838    }
839}
840
841#[doc(hidden)]
842/// A map from every [Type] to its ordered (as per interface deps) list of interface verifiers.
843/// An interface's super-interfaces are to be verified before it itself is.
844pub static TYPE_INTERFACE_VERIFIERS_MAP: LazyLock<
845    HMap<core::any::TypeId, Vec<TypeInterfaceVerifier>>,
846> = LazyLock::new(|| collect_deduped_interface_verifiers(statics::get_type_interface_verifiers()));
847
848/// A convenient struct to hold a type signature.
849
850#[derive(Debug, Clone, PartialEq, Eq, Hash)]
851#[format("`(` vec($arguments, CharSpace(`,`)) `)` ` -> ` `(`vec($results, CharSpace(`,`)) `)`")]
852pub struct TypeSig {
853    pub arguments: Vec<TypeHandle>,
854    pub results: Vec<TypeHandle>,
855}