E221: Recurse With Default

This warning is emitted when a recursive call uses a default argument for a parameter, which may lead to unintended behavior.

In recursive functions, using default arguments can be confusing because the default value is used on each recursive call rather than passing the current value down the stack. This warning helps catch potential bugs where you meant to pass the current parameter value but accidentally relied on the default.

This warning is enabled with the -Wrecurse-with-default compiler flag.


Example

//> using options -Wrecurse-with-default

def fun(x: Int)(using p: Int, q: Int = 0): Int =
  if x <= 0 then p * q
  else fun(x - 1)(using p = p + x)

Error

-- [E221] Type Warning: example.scala:5:17 -------------------------------------
5 |  else fun(x - 1)(using p = p + x)
  |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |       Recursive call used a default argument for parameter q.
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | It's more explicit to pass current or modified arguments in a recursion.
   -----------------------------------------------------------------------------

Solution

Pass all arguments explicitly in the recursive call:

//> using options -Wrecurse-with-default

def fun(x: Int)(using p: Int, q: Int = 0): Int =
  if x <= 0 then p * q
  else fun(x - 1)(using p = p + x, q = q)

Or use a different design that avoids default arguments in recursive functions:

//> using options -Wrecurse-with-default

def fun(x: Int)(using p: Int)(q: Int): Int =
  if x <= 0 then p * q
  else fun(x - 1)(using p = p + x)(q)