Add type checking to the node graph (#1025)

* Implement type inference

Add type hints to node trait

Add type annotation infrastructure

Refactor type ascription infrastructure

Run cargo fix

Insert infer types stub

Remove types from node identifier

* Implement covariance

* Disable rejection of generic inputs + parameters

* Fix lints

* Extend type checking to cover Network inputs

* Implement generic specialization

* Relax covariance rules

* Fix type annotations for TypErasedComposeNode

* Fix type checking errors

* Keep connection information during node resolution
* Fix TypeDescriptor PartialEq implementation

* Apply review suggestions

* Add documentation to type inference

* Add Imaginate node to document node types

* Fix whitespace in macros

* Add types to imaginate node

* Fix type declaration for imaginate node + add console logging

* Use fully qualified type names as fallback during comparison

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2023-02-15 23:31:30 +01:00
committed by Keavon Chambers
parent a64c856ec4
commit 5dab7de68d
25 changed files with 1365 additions and 1008 deletions

View File

@@ -1,6 +1,8 @@
use dyn_any::{DynAny, StaticType};
use dyn_any::StaticType;
pub use graph_craft::proto::{Any, TypeErasedNode, TypeErasedPinned, TypeErasedPinnedRef};
use graphene_core::NodeIO;
pub use graphene_core::{generic, ops, Node};
use std::{marker::PhantomData, pin::Pin};
use std::marker::PhantomData;
pub struct DynAnyNode<I, O, Node> {
node: Node,
@@ -39,17 +41,13 @@ impl<_I, _O, S0> DynAnyRefNode<_I, _O, S0> {
}
}
pub type TypeErasedNode<'n> = dyn for<'i> Node<'i, Any<'i>, Output = Any<'i>> + 'n + Send + Sync;
pub type TypeErasedPinnedRef<'n> = Pin<&'n (dyn for<'i> Node<'i, Any<'i>, Output = Any<'i>> + 'n + Send + Sync)>;
pub type TypeErasedPinned<'n> = Pin<Box<dyn for<'i> Node<'i, Any<'i>, Output = Any<'i>> + 'n + Send + Sync>>;
pub trait IntoTypeErasedNode<'n> {
fn into_type_erased(self) -> TypeErasedPinned<'n>;
}
impl<'n, N: 'n> IntoTypeErasedNode<'n> for N
where
N: for<'i> Node<'i, Any<'i>, Output = Any<'i>> + Send + Sync + 'n,
N: for<'i> NodeIO<'i, Any<'i>, Output = Any<'i>> + Send + Sync + 'n,
{
fn into_type_erased(self) -> TypeErasedPinned<'n> {
Box::pin(self)
@@ -70,7 +68,7 @@ impl<N: Copy, O: StaticType> Copy for DowncastNode<O, N> {}
#[node_macro::node_fn(DowncastNode<_O>)]
fn downcast<N, _O: StaticType>(input: Any<'input>, node: &'input N) -> _O
where
N: Node<'input, Any<'input>, Output = Any<'input>>,
N: for<'any_input> Node<'any_input, Any<'any_input>, Output = Any<'any_input>> + 'input,
{
let node_name = core::any::type_name::<N>();
let out = dyn_any::downcast(node.eval(input)).unwrap_or_else(|e| panic!("DowncastNode Input {e} in:\n{node_name}"));
@@ -148,8 +146,6 @@ impl<'a> ComposeTypeErased<'a> {
}
}
pub type Any<'n> = Box<dyn DynAny<'n> + 'n>;
pub fn input_node<O: StaticType>(n: TypeErasedPinnedRef) -> DowncastBothNode<(), O> {
DowncastBothNode::new(n)
}