Thoughts on fixing a SIL verification error and/or bad codegen involving default arguments & implicitly-opened existentials

Perhaps something went wrong with that consuming parameter. I don't know how those are lowered here.

It's really just for default arguments and inout arguments. We have to delay the inout access until after all rvalue arguments are evaluated. I don't think there is any reason to delay default arguments, except for this opened existential case.

For rvalue arguments, existential opening actually happens before ordinary argument evaluation via yet another mechanism. Suppose you have something like

func f(_: Int, _: some P) {}

func g() -> Int {}
func h() -> any P {}

f(g(), h())

This basically lowers to the equivalent of this:

let x = h() // second argument is evaluated first
_openExistential(x, do: {
  xx in // type of xx is a type parameter now
  let y = g() // first argument is evaluated last
  g(y, xx)
})

In the AST this uses OpenExistentialExpr / OpaqueValueExpr instead of actually calling _openExistential, but the end result is that the expression being opened is evaluated before other arguments. (However, I believe that according to the rules of the proposal, this "delay everything that is not an open existential" step is not actually necessary, and after we sort out the other issues here, we could perform this opening in SILGen argument evaluation instead! Here's another fun idea. Try to write down all the combinations of orders of lvalue/rvalue open/not-open default/not-default arguments, and see how many different evaluation orders you can get. ;-) )

So the only problem arises when we're opening an existential that is an lvalue. In this case, we still form the OpenExistentialExpr as before, but SILGen doesn't actually open it until after it evaluates the arguments.

SILGen has some vestigial support for the old curried function call syntax that was removed in Swift 3. We still use it to represent the self parameter, so a method has type (Self) -> (Args...) -> Result in the AST, but in SIL it's (Args..., Self) -> Result. There are two "call sites" for a single "call", basically. But now it only ever comes up in this case.

Thank you for digging into this! Sorting out the details of fundamentals like call argument evaluation order is really important work.

2 Likes