Questions on two crashes caused by variadic generic function

  1. Does anyone know why this doesn't work? If I remove the map() call, it compiles. It seems to indicate that each entity can only be used as parameter to function and it's not allowed to invoke method on it.

    func test<each Entity>(entities entity: repeat [each Entity])  {
        repeat (each entity).map({ $0 }) // This crashes compiler
    }
    
  2. On another note, I also find saving value pack expansion result to a local variable crashes the compiler. Adding parenthesis around repeat each entity fixes the issue. I suppose the parenthesis is required because it creates a tuple of value pack expansion (the compiler shouldn't crash though).

    func test<each Entity>(entities entity: repeat each Entity)  {
        let result = repeat each entity  // This crashes compiler
    }
    
1 Like

The type of the closure's $0 is the element type of the pack. For now there's a limitation preventing closures from being able to capture element types, which in practice means closures cannot appear inside the pack expansion expression at all. As a workaround you can declare a local function that is generic over the element type:

func test<each Entity>(entities entity: repeat [each Entity])  {
    func doStuff <Element>(_ arg: [Element]) {
        arg.map { $0 }
    }
    repeat doStuff(each entity)
}

On another note, I also find saving value pack expansion result to a local variable crashes the compiler. Adding parenthesis around repeat each entity fixes the issue. I suppose the parenthesis is required because it creates a tuple of value pack expansion (the compiler shouldn't crash though).

This appears to have already been fixed on the 5.10 branch.

1 Like

Thanks. It works. I'm trying to generalize your workaround, but it crashes too. I think the type of the closure's $0 isn't the element type of the pack in the code below. Is it a different issue?

func _map<Element, T>(
    _ elements: [Element],
    _ transform: (Element) throws -> T
) rethrows -> [T] {
    try elements.map(transform)
}

func test<each Entity>(entities entity: repeat [each Entity])  {
    repeat _map(each entity) { $0 }
}

EDIT: I figured out why. What matters is the call site where the capture actually happens. So it's the same issue. The only way to avoid it is to not use closure inside the pack expansionn expression (as you said).

2 Likes