E11055: constructor result is discarded - assign to a variable; if you need side effects, use a function

Category: E11xxx Code quality and IR analysis · Reported in phase: PRE_IR_CHECKS · Classification: DISCARDED_CONSTRUCTOR_RETURN · All error codes

What went wrong

A constructor was called as a standalone statement and the resulting object is immediately discarded. A constructor's purpose is to create a usable object. Discarding it means the object is created and immediately garbage collected — this is always either a bug (forgot to assign) or a misuse of constructors.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 732 (Why must every constructor, operator, and pure function r...)

Rationale

A constructor creates an object. If that object is never assigned, passed as an argument, or used in any expression, the creation achieves nothing.

If the intent was to perform side effects (logging, registration, I/O), use a function instead. Functions are the correct EK9 construct for actions that produce no usable value. Constructors are for object creation.

Go makes discarded return values a compile error. Swift and Rust warn by default. SonarQube classifies this as a Bug (rule S1848). Every major static analysis tool flags this pattern.

Common causes

  • Forgot the '<-' assignment: wrote 'MyType(args)' instead of 'x <- MyType(args)'
  • Copy-paste error that removed the variable declaration
  • Using a constructor for side effects instead of a function
  • Mutation removed the assignment from valid code (fuzzer finding)

See also

  • E11050: discarded operator return
  • E11051: discarded pure method return
  • E11052: discarded Result or Optional

Examples

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

Fails with E11055: constructor result is discarded - assign to a variable; if you need side effects, use a function

#!ek9
defines module error.e11055.bad

  defines class

    Sensor
      reading <- Float()

      Sensor()
        -> initialReading as Float
        this.reading :=: initialReading

      currentReading() as pure
        <- rtn as Float: reading

      default operator ?

  defines function

    testDiscardedBuiltInConstructor()
      String("hello")

    testDiscardedBuiltInConstructorWithArg()
      Integer(42)

    testDiscardedUserClassConstructor()
      Sensor(98.6)

    testDiscardedExceptionConstructor()
      Exception("something went wrong")

    testAssignedConstructorIsOk()
      greeting <- String("hello")
      sensor <- Sensor(98.6)
      Stdout().println(greeting)
      Stdout().println($sensor.currentReading())

    testConstructorInExpressionIsOk()
      stdout <- Stdout()
      stdout.println(String("used in expression"))

Fixed: Keep what you construct - or call a function if you only want its side effect

#!ek9
defines module error.e11055.good

  defines function

    greeting()
      <- rtn as String: String("hello")

    announce()
      stdout <- Stdout()
      stdout.println(greeting())

Questions and answers

These Q&A entries show E11055 and its fix: