Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: Scala 2.10.0
    • Component/s: Misc Compiler
    • Labels:
      None

      Description

      The following two programs should both give ambiguity errors, but only the first one does:

      package object foo {
        implicit val x: Bippy = new Bippy("x")
      }
      package foo {
        class Bippy(override val toString: String) { }
        class Dingus {
          implicit val z: Bippy = new Bippy("z")
          def f1 = implicitly[Bippy]
        }
      }
      

      This one compiles without error, but shouldn't:

      package object foo {
        implicit val x: Bippy = new Bippy("x")
      }
      package foo {
        class Bippy(override val toString: String){ }
        class Dingus {
          def f1 = {
            implicit val z: Bippy = new Bippy("z")
            implicitly[Bippy]
          }
        }
      

        Activity

        Hide
        Martin Odersky added a comment -

        I think I have isolated the reason. Overloading resolution prefers values x over parameterless method accessors x. In the first case, we have two implicits as fields, and both are accessed with parameterless method accessors. So ambiguity results. In the second case, the local variable is treated as more specific in overloading resolution. This is not justified by the spec, which treats fields and parameterless methods the same. But changing it might break existing code, so we have to tread carefully here.

        Show
        Martin Odersky added a comment - I think I have isolated the reason. Overloading resolution prefers values x over parameterless method accessors x. In the first case, we have two implicits as fields, and both are accessed with parameterless method accessors. So ambiguity results. In the second case, the local variable is treated as more specific in overloading resolution. This is not justified by the spec, which treats fields and parameterless methods the same. But changing it might break existing code, so we have to tread carefully here.
        Hide
        Martin Odersky added a comment -

        Turns out my previous reasoning was completely incorrect. The compiler does indeed treat values and parameterless methods the same, just as the spec demands. The reason why the second example slipped through is considerably more devious: When checking the `Foo.x' implicit, a CyclicReference error occurs which causes the alternative to be discarded. Why a CylicReference? Because the inferencer tries to decide whether the owner of `z` is a subclass of the owner od `x`. To do this, it computed the info of the owner of `z1`, which is not complete because no result type for `f1` was given. Hence a CyclicReference error.

        The fix is twofold: (1) We make isNonBottomSubClass smarter so that it always returns false if the symbol in question is not a type; hence the info need not be computed. (2) It's dubious to swallow CyclicReference errors anywhere, but I deemed it too risky to propagate them. But at least the CyclicReference is now logged if -Ylog-implicit is true. This hopefully spares future maintainers the same detective work I had to go through when digging this out.

        Leaving for Paul to close once pull request is accepted.

        Show
        Martin Odersky added a comment - Turns out my previous reasoning was completely incorrect. The compiler does indeed treat values and parameterless methods the same, just as the spec demands. The reason why the second example slipped through is considerably more devious: When checking the `Foo.x' implicit, a CyclicReference error occurs which causes the alternative to be discarded. Why a CylicReference? Because the inferencer tries to decide whether the owner of `z` is a subclass of the owner od `x`. To do this, it computed the info of the owner of `z1`, which is not complete because no result type for `f1` was given. Hence a CyclicReference error. The fix is twofold: (1) We make isNonBottomSubClass smarter so that it always returns false if the symbol in question is not a type; hence the info need not be computed. (2) It's dubious to swallow CyclicReference errors anywhere, but I deemed it too risky to propagate them. But at least the CyclicReference is now logged if -Ylog-implicit is true. This hopefully spares future maintainers the same detective work I had to go through when digging this out. Leaving for Paul to close once pull request is accepted.
        Hide
        Paul Phillips added a comment -

        Merged in 6975b4888d.

        Show
        Paul Phillips added a comment - Merged in 6975b4888d.
        Hide
        Jason Zaugg added a comment -

        This also fixed a similar problem in a different manner:

        http://stackoverflow.com/questions/10763511/implicit-resolution-in-scala-2-10-x-whats-going-on

        2.9.2 considered <local Test> as a subclass of <none>.

        Show
        Jason Zaugg added a comment - This also fixed a similar problem in a different manner: http://stackoverflow.com/questions/10763511/implicit-resolution-in-scala-2-10-x-whats-going-on 2.9.2 considered <local Test> as a subclass of <none> .

          People

          • Assignee:
            Martin Odersky
            Reporter:
            Martin Odersky
          • Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development