-
Notifications
You must be signed in to change notification settings - Fork 116
Structural Types Schema support (#517) #614
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
base: main
Are you sure you want to change the base?
Conversation
7ee9866 to
13653d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted
|
@jdegoes @plokhotnyuk Structural types are a little tricky especially in Scala 3. type PersonLike = { def name:String; def age:Int}
val aPersoon: PersonLike = new Selectable {
...
}Will not be recognized by the compiler as a One could suggest, to create a class final class Record(...) extends Selectable {
...
}So that this is returned by val structuralSchema: Schema[ Record {def name: String; def age: Int}] = nominal.structuralBut this is fundamentally flawed, since it defeats the purpose of the structural typing. case class Person(name: String, age: Int)This is not of type Instead my current solution offers that .structural does not return //Works on JVM, JS, Native
val structural = Schema.derived[Record {def name: String; def age: Int}] |
253ec74 to
1ebd60b
Compare
|
@987Nabil Please update, rebase, and refactor to handle refinement types on |
52e9c2d to
3d1a1b4
Compare
3d1a1b4 to
7b75a2f
Compare
|
@987Nabil Pleaes re-open when ready. 🙏 |
What to do with this, I was waiting him to fix 28 test errors, I'm going to fix them then submit my pr as they coming from this implementation not my implementation but my implementation depends on them! |
8b0f838 to
eded7a2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 34 out of 34 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| val typeName = normalizeTypeName(fieldInfos.toList.map { case (name, reflect) => | ||
| (name, reflect.typeName.name) | ||
| (name, reflect.typeName.name) |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate line detected. Line 220 is identical to line 219, creating a duplicate entry in the tuple list. This will cause the same field name and type name to be added twice to the fieldInfos list, leading to incorrect type name normalization.
| (name, reflect.typeName.name) |
- Fix duplicate line bug in Scala 2 ToStructuralVersionSpecific.scala - Add DynamicValue roundtrip tests to PureStructuralTypeSpec - Remove TypeNameNormalizationSpec per review feedback
- Delete EnumToUnionSpec.scala (tests enum derivation, not .structural) - Delete SealedTraitToUnionSpec.scala (tests sealed trait derivation, not .structural) - Delete AsPrimitiveSpec.scala (tests As/Into primitives, unrelated to structural types) - Revert JsonSpec.scala additions (coverage tests unrelated to structural types) - Fix weak assertions in EnumStructuralSpec.scala and UnionTypesSpec.scala to use exact Tag pattern matches
Per reviewer feedback on PR #614: - EnumToUnionSpec now tests schema.structural conversion for Scala 3 enums - SealedTraitToUnionSpec now tests schema.structural for sealed traits - Tests verify structural schemas are Variants with Tag markers - Tests verify DynamicValue round-trip through structural schema - Removed AsPrimitiveSpec (unrelated to structural types)
- Fix duplicate line bug in Scala 2 ToStructuralVersionSpecific.scala - Add DynamicValue roundtrip tests to PureStructuralTypeSpec - Remove TypeNameNormalizationSpec per review feedback
20d4776 to
df780f4
Compare
- Delete EnumToUnionSpec.scala (tests enum derivation, not .structural) - Delete SealedTraitToUnionSpec.scala (tests sealed trait derivation, not .structural) - Delete AsPrimitiveSpec.scala (tests As/Into primitives, unrelated to structural types) - Revert JsonSpec.scala additions (coverage tests unrelated to structural types) - Fix weak assertions in EnumStructuralSpec.scala and UnionTypesSpec.scala to use exact Tag pattern matches
Per reviewer feedback on PR #614: - EnumToUnionSpec now tests schema.structural conversion for Scala 3 enums - SealedTraitToUnionSpec now tests schema.structural for sealed traits - Tests verify structural schemas are Variants with Tag markers - Tests verify DynamicValue round-trip through structural schema - Removed AsPrimitiveSpec (unrelated to structural types)
- Fix duplicate line bug in Scala 2 ToStructuralVersionSpecific.scala - Add DynamicValue roundtrip tests to PureStructuralTypeSpec - Remove TypeNameNormalizationSpec per review feedback
e1b1ee3 to
b2b5fd0
Compare
Implement ToStructural type class for converting nominal types to pure structural types on JVM. Key features: - Schema.structural extension method via SchemaVersionSpecific trait - Fully unpacks opaque types (Scala 3) and ZIO Prelude newtypes recursively - Handles nested type constructors (e.g., List[UserId] -> List[String]) - JVM-only via Platform.supportsReflection checks - Uses pure Selectable types with selectDynamic (no custom apply/map) Also fixes Array/IArray/ArraySeq constructors to implement emptyObject and use Math.max(sizeHint, 1) for proper initialization.
- Fix fullyUnpackType to use isOpaqueAlias for proper opaque type detection - Add OpaqueTypeUnpackingSpec for testing opaque type handling in structural types - Add enum structural conversion tests to EnumToUnionSpec
- Move enum structural conversion tests from shared to JVM-only (EnumStructuralSpec) - Remove structural tests from EnumToUnionSpec (shared) to fix JS/Native compilation - Add TupleStructuralSpec for tuple structural conversion tests - Add StructuralRoundTripSpec for product/sum type round-trip and structure tests
- Restore StructuralTypeCompileErrorSpec (JS/Native) to original error expectations - Restore StructuralTypeSpec (Scala 2) to original form - Add StructuralBindingSpec to exercise structural schema encoding/decoding paths
- Add AsPrimitiveSpec with tests for As.reverseInto, As.reverse, As.apply, Into.identity, and all numeric widening/narrowing conversions - Extend JsonSpec with additional coverage for: - PrimitiveValue conversions (all date/time types, Currency, UUID) - Number comparison edge cases (invalid number strings) - Parse error handling (invalid JSON, unclosed structures) - ByteBuffer encoding/decoding - CharSequence parsing - Object/Array varargs constructors - sortKeys/dropNulls/dropEmpty on non-objects - asUnsafe method Achieves branch coverage 83.31% (>= 83% required)
- Delete EnumToUnionSpec.scala (tests enum derivation, not .structural) - Delete SealedTraitToUnionSpec.scala (tests sealed trait derivation, not .structural) - Delete AsPrimitiveSpec.scala (tests As/Into primitives, unrelated to structural types) - Revert JsonSpec.scala additions (coverage tests unrelated to structural types) - Fix weak assertions in EnumStructuralSpec.scala and UnionTypesSpec.scala to use exact Tag pattern matches
Per reviewer feedback on PR #614: - EnumToUnionSpec now tests schema.structural conversion for Scala 3 enums - SealedTraitToUnionSpec now tests schema.structural for sealed traits - Tests verify structural schemas are Variants with Tag markers - Tests verify DynamicValue round-trip through structural schema - Removed AsPrimitiveSpec (unrelated to structural types)
Replace contains() assertions with exact equality checks for structural type names per reviewer feedback.
- Changed structural types from type members to method members (def Tag: "Red") - Added ReflectiveDeconstructor for reading fields via reflection - Added ReflectiveVariantDiscriminator for Tag-based case discrimination - Added ReflectiveMatcher for variant case matching - Sorted variant cases alphabetically for consistency - Updated tests to use anonymous structural instances per JDG review
- Fix duplicate line bug in Scala 2 ToStructuralVersionSpecific.scala - Add DynamicValue roundtrip tests to PureStructuralTypeSpec - Remove TypeNameNormalizationSpec per review feedback
- Rename UnsupportedTypeErrorSpec to SupportedTypesSpec (moved to scala-3/)
- Add explicit Schema[{def ...}] type annotations to all typeCheck tests
- Fix DynamicValue.Record(Vector(...)) compilation errors after rebase
- Add typeCheck tests to enum, sealed trait, product, and tuple specs
- All tests pass on Scala 3.3.7 and 2.13.18
Replace all typeName.contains() and typeName == assertions with typeCheck tests that verify structural type signatures compile correctly. Changes: - Remove typeName assertions from 13 test files - Delete TypeNameNormalizationSpec.scala (tests TypeName going away) - Preserve all runtime tests (roundtrips, Reflect structure checks) - Add typeCheck tests where needed for coverage This prepares for TypeName removal in a separate PR.
Change structural type encoding from flat Tag-based format to nested case
wrapper format:
- Old: {def Tag: "Circle"; def radius: Double}
- New: {def Circle: {def radius: Double}}
Key changes:
- Rename buildStructuralTypeWithTag to buildNestedCaseType
- Add ReflectiveVariantCaseDeconstructor for nested value extraction
- Update ReflectiveVariantDiscriminator to check case name method existence
- Update ReflectiveMatcher to invoke case name method for nested values
- Update normalizeUnionCaseTypeName for {CaseName:{fields}} format
- Update all structural test specs for new encoding
b2b5fd0 to
e6c5e70
Compare
fixes #517
/claim #517
This PR is build up on my PR for #518 so #589 should be reviewed first.