Compiler can't infer types with Parameter Packs containing more than three elements

Hello! I'm trying to create a container type that hold a root type, plus n number of additional types that conform to a protocol. This works well with Parameter Packs, except that any time the number of additional types in the Parameter Packs exceeds three, the compiler throws an error and can't infer the type anymore. This requires a lot of extra code to work around inference issues and use the Expanded type with multiple elements.

Am I doing something wrong here? Or is there a workaround that would let me keep calling addingExpansion as many times as needed?

:point_up: Up to three Parameter Pack elements works fine

:point_up: One more and inference stops working

UPDATE: here is the actual code:

struct Expanded<Base, each Expansion> {
    fileprivate let base: Base
    fileprivate let expansions: (repeat each Expansion)
    init(base: Base, expansions: (repeat each Expansion)) {
        self.base = base
        self.expansions = (repeat each expansions)
    }

    public func addingExpansion<New>(_ expansion: New) -> Expanded<Base, repeat each Expansion, New> {
        .init(base: base, expansions: (repeat each expansions, expansion))
    }
}

struct One { }
struct Two { }
struct Three { }
struct Four { }


let initial = Expanded(base: "", expansions: One())
var more = initial
    .addingExpansion(Two())
    .addingExpansion(Three())
    .addingExpansion(Four())

print(more) 
1 Like

If you post the code itself rather than an image of it, you would make it easier for others to help you. They can just copy and paste.

Plus, images take a lot more space to store. :slight_smile:

Good point β€” updated my post with the code!

2 Likes

That's debatable. I also use parameter packs, but doing so is rather a world of pain.

Here are two:

typealias Itself<Value> = Value

extension Expanded {
  func addingExpansions<each New>(
    _ expansion: repeat each New
  ) -> Expanded<Base, repeat each Expansion, repeat each New> {
    .init(base: base, expansions: (repeat each self.expansions, repeat each expansion))
  }
}
var more = (
  ( initial
    .addingExpansion(Two())
    .addingExpansion(Three())
    as Itself
  )
  .addingExpansion(Four()) as Itself
)
  .addingExpansion(One())

var smore = initial.addingExpansions(
  Two(), Three(), Four(), One()
)

But keep in mind to expect that pain.

For example, this is all fine:

more = smore

let makeMore = {
  initial.addingExpansions(
    Two(), Three(), Four(), One()
  )
}

more = makeMore()

But any of this will yield the error

Cannot assign value of type 'Expanded<String, One, Two, Three, Four, One>' to type 'Expanded<String, One, Two, Three, Four, One>'

more = initial.addingExpansions(
  Two(), Three(), Four(), One()
)
more = {
  initial.addingExpansions(
    Two(), Three(), Four(), One()
  )
} ()

// Yes, this is exactly the copied and pasted code from above, aside from `var`.
smore = initial.addingExpansions(
  Two(), Three(), Four(), One()
)
1 Like

Thanks for the great notes and suggested workarounds! Yes, I also ran into the bizarre type mismatch error for two exactly identical types :man_facepalming:

That approach of just taking multiple expansions as variadic parameters rather than chaining multiple calls with single parameters each works well enough! :+1:

1 Like

This type inference failure when chaining is a known bug, but I don’t think we’re tracking it on GitHub. Do you mind filing an issue?

Yes. I do not think it is ethically acceptable that there is no system in place for contributors to be paid.

Sorry, that was a terrible choice of words. I certainly did not mean it to come across as asking you folks to do my job. I meant to ask if Daniel wishes to make the contribution himself and track fixes.

And thank you for reporting this @danielhall. The more test cases, the better.

2 Likes

I actually filed this issue the other day. Looks like you triaged it recently :slight_smile:

4 Likes

Hi @anthonylatsis, thanks for replying to this thread! Sure, I'd happy to open an issue but it looks like @stephencelis is already a step ahead there! Happy to provide anything else that can help though.

No worries, I’ve related all these test cases internally. Thanks again!

1 Like