Details

      Description

      Implicit case classes are broken, because the type of the class and the type of the object are being mixed up:

      
      scala> implicit case class IntOps( i: Int ) {
           |    def twice = i * 2
           | }
      defined class IntOps
      
      scala> 11 : IntOps
      <console>:10: error: ambiguous reference to overloaded definition,
      both method IntOps of type (i: Int)IntOps
      and  object IntOps of type IntOps.type
      match argument types (Int) and expected result type IntOps
                    11 : IntOps
                    ^
      

        Issue Links

          Activity

          Hide
          Paolo G. Giarrusso added a comment -

          Thanks for your explanation, although this situation is somewhat sad. Still, you make clear that the alternatives are no better, especially at this late stage.

          Show
          Paolo G. Giarrusso added a comment - Thanks for your explanation, although this situation is somewhat sad. Still, you make clear that the alternatives are no better, especially at this late stage.
          Hide
          Simon Ochsenreither added a comment -

          I understand that the release shouldn't be delayed over this bug, but I really hope this situation can be addressed with a fix as soon as possible. Loosing case is a pretty hefty price to pay, especially when intending to use it combined with value classes.

          Show
          Simon Ochsenreither added a comment - I understand that the release shouldn't be delayed over this bug, but I really hope this situation can be addressed with a fix as soon as possible. Loosing case is a pretty hefty price to pay, especially when intending to use it combined with value classes.
          Hide
          Paolo G. Giarrusso added a comment - - edited

          On the ML (https://groups.google.com/d/msg/scala-internals/8TrS3ar5LcY/Qg7JEqN7onwJ), this alternative desugaring was mentioned, but I can't find any discussion of its disadvantages ("I remember some kind of issue with the tech. details" is not enough). Note that it works with the current implicit resolution rules (https://gist.github.com/Blaisorblade/6089067).

          object bip {
            class Foo(val xxx: Int)
            implicit object Foo extends (Int => Foo) { def apply(x: Int) = new Foo(x) }
          }
          

          My colleague Tillmann Rendel came up again with this encoding.

          EDIT: So, why don't we use this desugaring?

          Show
          Paolo G. Giarrusso added a comment - - edited On the ML ( https://groups.google.com/d/msg/scala-internals/8TrS3ar5LcY/Qg7JEqN7onwJ ), this alternative desugaring was mentioned, but I can't find any discussion of its disadvantages ("I remember some kind of issue with the tech. details" is not enough). Note that it works with the current implicit resolution rules ( https://gist.github.com/Blaisorblade/6089067 ). object bip { class Foo(val xxx: Int) implicit object Foo extends (Int => Foo) { def apply(x: Int) = new Foo(x) } } My colleague Tillmann Rendel came up again with this encoding. EDIT: So, why don't we use this desugaring?
          Hide
          Jason Zaugg added a comment -

          I don't think that can encode classes with type parameters; function types are not type-polymporhic.

          Show
          Jason Zaugg added a comment - I don't think that can encode classes with type parameters; function types are not type-polymporhic.
          Hide
          Paolo G. Giarrusso added a comment - - edited

          Whoops, agreed. (EDIT: maybe we can avoid using function types - but objects are also not type-polymorphic, and changing that makes no sense).

          And the obvious fixes require using a method instead of a companion object, at least for the implicit conversion (EDIT: which is the original encoding). I can imagine moving unapply to the method instead:

          implicit def Foo = new {
            def apply(x: Int) = new Foo(x)
            def unapply(x: Foo) = ...
          }
          

          but not only this doesn't work nowadays, I'm not even sure it is a good idea, since Foo.unapply could refer to different methods. If that's not a problem, that encoding might be superior, but requires significant changes.

          It seems that the only alternative is that the implicit conversion's name is derived in a documented way from the class name, either only for case classes (which preserves compatibility) or also for other classes (which ensures consistency).

          Show
          Paolo G. Giarrusso added a comment - - edited Whoops, agreed. (EDIT: maybe we can avoid using function types - but objects are also not type-polymorphic, and changing that makes no sense). And the obvious fixes require using a method instead of a companion object, at least for the implicit conversion (EDIT: which is the original encoding). I can imagine moving unapply to the method instead: implicit def Foo = new { def apply(x: Int) = new Foo(x) def unapply(x: Foo) = ... } but not only this doesn't work nowadays, I'm not even sure it is a good idea, since Foo.unapply could refer to different methods. If that's not a problem, that encoding might be superior, but requires significant changes. It seems that the only alternative is that the implicit conversion's name is derived in a documented way from the class name, either only for case classes (which preserves compatibility) or also for other classes (which ensures consistency).

            People

            • Assignee:
              Martin Odersky
              Reporter:
              Daniel Sobral
            • Votes:
              1 Vote for this issue
              Watchers:
              11 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development