Details

      Description

      === What steps will reproduce the problem (please be specific and use wikiformatting)? ===

      File1.scala

      package other {
        trait LowPriImplicits {
          implicit def lstr2int(x : String) = {
            Console.println("ZOMG")
            x.toInt
          }
        }
        trait MyImplicits {
           implicit def str2int(x : String) = x.toInt
        }
      }
      
      package object test extends other.MyImplicits {}
      
      

      File2.scala

      package test;
      
      object Foo {
        def str2int = null
        def test : Int = "5"
      }
      

      Then when running scalac File1.scala File2.scala things compile successfully.

      === What is the expected behavior? ===
      From what I understand from reading the SLS, implicits are only applicable if they can be accessed on the current scope without any prefix. Shadowing should prevent them from being used in the current scope, however it appears that only implicits can shadow implicits.

      When changing file2 to the following:

      package test;
      
      object Foo {
        implicit def str2int = null
        def test : Int = "5"
      }
      

      Now when running scalac:

      jsuereth@jsuereth-laptop:~/projects/tmp/fun$$ scalac *.scala
      File2.scala:5: error: type mismatch;
       found   : java.lang.String("5")
       required: Int
        def test : Int = "5"
                         ^
      one error found
      

      === What do you see instead? ===
      Things successfully compile and they should not (according to spec).

      === Additional information ===
      SLS 7.2 states:

      "First, eligible are all identifiers x that can be accessed at
      the point of the method call without a prefix and that denote an implicit definition
      (�7.1) or an implicit parameter"

      The implicit lookup rules appear to be filtering the available scope such that only implicit bindings can shadow each other.

      === What versions of the following are you using? ===

      • Scala: 2.8.1
      • Java: 1.6.0_20
      • Operating system: Ubuntu

        Issue Links

          Activity

          Hide
          Martin Odersky added a comment -

          Both str2int's are accessible as overloaded variants. So I so not see a diff between the spec and the compiler.

          Show
          Martin Odersky added a comment - Both str2int's are accessible as overloaded variants. So I so not see a diff between the spec and the compiler.
          Hide
          Mark Harrah added a comment -

          I think this is a valid bug. It looks like the same kind of problem as SI-3453. (I'm not sure why !LowPriImplicits is in Josh's example, since it isn't used.)

          As a simpler example:

          object MyImplicits {
            implicit def str2int(x : String) = x.toInt
          }
          import MyImplicits._
          object Foo {
            def str2int = null
            def test : Int = "5"
          }
          

          This compiles, although it should not. The implicit str2int is not accessible without a prefix because the wildcard import is shadowed by the local definition. If str2int is made implicit, scalac correctly generates an error.

          Show
          Mark Harrah added a comment - I think this is a valid bug. It looks like the same kind of problem as SI-3453 . (I'm not sure why !LowPriImplicits is in Josh's example, since it isn't used.) As a simpler example: object MyImplicits { implicit def str2int(x : String) = x.toInt } import MyImplicits._ object Foo { def str2int = null def test : Int = "5" } This compiles, although it should not. The implicit str2int is not accessible without a prefix because the wildcard import is shadowed by the local definition. If str2int is made implicit, scalac correctly generates an error.
          Hide
          Paul Phillips added a comment -

          I stumbled across this through luck. Courage of your convictions there, buddy. I agree, I don't see how the example mark gives can be anything but bug.

          Show
          Paul Phillips added a comment - I stumbled across this through luck. Courage of your convictions there, buddy. I agree, I don't see how the example mark gives can be anything but bug.
          Hide
          Adriaan Moors added a comment -

          related to SI-3453 – `nonImplicitSynonymInScope` probably needs to be improved to consider imports

          Show
          Adriaan Moors added a comment - related to SI-3453 – `nonImplicitSynonymInScope` probably needs to be improved to consider imports
          Hide
          Jason Zaugg added a comment -

          Another example where this isn't working. The context.scope checked by nonImplicitSynonymInScope doesn't contain the template member x.

          object Test1 {
            object A { implicit val x: Int = 1 }
            import A.x
            def x: Int = 0
            implicitly[Int]
          }
          

          By contrast, this does shadow:

          object Test2 {
            object A { implicit val x: Int = 1 }
            
            {
              import A.x
              def x: Int = 0
              implicitly[Int]
            }
          }
          
          Show
          Jason Zaugg added a comment - Another example where this isn't working. The context.scope checked by nonImplicitSynonymInScope doesn't contain the template member x . object Test1 { object A { implicit val x: Int = 1 } import A.x def x: Int = 0 implicitly[Int] } By contrast, this does shadow: object Test2 { object A { implicit val x: Int = 1 } { import A.x def x: Int = 0 implicitly[Int] } }
          Hide
          Jason Zaugg added a comment -

          Test cases for this bug should also exercise renamed imports – examples in the test cases for SI-2405.

          Show
          Jason Zaugg added a comment - Test cases for this bug should also exercise renamed imports – examples in the test cases for SI-2405 .
          Hide
          Jason Zaugg added a comment -
          Show
          Jason Zaugg added a comment - I've got a fix in the works: https://github.com/retronym/scala/compare/ticket/4270
          Hide
          Jason Zaugg added a comment -
          Show
          Jason Zaugg added a comment - Merged in https://github.com/scala/scala/commit/736f622f7
          Hide
          Oleg Aleshko added a comment -

          in general implicit method names do not matter, unless they are accidentally ambiguous
          the error message generated by compiler if implicit is shadowed makes it really hard to understand what's going on
          it just says that e.g. a method provided by conversion is not found, no clue about why conversion does not kick in

          Show
          Oleg Aleshko added a comment - in general implicit method names do not matter, unless they are accidentally ambiguous the error message generated by compiler if implicit is shadowed makes it really hard to understand what's going on it just says that e.g. a method provided by conversion is not found, no clue about why conversion does not kick in

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              Josh Suereth
              TracCC:
              Mark Harrah, Paul Phillips
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development