scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.8k stars 1.04k forks source link

Cannot use `derives` when typeclasses have the same name #17328

Open kyri-petrou opened 1 year ago

kyri-petrou commented 1 year ago

Compiler version

3.2.2, 3.3.0-RC4

Minimized code

trait Foo[A]
object Foo:
  trait Codec[A] extends Foo[A]
  object Codec:
    inline def derived[A]: Codec[A] = ???
end Foo

trait Bar[A]
object Bar:
  trait Codec[A] extends Bar[A]
  object Codec:
    inline def derived[A]: Codec[A] = ???
end Bar

final case class FooBar() derives Foo.Codec, Bar.Codec

Output

The code above fails to compile with the following error:

[error] 15 |final case class FooBar() derives Foo.Codec, Bar.Codec
[error]    |                                             ^^^^^^^^^
[error]    |                               duplicate type class derivation for Codec

Expectation

I'm not sure if this is a bug or the intended operation. A workaround is to alias one of the Codecs. e.g., the following works:

type BarCodec[A] = Bar.Codec[A]
final case class FooBar() derives Foo.Codec, BarCodec

If this is the intended operation, would it make sense for the compiler to auto-generate the alias, or if that's not possible, provide the workaround in the error description?

OlegYch commented 6 months ago

same on 3.3.1

nicolasstucki commented 6 months ago

Workaround

- final case class FooBar() derives Foo.Codec, Bar.Codec
+ final case class FooBar()

+ object FooBar:
+   given FooCodec: Foo.Codec[FooBar] = Foo.Codec.derived
+   given BarCodec: Bar.Codec[FooBar] = Bar.Codec.derived
nicolasstucki commented 6 months ago

We have a similar issue with

object FooBar:
  given Foo.Codec[FooBar] = Foo.Codec.derived
  given Bar.Codec[FooBar] = Bar.Codec.derived
nicolasstucki commented 6 months ago

This is part of the current spec. It is a consequence of the names we choose when desugaring. We can't change the generated names without breaking binary compatibility. To make this work we would need a change in the spec with a good migration path.