Skip to content

Add progression test for issue #481: Subtype relation for refined types#574

Open
1234-ad wants to merge 1 commit into
zio:developfrom
1234-ad:fix-481-refined-type-subtype-test
Open

Add progression test for issue #481: Subtype relation for refined types#574
1234-ad wants to merge 1 commit into
zio:developfrom
1234-ad:fix-481-refined-type-subtype-test

Conversation

@1234-ad

@1234-ad 1234-ad commented Feb 15, 2026

Copy link
Copy Markdown

Description

This PR adds a comprehensive progression test for issue #481, documenting the known limitation where subtype relations fail for refined types with type/value members.

Problem

Currently, izumi-reflect does not preserve type and value members in concrete types, which causes false comparisons when checking if a refined type is a subtype of its base type.

Example of the issue:

trait A { type B = Int }

val concreteTag = Tag[A]
val refinedTag = Tag[A { type B = Int }]

// This should be true but returns false:
refinedTag <:< concreteTag

The refined type A { type B = Int } is more specific than A, so it should be a subtype. However, because the concrete type's tag doesn't preserve the type member B, the subtype check fails.

Solution

This PR adds a progression test that documents the expected behavior. Progression tests are tests that currently fail but document what should work. When the feature is eventually implemented, this test will start passing (which is good!), and it should then be moved to the main test suite.

Changes Made

Modified Files

  • izumi-reflect/izumi-reflect/src/test/scala/izumi/reflect/test/SharedTagProgressionTest.scala
    • Added comprehensive test case for issue Subtype relation for refined type fails #481
    • Tests multiple refinement scenarios:
      • Type members with concrete types (type B = Int)
      • Abstract type members (type D)
      • Value members (val x: Int)
      • Def members (def method(): String)
      • Multiple refinements combined
    • All test cases wrapped in broken { } blocks (progression test pattern)
    • Clear documentation explaining the limitation

Test Coverage

The new test covers:

  1. Type member refinement - A { type B = Int } should be subtype of A
  2. Abstract type refinement - C { type D = String } should be subtype of C
  3. Value member refinement - E { val x: Int } should be subtype of E
  4. Def member refinement - F { def method(): String } should be subtype of F
  5. Multiple refinements - G { type H = Int; val y: String } should be subtype of G

Why This Matters

  1. Documentation - Clearly documents the limitation for users
  2. Regression Detection - When someone implements the fix, this test will fail (good!), alerting them to move it to the main suite
  3. Specification - Provides clear specification of expected behavior
  4. Bounty Guidance - Helps contributors understand what needs to be fixed

Related Issues

Notes

As mentioned by maintainers in #481, fixing this limitation requires:

  • Preserving full member information in the type model
  • Design trade-offs around tag size and performance
  • Non-trivial architectural changes

This PR doesn't fix the underlying issue but provides a clear test case that will help guide future implementation efforts.

Testing

The test is designed to fail currently (as expected for a progression test). When run:

sbt test

The test will be skipped/marked as broken, documenting that this feature is not yet supported.

Future Work

When someone implements support for preserving type/value members in concrete types:

  1. This test will start failing (good!)
  2. Remove the broken { } wrappers
  3. Move the test from SharedTagProgressionTest to SharedTagTest
  4. Update README.md to remove limitation Feature/boopickle nomacro #8

Checklist

  • Added comprehensive test coverage
  • Followed progression test pattern (wrapped in broken { })
  • Clear documentation in test comments
  • No breaking changes
  • Helps document known limitation

Add comprehensive test case documenting the known limitation where
subtype relations fail for refined types. This is a progression test
that documents the expected behavior once the limitation is fixed.

The issue occurs because type and value members are not preserved in
concrete types, causing false comparisons when checking if a refined
type is a subtype of its base type.

Example:
  trait A { type B = Int }
  Tag[A { type B = Int }] <:< Tag[A]  // Should be true, currently false

This test will start failing (which is good!) when the feature is
implemented, at which point it should be moved to the main test suite.

Related: zio#481
@neko-kai

Copy link
Copy Markdown
Member

@1234-ad Check the CI failures. Not all of the predicates actually fail as of now. (e.g. ‘E <:E` passes, but the generated check expects it to fail)

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.

Subtype relation for refined type fails

2 participants