Cannot mangle free standing archetype

Hi! I'm running into an annoying crash related to variadic generics with the error message "Cannot mangle free-standing archetype"

I've posted an issue here: Cannot mangle free-standing archetype · Issue #83021 · swiftlang/swift · GitHub

I've reduced the problematic code to:

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

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

public struct BottomSchema<Value: SchemaCodable>: Schema {

  public typealias Schema = BottomSchema<Self>
  static public func schema() -> Schema {
    Schema()
  }
}

extension String: SchemaCodable {
  public static func schema() -> BottomSchema<String> {
    BottomSchema<String>()
  }
}

public protocol StructSchema: Schema {
  associatedtype Properties
  associatedtype PropertyName: CodingKey
  static var properties: Properties { get }
}

extension StructSchema {
  fileprivate static func metaSchema<each PropertyValue: SchemaCodable>()
    -> StructMetaSchema<Self, repeat each PropertyValue>
  where
    (repeat StructSchemaPropertyDefinition<Self.Value, PropertyName, each PropertyValue>)
      == Properties
  {
    StructMetaSchema<Self, repeat each PropertyValue>()
  }
}

public struct StructSchemaPropertyDefinition<
  Root,
  Name: CodingKey,
  Value: SchemaCodable
>: Sendable {
  let name: Name
  let keyPath: KeyPath<Root, Value> & Sendable
  let valueSchema: Value.Schema
}

public struct ExampleStruct {
  let x, y: String
}

public struct ExampleStructSchema: StructSchema {

  public typealias Value = ExampleStruct

  public enum PropertyName: CodingKey {
    case x, y
  }

  public static let properties = (
    StructSchemaPropertyDefinition<ExampleStruct, PropertyName, String>(
      name: .x,
      keyPath: \ExampleStruct.x,
      valueSchema: BottomSchema<String>()
    ),
    StructSchemaPropertyDefinition<ExampleStruct, PropertyName, String>(
      name: .y,
      keyPath: \ExampleStruct.y,
      valueSchema: BottomSchema<String>()
    )
  )

  /// Removing this function causes the compiler to no longer crash.
  public static func schema() -> StructMetaSchema<Self, String, String> {
    metaSchema()
  }

}

extension StructSchema {

  fileprivate subscript<T: SchemaCodable>(
    _ keyPath: KeyPath<Value, T>
  ) -> T.Schema {
    T.schema()
  }

}

public struct StructMetaSchema<
  Base: StructSchema,
  each BasePropertyValue: SchemaCodable
>: StructSchema
where
  Base.Properties == (
    repeat StructSchemaPropertyDefinition<
      Base.Value,
      Base.PropertyName,
      each BasePropertyValue
    >
  )
{
  public typealias Value = Base
  public typealias PropertyName = Base.PropertyName
  public typealias Properties = (
    repeat StructSchemaPropertyDefinition<
      Base, PropertyName, (each BasePropertyValue).Schema
    >
  )

  public static var properties: Properties {
    (repeat StructSchemaPropertyDefinition(
      name: (each Value.properties).name,
      keyPath: \Base.[(each Base.properties).keyPath],
      valueSchema: type(of: (each Value.properties).valueSchema).schema()
    ))
  }

  public static func schema() -> StructMetaSchema<Self, repeat (each BasePropertyValue).Schema> {
    StructMetaSchema<Self, repeat (each BasePropertyValue).Schema>()
  }
}

Anyone else run into this crash, and/or have any suggestions for a workaround? (Claude thinks @Slava_Pestov might have the most context :slight_smile:)

Key paths cannot be formed in a variadic generic context, due to implementation limitations. I guess we should just add a diagnostic instead of crashing at this point.

2 Likes

Interesting! I had actually run into an issue with KeyPaths and variadic generics before, but the reason this was confusing is because removing the specified function caused the crash to go away because compilation failed due to the protocol requirements not being fulfilled. This red herring confused me but I guess what is actually going on is that once those checks pass, it attempts to generate the binary and crashes during name mangling?

I remember I had also run into a similar issue with Sendable checking, where that seems to happen later than other checks and I need to address other compilation issues before the compiler lets me know I’m not Sendabling correctly.

Either way, thanks for the tip! Switching to a closure based accessor fixed the crash.