E06010: type/function is generic but no parameters were supplied

Category: E06xxx Type hierarchy checks · Reported in phase: FULL_RESOLUTION · Classification: GENERIC_TYPE_OR_FUNCTION_PARAMETERS_NEEDED · All error codes

What went wrong

A generic type or function requires type parameters but none were provided. You must specify what types the generic operates on using the 'of' clause.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 681 (What is the correct syntax for generic type parameterizat...)
  • ek9 -q 742 (How does EK9 detect when a function type or generic type ...)
  • ek9 -q 45 (How does the List type work in EK9?)
  • ek9 -q 46 (How does the Dict type work in EK9?)
  • ek9 -q 127 (How does collection type inference work in EK9?)

[TARGET-TYPED CONSTRUCTION] A bare 'G()' is completed from its DECLARED type when that type is a parameterisation of exactly that generic - a typed declaration, a ':', ':=', '=' or ':=?' assignment to a declared variable, a returning variable, a property, or a field reached through an object:

  • //A typed declaration, and an assignment to a declared variable
  • names as List of String: List()
  • names := List()
  • //A field through 'this', and a field through another object
  • this.lines := List()
  • other <- Order()
  • other.lines: List()
  • //A generic function's value
  • fn as echo of Integer: echo()

'<-' declares no type, so 'names <- List()' is this error; a target of another generic ('x as Optional of String: List()'), a non-generic target, or 'List().reverse()' completes nothing. A ternary arm and an argument are not targets either (an argument takes part in choosing the overload) - write the type arguments there:

  • //A ternary arm and an argument are not targets: write the type arguments there
  • this.lines := accepted <- List() of String else ["none"]
  • count <- countOf(List() of String)

Type inference alternative

When creating with literal values, types can be inferred: '["a", "b", "c"]' is a List of String and '{"key": 123}' a Dict of (String, Integer).

How to fix it

  1. Add 'of TypeName' after the generic type constructor: 'names <- List() of String'
  2. For multiple parameters: use 'of (Type1, Type2)'
  3. Or declare the target's type and construct bare: 'names as List of String: List()'
  4. Or use literal syntax if initializing with values

Common generic types and parameters

  • List of T - element type
  • Dict of (K, V) - key type, value type
  • Optional of T - contained type
  • Result of (T, E) - success type, error type
  • Function of (T, R) - input type, return type

Common causes

  • Forgetting to specify type parameter
  • Coming from dynamically-typed languages
  • Assuming type can always be inferred (it can't without values)

See also

  • E06010: MISSING type parameters entirely (this error)
  • E06020: WRONG NUMBER of type parameters
  • E04080: similar error in earlier compilation phase

Examples

Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.

Fails with E06010: type/function is generic but no parameters were supplied

#!ek9
defines module error.e06010.bad

  defines function

    <?-
      Valid uses of built-in generics for comparison.
    -?>
    ValidBuiltInGenericUse()
      stdout <- Stdout()

      validOpt <- Optional("Hello")
      stdout.println(`opt: ${validOpt}`)

      validOpt2 <- Optional() of String
      stdout.println(`opt2 set: ${validOpt2?}`)

      validList <- [1, 2, 3]
      stdout.println(`list: ${validList}`)

    <?-
      Bare Optional() without type parameters.
    -?>
    BareOptionalCall()
      bareOpt <- Optional()
      Stdout().println(`${bareOpt?}`)

    <?-
      Bare List() without type parameters.
    -?>
    BareListCall()
      bareList <- List()
      Stdout().println(`${bareList}`)

    <?-
      Bare Result() without type parameters.
    -?>
    BareResultCall()
      bareResult <- Result()
      Stdout().println(`${bareResult?}`)

Fixed: Say what it holds: of String, of Integer, of (Integer, String)

#!ek9
defines module error.e06010.good.fix

  defines function

    <?-
      Valid uses of built-in generics for comparison.
    -?>
    ValidBuiltInGenericUse()
      stdout <- Stdout()

      validOpt <- Optional("Hello")
      stdout.println(`opt: ${validOpt}`)

      validOpt2 <- Optional() of String
      stdout.println(`opt2 set: ${validOpt2?}`)

      validList <- [1, 2, 3]
      stdout.println(`list: ${validList}`)

    <?-
      Bare Optional() without type parameters.
    -?>
    BareOptionalCall()
      bareOpt <- Optional() of String
      Stdout().println(`${bareOpt?}`)

    <?-
      Bare List() without type parameters.
    -?>
    BareListCall()
      bareList <- List() of Integer
      Stdout().println(`${bareList}`)

    <?-
      Bare Result() without type parameters.
    -?>
    BareResultCall()
      bareResult <- Result() of (Integer, String)
      Stdout().println(`${bareResult?}`)

Fixed: Say what the generic holds: Optional() of String - or declare the type and let it be the target

#!ek9
defines module error.e06010.good

  defines function

    typedCalls()
      stdout <- Stdout()
      nothingYet <- Optional() of String
      names as List of String: List()
      outcome as Result of (String, Integer): Result()
      stdout.println(`${nothingYet?} ${length names} ${outcome?}`)

Fixed: A bare G() takes its type arguments from a declared target of the same generic

#!ek9
defines module error.e06010.good.targets

  defines function
    echo() of type T
      -> item as T
      <- rtn as T: item

  defines class
    Order
      lines as List of String: List()

      replaceLines()
        //A typed declaration, and an assignment to a declared variable
        names as List of String: List()
        names := List()
        //A field through 'this', and a field through another object
        this.lines := List()
        other <- Order()
        other.lines: List()
        //A generic function's value
        fn as echo of Integer: echo()
        lines += names
        lines += other.lines
        require fn?

      replaceWhenAccepted()
        -> accepted as Boolean
        //A ternary arm and an argument are not targets: write the type arguments there
        this.lines := accepted <- List() of String else ["none"]
        count <- countOf(List() of String)
        require count?

      countOf()
        -> items as List of String
        <- rtn as Integer: length items

      default operator ?

Questions and answers

These Q&A entries show E06010 and its fix: