Parameter pack bug?

Loving the parameter packs feature, great work! To test it out, I made a rough variadic zip function with this signature (that works as expected):

func zipp<each T>(_ arrays: repeat [each T]) -> [(repeat each T)]

The surprising thing is that tuple destructuring seems to behave erratically, or at least in a to me surprising way. It seems to me that all these should work, but some of them do not (all of them work for normal zip). Is this a bug or am I missing something?

func zippTest(array1: [String], array2: [String]) {
    // error = Value of tuple type '(String, String)' has no member '1'

    // This works
    let variadic = zipp(array1, array2)
    let indirect1 = variadic.map { $0 + $1 }
    let indirect2 = variadic.map { x, y in x + y }
    let indirect3 = variadic.map { $0.0 + $0.1 }
    let indirect4 = variadic.map { x in x.0 + x.1 }

    // But without the intrmediate variable `varidic` it seems that "explicit destructuring" breaks down
    let direct3 = zipp(array1, array2).map { $0.0 + $0.1 } // error
    let direct4 = zipp(array1, array2).map { x in x.0 + x.1 } // error

    // Mapping via $0 does not help
    let mapped3 = zipp(array1, array2).map { $0 }.map { $0.0 + $0.1 } // error
    let mapped4 = zipp(array1, array2).map { $0 }.map { x in x.0 + x.1 } // error

    // But mapping via an explicit tuple does
    let tupleMapped3 = zipp(array1, array2).map { ($0, $1) }.map { $0.0 + $0.1 }
    let tupleMapped4 = zipp(array1, array2).map { ($0, $1) }.map { x in x.0 + x.1 }

    // Casting also works, even though zipp(array1, array2) already is supposed be a [(String, String)]
    let cast3 = (zipp(array1, array2) as [(String, String)]).map { $0.0 + $0.1 }
    let cast4 = (zipp(array1, array2) as [(String, String)]).map { x in x.0 + x.1 }
}

3 Likes

I suspect the behavior depends on the order in which the expression checker solves constraints. We probably get to a point where a type variable still has a pack type, and we try to solve the tuple member constraint which fails. We need to fix the solver to delay tuple member simplification until pack expansion types are made concrete. Do you mind filing an issue?

This might already be fixed, I tried with more or less recent main and all of the expressions marked as // error type-check.

3 Likes

@GreatApe Could you please verify that with a recent snapshot of main from swift.org?

Sure, will do that!

So I tried with the trunk development snapshot of August 12th, but it didn't seem to work there. This is the first time I run a snapshot, so I might be doing something wrong, but I did download, install and select it in the XCode > Toolchains menu.

I think it might just be an old compiler that doesn't have a fix, we have made some changes to parameter pack handling recently. I see that we have August 26th compiler now on swift.org which is very close to what I have locally and when I run your examples with main branch development build all I get is warnings about immutable variable initialization for all the let bindings.

2 Likes