E07930: the whole source of its examples

The code page for E07930 shows the parts of a long example that teach the error. This page holds every line of it, compiled by the EK9 compiler exactly as written.

bad.ek9

Fails with E07930: cannot assign from sanitized parameter - creates hidden copy semantics

#!ek9
defines module error.e07930.bad

  defines function

    badDeclarationFromSanitized()
      -> input as sanitized String
      <- result as String?

      //ERROR: Direct declaration assignment from sanitized parameter
      local <- input

      //Use local to avoid NOT_REFERENCED error
      result: local

    badReassignmentFromSanitized()
      -> input as sanitized String
      <- result as String?

      local <- "initial"
      //ERROR: Reassignment from sanitized parameter
      local := input

      result: local

    badGuardedAssignmentFromSanitized()
      -> input as sanitized String
      <- result as String?

      local <- String()
      //ERROR: Assign-if-unset from sanitized parameter
      local :=? input

      result: local

    okDirectUse()
      -> input as sanitized String
      <- result as String?

      //OK: Using sanitized parameter directly is fine
      result: input

    okExplicitCopy()
      -> input as sanitized String
      <- result as String?

      //OK: Explicit copy makes semantics clear
      local <- String(input)
      result: local

    okPassToAnotherFunction()
      -> input as sanitized String
      <- result as String?

      //OK: Passing to another function is fine
      result: processData(input)

    processData()
      -> data as String
      <- result as String?
      result: data

    <?-
      BAD: Coalescing min operator could return sanitized parameter directly.
      If input < other alphabetically, result becomes an ALIAS to input.
    -?>
    badCoalescingMinFromSanitized()
      -> input as sanitized String
      <- result as String?

      other <- "zzzzz"
      //ERROR: Could create alias if input is selected as minimum
      local <- input <? other

      result: local

    <?-
      BAD: Coalescing max operator could return sanitized parameter directly.
      If input > other alphabetically, result becomes an ALIAS to input.
    -?>
    badCoalescingMaxFromSanitized()
      -> input as sanitized String
      <- result as String?

      other <- "aaaaa"
      //ERROR: Could create alias if input is selected as maximum
      local <- input >? other

      result: local

    <?-
      BAD: Elvis operator could return sanitized parameter directly.
      If input is set, result becomes an ALIAS to input.
    -?>
    badElvisFromSanitized()
      -> input as sanitized String
      <- result as String?

      //ERROR: Could create alias if input is set
      local <- input ?: "default"

      result: local

    <?-
      BAD: Ternary operator could return sanitized parameter directly.
      If condition is true, result becomes an ALIAS to input.
    -?>
    badTernaryFromSanitized()
      -> input as sanitized String
      <- result as String?

      condition <- true
      //ERROR: Could create alias if condition selects input
      local <- condition <- input : "alternative"

      result: local

    <?-
      BAD: Null coalescing operator could return sanitized parameter directly.
      If input is not null, result becomes an ALIAS to input.
    -?>
    badNullCoalescingFromSanitized()
      -> input as sanitized String
      <- result as String?

      //ERROR: Could create alias if input is not null
      local <- input ?: "default"

      result: local

    <?-
      BAD: Coalescing LE operator could return sanitized parameter directly.
    -?>
    badCoalescingLEFromSanitized()
      -> input as sanitized String
      <- result as String?

      other <- "zzzzz"
      //ERROR: Could create alias if input is selected
      local <- input <? other

      result: local

    <?-
      BAD: Coalescing GE operator could return sanitized parameter directly.
    -?>
    badCoalescingGEFromSanitized()
      -> input as sanitized String
      <- result as String?

      other <- "aaaaa"
      //ERROR: Could create alias if input is selected
      local <- input >? other

      result: local

    <?-
      BAD: Guard in if statement could create alias to sanitized parameter.
      The guard uses '<-' which is an assignment.
    -?>
    badGuardInIfFromSanitized()
      -> input as sanitized String
      <- result as String?

      //ERROR: Guard creates alias to sanitized parameter
      if local <- input
        result: local
      else
        result: "empty"

    <?-
      BAD: Guard in switch statement could create alias to sanitized parameter.
    -?>
    badGuardInSwitchFromSanitized()
      -> input as sanitized String
      <- result as String?

      //ERROR: Guard creates alias to sanitized parameter
      switch local <- input
        case "test"
          result: local
        default
          result: "other"

    <?-
      BAD: An assignment pre-flow (:=) could create alias to sanitized parameter.
      The ':=' assigns to an EXISTING variable; 'then local?' then gates on it being set.
    -?>
    badGuardExpressionFromSanitized()
      -> input as sanitized String
      <- result as String?

      //Declare local first (required for the ':=' pre-flow)
      local <- String()

      //ERROR: Guard creates alias to sanitized parameter
      if local := input then local?
        result: local
      else
        result: "empty"