~mna/snow unlisted

snow/doc/generics.md -rw-r--r-- 1.9 KiB
424066c5Martin Angers doc: v0.0.5 9 months ago


  • AST nodes are pretty much correct as-is, GenericClause for both Params and Args, and GenericIdent for explicit generic instantiations.

  • In the semantic graph, the non-nil GenericClause field indicates if the struct or fn declaration is a generic or not.

  • The $T identifiers must be declarations, so they can be registered in the scopes (and they have to be registered, so they can be looked up and see if the identifier is defined). They translate to GenericElem in the semantic graph and can only appear in GenericClause (so, in an Fn or Struct declaration).


  • The Type interface has an IsGeneric method to prevent a non-instantiated Generic type from being used anywhere except in its declaration and instatiation. As long as the type is not fully instantiated, it is still IsGeneric(...) == true.

  • It follows that generic declarations have a standard StructType or SignatureType, but it returns true to IsGeneric. The type-check pass would make sure it is only used where allowed.

  • Structs and Fns have fundamentally different semantics regarding generics:

    • a generic struct instantiation yields a type and each different instantiation (where different actual types are used) yields different types, so the instantiation types are part of the instantiated struct type.
    • a generic fn instantiation yields a value that can be stored in a variable, passed as argument to a function, or called. That value has the type of the resulting signature of that function, with generic placeholders replaced with actual types.
    • TODO: what about nested fns that use generic placeholders in a generic function? Currently this is treated as generic fns on their own, but the non-surprising behaviour might be that it uses its parent generic fn's placeholders... Maybe all generic declarations should be explicit and nested declarations inherit the placeholders?