Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error trying to build up a tuple of generic types via a result builder; works fine for non-generic types #78392

Open
lukaskollmer opened this issue Dec 31, 2024 · 0 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels

Comments

@lukaskollmer
Copy link

lukaskollmer commented Dec 31, 2024

Description

Trying to build up, via a result builder, a tuple of variadic length where the elements in the tuple are instances of a generic type with different generic parameters, doesn't compile, even though one would assume that this should be possible.

See the code below for an example.

Modifying the result builder to instead operate on a variadic generic struct acting as a wrapper around a tuple, and then "converting" it back to a tuple at the end (see here) works fine.

Alternatively, trying to simply build up a tuple of non-generic types (or, rather a tuple of arbitrary types where we don't know anything about the type; it might of course still be generic) also works absolutely fine (see here for an example of what i'm talking about).

So it appears that the issue here is trying to build up a tuple where a generic parameter pack is applied to the elements of the tuple?

I.e.: (pseudocode)

  • works: TupleBuilder<each T> -> (repeat each T)
  • broken: TulpeBuilder<each T> -> (repeat X<each T>)

Reproduction

protocol P {}


struct S1: P {}
struct S2: P {}


struct Entry<T: P> {
    let value: T
    init(_ value: T) {
        self.value = value
    }
}


@resultBuilder
enum ContentBuilder1 {
    static func buildExpression<T>(_ entry: Entry<T>) -> Entry<T> {
        entry
    }
    
    static func buildEither<T>(
        first entry: Entry<T>
    ) -> Entry<T> {
        entry
    }
    
    static func buildEither<T>(
        second entry: Entry<T>
    ) -> Entry<T> {
        entry
    }
    
    static func buildPartialBlock<T>(
        first entry: Entry<T>
    ) -> Entry<T> {
        entry
    }
    
    static func buildPartialBlock<each T, NextT>(
        accumulated: (repeat Entry<each T>),
        next: Entry<NextT>
    ) -> (repeat Entry<each T>, Entry<NextT>) {
        (repeat each accumulated, next)
    }
    
    static func buildBlock() -> () {
        ()
    }
    
    static func buildFinalResult<each T>(
        _ entry: (repeat Entry<each T>)
    ) -> (repeat Entry<each T>) {
        entry
    }
}



struct Foo<each T: P> {
    static func make1(@ContentBuilder1 _ entry: () -> (repeat Entry<each T>)) -> Self {
        Self()
    }
}


_ = Foo.make1 {} // fine

_ = Foo.make1 { // fine
    Entry(S1())
}

_ = Foo.make1 { // Cannot convert return expression of type '(_: (Entry<S1>, Entry<S2>))' to return type '(repeat Entry<_>)'
    Entry(S1())
    Entry(S2())
}

Expected behavior

This should work, since it's essentially just a combination of two language features that each should (and do) work on their own.

Environment

swift-driver version: 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)
Target: arm64-apple-macosx14.0

Additional information

No response

@lukaskollmer lukaskollmer added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Dec 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

1 participant