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

Generic result builder "buildExpression" inference bug #59575

Open
stephencelis opened this issue Jun 19, 2022 · 0 comments
Open

Generic result builder "buildExpression" inference bug #59575

stephencelis opened this issue Jun 19, 2022 · 0 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.

Comments

@stephencelis
Copy link
Contributor

Describe the bug

A generic result builder with a buildExpression that locks uses these generics must still constrain the buildBlock against those same generics when it reaches a certain complexity.

To Reproduce

I've tried to create a minimal repro, though it may minimize a little further.

protocol P0<A0, A1> {
  associatedtype A0
  associatedtype A1
  func f(_ a0: A0, _ a1: A1)
}

struct S0<A0, A1>: P0 {
  func f(_ a0: A0, _ a1: A1) {}
}

@resultBuilder
enum B<A0, A1> {
  static func buildExpression<T: P0<A0, A1>>(_ expression: T) -> T { expression }

  static func buildPartialBlock<R>(first: R) -> R { first }

  static func buildPartialBlock<R0: P0, R1: P0<R0.A0, R0.A1>>(
    accumulated: R0, next: R1
  ) -> some P0<R0.A0, R0.A1>
  // Commenting the next line in gets things building,
  // even though it should be inferred via 'buildExpression'
//  where R0.A0 == A0, R1.A1 == A1
  {
    accumulated
  }
}

struct S1<B0> {}
enum E1<B0, B1> {}

protocol P1 {
  associatedtype B0
  var s1: S1<B0> { get set }
}

protocol P2 {
  associatedtype B0
  associatedtype B1
  static func e1(_: E1<B0, B1>) -> Self
}

extension P0
where
  A0: P1,
  A1: P2,
  A0.B0 == A1.B0
{
  func g<GReturnValue: P0>(
    @B<GReturnValue.A0, GReturnValue.A1> build: () -> GReturnValue
  ) -> some P0<A0, A1>
  where
    GReturnValue.A0 == A0.B0,
    GReturnValue.A1 == A1.B1
  {
    S0()
  }
}

struct S2: P0 {
  struct A0: P1 {
    var s1: S1<T0>
  }
  enum A1: P2 {
    case e1(E1<T0, T1>)
  }

  struct T0 {}
  enum T1 {}

  func f(_ a0: A0, _ a1: A1) {}
}

@B<S2.A0, S2.A1>
var p: some P0<S2.A0, S2.A1> {
  S0<S2.A0, S2.A1>()
    .g { // error: Generic parameter 'GReturnValue' could not be inferred
      S0<S2.T0, S2.T1>()
      S0<S2.T0, S2.T1>()
    }
}

Expected behavior

I expect the above to build without specifying the generic constraints on buildPartialBlock(accumulated:next:).

Environment (please complete the following information):

  • Xcode 14 (Swift 5.7 Development Snapshot 2022-06-13 (a))
@stephencelis stephencelis added the bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. label Jun 19, 2022
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.
Projects
None yet
Development

No branches or pull requests

1 participant