Opaque return type fails when using variadic generics

I'm running into another issue that I'd love any advice on how to work around. I've filed a bug here: Type with parameter pack argument fails to be erased to an opaque type. · Issue #83055 · swiftlang/swift · GitHub

Basically, returning a type from a method specifying an opaque return type fails when using variadic generics. Below is a minimal reproduction. Interestingly, the error is Pack expansion requires that 'each PropertyValue' and 'repeat each PropertyValue' have the same shape, which is something I've seen when failing to convert a variadic argument into a tuple, but there is no such situation here I recognize.

public protocol Schema<Value>: Sendable {
  associatedtype Value
}

public protocol SchemaCodable {
  associatedtype Schema: VariadicTest.Schema where Schema.Value == Self
  static func schema() -> Schema
}

public protocol StructSchemaCodable: SchemaCodable {
  associatedtype SchemaDefinition
  static var schemaDefinition: SchemaDefinition { get }
}

// MARK: - This does not work

public struct StructSchemaDefinition<
  each PropertyValue: SchemaCodable
>: Sendable {
}

public struct StructSchema<
  Value: StructSchemaCodable,
  each PropertyValue: SchemaCodable
>: Schema
where
  Value.SchemaDefinition == StructSchemaDefinition<
    repeat each PropertyValue
  >
{
  var opaque: some Schema<Value> {
    // Pack expansion requires that 'each PropertyValue' and 'repeat each PropertyValue' have the same shape
    self
  }
}

// MARK: - The Following works

public struct StructSchemaDefinitionNoVariadic<
  PropertyValues
>: Sendable {
}

public struct StructSchemaNoVariadic<
  Value: StructSchemaCodable,
  PropertyValues
>: Schema
where
  Value.SchemaDefinition == StructSchemaDefinitionNoVariadic<PropertyValues>
{
  var opaque: some Schema<Value> {
    self
  }
}

Not so! Reducing it further shows that the problem lies with using opaque return types in any capacity—the constraint is problematic even without attempting to return an instance of the type that uses it.

struct S1<each T> { }
struct S2<each T, U> { }
extension S2 where U == S1<repeat each T> {
  var property: some Any { () } // ❌
  func function() -> some Any { () } // ❌
}
2 Likes