Skip to content

Conversation

@ethanhuang13
Copy link

Add Identifiable Conformance to PartiallyGenerated

Summary

This PR adds Identifiable conformance to the PartiallyGenerated struct generated by the @Generable macro, enabling seamless integration with SwiftUI's ForEach and other APIs that require Identifiable types.

Problem

When using @Generable structs with SwiftUI's ForEach, compilation fails because the generated PartiallyGenerated struct does not conform to Identifiable.

It's not the case in Foundation Models framework. The commented code are produced by @Generable in Foundation Models.

// Sample code from https://developer.apple.com/documentation/foundationmodels/supporting-languages-and-locales-with-foundation-models?changes=_10_5#Prompt-the-model-in-the-language-you-prefer

import FoundationModels

@Generable(description: "Basic profile information about a cat")
struct CatProfile {
    var name: String

    @Guide(description: "The age of the cat", .range(0 ... 20))
    var age: Int

    @Guide(description: "One sentence about this cat's personality")
    var profile: String

    /*
      nonisolated static var generationSchema: FoundationModels.GenerationSchema {
          FoundationModels.GenerationSchema(
              type: Self.self,
              description: "Basic profile information about a cat",
              properties: [
                  FoundationModels.GenerationSchema.Property(name: "name", type: String.self),
                  FoundationModels.GenerationSchema.Property(
                      name: "age",
                      description: "The age of the cat",
                      type: Int.self,
                      guides: [.range(0 ... 20)]
                  ),
                  FoundationModels.GenerationSchema.Property(
                      name: "profile",
                      description: "One sentence about this cat's personality",
                      type: String.self
                  ),
              ]
          )
      }

      nonisolated var generatedContent: GeneratedContent {
          var properties = [(name: String, value: any ConvertibleToGeneratedContent)]()
          addProperty(name: "name", value: self.name)
          addProperty(name: "age", value: self.age)
          addProperty(name: "profile", value: self.profile)
          return GeneratedContent(
              properties: properties,
              uniquingKeysWith: { _, second in
                  second
              }
          )
          func addProperty(name: String, value: some Generable) {
              properties.append((name, value))
          }
          func addProperty(name: String, value: (some Generable)?) {
              if let value {
                  properties.append((name, value))
              }
          }
      }

      nonisolated struct PartiallyGenerated: Identifiable, nonisolated FoundationModels.ConvertibleFromGeneratedContent {
          var id: GenerationID
          var name: String.PartiallyGenerated?
          var age: Int.PartiallyGenerated?
          var profile: String.PartiallyGenerated?
          nonisolated init(_ content: FoundationModels.GeneratedContent) throws {
              self.id = content.id ?? GenerationID()
              self.name = try content.value(forProperty: "name")
              self.age = try content.value(forProperty: "age")
              self.profile = try content.value(forProperty: "profile")
          }
      }
    */
}

/*
extension CatProfile: nonisolated FoundationModels.Generable {
  nonisolated init(_ content: FoundationModels.GeneratedContent) throws {
    self.name = try content.value(forProperty: "name")
    self.age = try content.value(forProperty: "age")
    self.profile = try content.value(forProperty: "profile")
  }
}
*/

Solutions & Changes

Following Foundation Models' @Generable macros:

  • Added Identifiable conformance to PartiallyGenerated struct.
  • Added var id: GenerationID property
  • Use generatedContent.id as id

Testing:

  • Updated Create instance from GeneratedContent test with generationID

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Identifiable conformance to the PartiallyGenerated struct generated by the @Generable macro, enabling seamless use with SwiftUI's ForEach and other APIs requiring Identifiable types. The implementation follows Foundation Models' pattern by adding a GenerationID property.

  • Added Identifiable conformance to the macro-generated PartiallyGenerated struct
  • Introduced id: GenerationID property initialized from GeneratedContent.id or a new instance
  • Updated test to verify id property is correctly set from GeneratedContent

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
Sources/AnyLanguageModelMacros/GenerableMacro.swift Adds Identifiable conformance and id property to the generated PartiallyGenerated struct
Tests/AnyLanguageModelTests/GenerableMacroTests.swift Updates test to create GeneratedContent with a GenerationID and verifies the id is properly assigned

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

stringLiteral: """
public struct PartiallyGenerated: Sendable, ConvertibleFromGeneratedContent {
public struct PartiallyGenerated: Identifiable, Sendable, ConvertibleFromGeneratedContent {
public var id: GenerationID
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The id property should be declared as public let instead of public var to make it immutable. This is consistent with: 1) the other properties in the PartiallyGenerated struct which are all declared as let, 2) the semantics of Identifiable where the identity should remain stable and not change, and 3) the documentation in GenerationID which states that IDs are "stable for the duration of a response".

Suggested change
public var id: GenerationID
public let id: GenerationID

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant