Where is type inference not supported in generic type and function bodies?

← Generics · Ref: Q646

Inside a generic type or function body, EK9 does not support type inference for local variables when the type would depend on the generic parameter. You must use explicit type declarations.

INFERENCE LIMITATION

Inside a generic definition, the compiler cannot infer types that depend on T because T is not yet known. Explicit typing is required when creating instances of T or using T-typed expressions.

EXPLICIT RETURN TYPES

Generic functions must declare return types explicitly:

  transform() of type (S, T) as open
    -> source as S
    <- target as T: T()

FIELD DECLARATIONS

Fields in generic classes must use the type parameter explicitly:

  Container of type T
    item as T?

WHEN INFERENCE WORKS

Type inference works at the CALL SITE, not inside the generic body:

  intContainer <- Container(42)  // inference works here

But inside Container's methods, T must be used explicitly.

See Q642 for constructor inference at call site. See Q648 for function constraints. See Q194 for generic class basics.

Example

defines module qa.genericsdeep.inferencelimits

  defines function

    <?-
      Correct: explicit types used throughout the generic body.
      Return type explicitly declared as T.
    -?>
    identity() of type T as open
      -> item as T
      <- rtn as T: T(item)

    <?-
      Correct: multi-param generic with explicit return type.
      Both S and T used with explicit type annotations.
    -?>
    converter() of type (S, T) as open
      -> source as S
      <- target as T: T()
      require source?

  defines class

    <?-
      Correct: all fields and method return types use T explicitly.
      No reliance on type inference inside the generic body.
    -?>
    Stack of type T
      items as List of T?

      Stack()
        items :=? List() of T

      Stack()
        -> initial as T
        items: List() of T
        items += initial

      push()
        -> item as T
        if not items?
          items: List() of T
        items += item

      count() as pure
        <- rtn as Integer: 0
        if items?
          rtn: length items

      default operator ?

  defines program

    InferenceLimitsDemo()
      stdout <- Stdout()

      // === INFERENCE AT CALL SITE (works) ===

      result <- identity(42)
      stdout.println(`Identity: ${result}`)

      // === EXPLICIT TYPE AT CALL SITE ===

      stack <- Stack("first")
      stack.push("second")
      stack.push("third")
      stdout.println(`Stack count: ${stack.count()}`)

Common mistakes

E50060 — Integer has no toString() method in EK9. Use the $ prefix operator or string interpolation. See ek9 -h E50060 for details.

Incorrect:

stdout.println(stack.count().toString())

Correct:

stdout.println(`Stack count: ${stack.count()}`)
Other ways to ask this
  • What is E06070 type inference not supported in generic context?
  • When must I use explicit types inside generic definitions?
  • Why cannot I use type inference inside a generic class body?

Coming from another language?

Java: type inference works inside generics (var keyword, diamond). C++: auto deduction inside templates. Rust: type inference inside generic functions with compiler assistance. Go: type inference limited inside generics too. Kotlin: type inference works inside generic bodies. EK9: no inference inside generic bodies, explicit T usage required.

Keywords: function, inference, explicit, type-parameter, E06070, context, type, generic, body, limitation, parameter