Uploaded image for project: 'Scala Programming Language'
  1. Scala Programming Language
  2. SI-4728

"Ambiguous reference to overloaded definition"... not ambiguous to Java, only to Scala

    Details

      Description

      Given

      class X
      class Y extends X
      object Ambiguous {
        def f(x: X) = 1
        def f(ys: Y*) = 2
      }
      

      scala> Ambiguous.f(new X)
      res2: Int = 1
       
      scala> Ambiguous.f(new Y)
      <console>:8: error: ambiguous reference to overloaded definition,
      both method f in object Ambiguous of type (ys: Y*)Int
      and  method f in object Ambiguous of type (x: X)Int
      match argument types (Y)
             Ambiguous.f(new Y)
      

      But the corresponding Java program works compiles:

      edit: as pointed out by andrew (comment below), javac picks the first alternative in both cases.

      public class AmbiguousJ {
          static int f(X x) { return 1; }
          static int f(Y... y) { return 2; }
          public static void main(String[] args) {
              System.out.println(f(new X()));
              System.out.println(f(new Y()));
          }
      }
      

      prints (when running):

      1
      1
      

      (Assuming that X.class and Y.class already exist from compiling the Scala example.)

      This is a PITA because X and Y, in my case, are JPA APIs, which I use a lot.

        Attachments

          Issue Links

            Activity

            Hide
            rytz Lukas Rytz added a comment -

            there is no type T* even as an internal fiction

            Not sure what you mean by that, but the compiler represents T* internally as <repeated>[T], i.e. as an AppliedType.

            Of course the implementation is not part of the specification, but it's certainly one reference point in the cases where the specification is incomplete.

            Show
            rytz Lukas Rytz added a comment - there is no type T* even as an internal fiction Not sure what you mean by that, but the compiler represents T* internally as <repeated> [T] , i.e. as an AppliedType . Of course the implementation is not part of the specification, but it's certainly one reference point in the cases where the specification is incomplete.
            Hide
            apm A. P. Marki added a comment -

            Yes; I meant that the spec doesn't call T* a type, as opposed to =>A, where it does call it a type (albeit not the type of any value).

            It's a bit hard to reason about =>A, witness recent scala-user discussion about whether there is a subtype relation between A and =>A (based on subsitutability). Let alone: isn't =>A just Function0[A]?

            So, it's at least as hard for T*. "T* isAsHardToReasonAbout =>A". Isn't T* just Seq[T]? Really? You're right, maybe the spec should use the language of the compiler and call it a type.

            For the record, my fix for this bug (which I also felt was definitely a bug) was just as Paul said: in this application, the effective type of m is to have k params. In the impl, if both fixed- and vari-arity apply, you know what k is. That is so obvious, it still bugs me.

            Yet it also seems proper that specificity is independent of a particular application. But that may be wrong, because what we're really doing is selecting a member; maybe it's crazy that selection becomes detached from the call used to make the selection. This was also my question around using cbn as a tie-breaker.

            I was making a joke about the syntax f1(bs: B

            {2,}

            ), but the disambiguated syntax means that I can't treat my args as a Seq[B] anymore. That just seems wrong. Is the only lesson to be drawn that overloading is evil?

            I'm not going to sleep well for a while.

            Show
            apm A. P. Marki added a comment - Yes; I meant that the spec doesn't call T* a type, as opposed to =>A, where it does call it a type (albeit not the type of any value). It's a bit hard to reason about =>A, witness recent scala-user discussion about whether there is a subtype relation between A and =>A (based on subsitutability). Let alone: isn't =>A just Function0 [A] ? So, it's at least as hard for T*. "T* isAsHardToReasonAbout =>A". Isn't T* just Seq [T] ? Really? You're right, maybe the spec should use the language of the compiler and call it a type. For the record, my fix for this bug (which I also felt was definitely a bug) was just as Paul said: in this application, the effective type of m is to have k params. In the impl, if both fixed- and vari-arity apply, you know what k is. That is so obvious, it still bugs me. Yet it also seems proper that specificity is independent of a particular application. But that may be wrong, because what we're really doing is selecting a member; maybe it's crazy that selection becomes detached from the call used to make the selection. This was also my question around using cbn as a tie-breaker. I was making a joke about the syntax f1(bs: B {2,} ), but the disambiguated syntax means that I can't treat my args as a Seq [B] anymore. That just seems wrong. Is the only lesson to be drawn that overloading is evil? I'm not going to sleep well for a while.
            Hide
            rytz Lukas Rytz added a comment -

            I agree with all you're saying.

            Yes, it feels unnatural not to fix this bug. Making overloading resolution depend on a particular application is a language change that needs deep discussion and evaluation, so it's out of the scope of this ticket.

            If there are ideas on how to simplify the spec with respect to T* and =>T, I and others would be happy to discuss.

            Show
            rytz Lukas Rytz added a comment - I agree with all you're saying. Yes, it feels unnatural not to fix this bug. Making overloading resolution depend on a particular application is a language change that needs deep discussion and evaluation, so it's out of the scope of this ticket. If there are ideas on how to simplify the spec with respect to T* and =>T , I and others would be happy to discuss.
            Hide
            moors Adriaan Moors added a comment -

            For the record, this now compiles... Both in 2.10.4-RC1 and (almost) 2.11.0-RC1. See also: SI-8197.

            Show
            moors Adriaan Moors added a comment - For the record, this now compiles... Both in 2.10.4-RC1 and (almost) 2.11.0-RC1. See also: SI-8197 .
            Hide
            rytz Lukas Rytz added a comment -

            I just tested 2.10.4-RC2, there it doesn't compile (as expected). Also 2.11 is OK. Test case in https://github.com/scala/scala/pull/3585

            Show
            rytz Lukas Rytz added a comment - I just tested 2.10.4-RC2, there it doesn't compile (as expected). Also 2.11 is OK. Test case in https://github.com/scala/scala/pull/3585

              People

              • Assignee:
                rytz Lukas Rytz
                Reporter:
                willisblackburn Willis Blackburn
              • Votes:
                0 Vote for this issue
                Watchers:
                7 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: