1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
use crate::type_checker::TypeChecker; use crate::type_checker::{AbstractType, TypeCheckKey}; use ena::unify::UnifyKey; /// Indicates that an abstract type could not be reified because it is too general or too restrictive. /// # Example /// 1. A numeric type cannot be reified into any concrete value because the concrete counterpart could be a natural /// number, integer, floating point number, .... -> `ReificationError::TooGeneral` /// 2. An integer type cannot be reified into a concrete type with fixed memory layout except a default size is /// defined, e.g. an Int will be reified into an Int32. -> `ReificationError::TooGeneral` /// 3. An unbounded integer might not have a concrete counterpart because the system requires a concrete bit size. /// -> `ReificationError::Conflicting` /// /// Note the subtle difference between `ReificationError::TooGeneral` and `ReificationError::Conflicting`: /// + In the `Conflicting` case there is no valid counterpart /// + In the `TooGeneral` case the counterpart is not defined or not unique but could exist. pub enum ReificationError { /// Attempting to reify an abstract type with either no unique concrete counterpart or with no defined default /// reification value results in this error. TooGeneral(String), /// Attempting to reify an abstract type for which no concrete counterpart does exist results in this error. Conflicting(String), } /// A type implementing this trait can be `reified` into a concrete representation. /// This transformation cannot fail. If it is fallible, refer to `TryReifiable`. pub trait Reifiable { type Reified; /// Transforms an instance of `Reifiable` into an more concrete `Reifiable::Reified` type. fn reify(&self) -> Self::Reified; } /// A type implementing this trait can potentially be `reified` into a concrete representation. /// This transformation can fail. If it is infallible, refer to `Reifiable`. pub trait TryReifiable { type Reified; /// Attempts to transform an instance of `TryReifiable` into an more concrete /// `TryReifiable::Reified` type. Returns a `ReificationError` if the transformation fails. fn try_reify(&self) -> Result<Self::Reified, ReificationError>; } /// A type implementing this trait can be `generalized` into an abstract representation. /// This transformation cannot fail. pub trait Generalizable { type Generalized; /// Generalizes the given concrete type. fn generalize(&self) -> Self::Generalized; } impl<Key: UnifyKey> TypeChecker<Key> where Key::Value: AbstractType + TryReifiable, { /// Returns a mapping of all registered abstract type nodes to their reification. pub fn try_get_reified_type_table( &mut self, ) -> Vec<(TypeCheckKey<Key>, Result<<Key::Value as TryReifiable>::Reified, ReificationError>)> { self.get_type_table().into_iter().map(|(key, value)| (key, value.try_reify())).collect() } } impl<Key: UnifyKey> TypeChecker<Key> where Key::Value: AbstractType + Reifiable, { /// Returns a mapping of all registered abstract type nodes to their reification. pub fn get_reified_type_table(&mut self) -> Vec<(TypeCheckKey<Key>, <Key::Value as Reifiable>::Reified)> { self.get_type_table().into_iter().map(|(key, value)| (key, value.reify())).collect() } }