Skip to content

Value classes' public val field introduce unnecessary collisions #2514

@kailuowang

Description

@kailuowang

In Scala 2.10 the underlying value field in a value class has to be public,
For example

final class EitherIdOpsBinCompat0[A](val value: A) extends AnyVal

In this particular case, it introduced a value val to all types that simply returns itself. There is no real use case for this it's only due to the limitation of value classes in 2.10. It collides with any implicit extension that adds a value too. See #2491 for detail in this case.
This limitation is removed since Scala 2.11. And Cats dropped support for 2.10 since 1.3.

I thought of two approaches that can fix this.

Option 1: make the existing implicit conversion and value class EitherIdOpsBinCompat0 package private and deprecated; copy the value class EitherIdOpsBinCompat0 and paste it as a new value class with its value private and new implicit conversion for it. We also need a new EitherSyntaxBinCompat1 trait for maintaining BC on Scala 2.11.
I believe that this would be binary compatible and hide the value field going forward, but I haven't tested it yet. The downside is, of course, the duplicated code and more boilerplate. Also if we want to use the syntax inside the package we will run into collision.

Option 2: make the value field private. It seems to me that unless user calls the value field which has no practical usage, user won't run into binary compatibility issue. This can be verified by adding a "232". leftNec[Int] line to the BC test added by #2509 (not merged yet) . We would also need to add a MiMa exception for this field.

What do you guys think?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions