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.

        Issue Links

          Activity

          Hide
          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
          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
          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
          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
          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
          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
          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
          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
          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
          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:
              Lukas Rytz
              Reporter:
              Willis Blackburn
            • Votes:
              0 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development