Scala Programming Language
  1. Scala Programming Language
  2. SI-6155

Typechecking of a macro expansion infers wrong type for List.map

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: Scala 2.10.0, Scala 2.11.0
    • Fix Version/s: Scala 2.12.0
    • Component/s: Macros, Type Checker
    • Labels:
      None

      Description

      As per http://stackoverflow.com/questions/11681631/macro-return-type-and-higher-order-functions:

      Macro definition:

      def test(s:String) = macro testImpl
      
      def testImpl(c:Context)(s:c.Expr[String]):c.Expr[Any] = {
        import c.universe._
        val list = reify(List(1)).tree
      
        val function = reify((x:Int) => x).tree
      
        val res = 
          Apply(
            Select(
              list,
              newTermName("map")),
            List(function)
          )
      
        c.Expr(res)
      }
      

      Macro call:

      val list:List[Int] = test("")
      

      Error message:

      [error]  found   : Any
      [error]  required: List[Int]
      [error]     val list:List[Int] = test("")
      [error]                              ^
      

        Issue Links

          Activity

          Show
          Eugene Burmako added a comment - Related: http://stackoverflow.com/questions/13669974/static-return-type-of-scala-macros .
          Hide
          Eugene Burmako added a comment -

          Let's keep this one in mind for 2.12, especially given the progress made by quasiquote implementation macros.

          Show
          Eugene Burmako added a comment - Let's keep this one in mind for 2.12, especially given the progress made by quasiquote implementation macros.
          Hide
          Paul Phillips added a comment -

          For another fascinating wrinkle, see https://github.com/puffnfresh/wartremover/pull/46 .

          class A {
            def f1 = Vector(1,2,3) == List(1).map(_ + 1)
            def f2 = Vector(1,2,3) equals List(1).map(_ + 1)
          }
          

          The first map call infers List[Int] for the type argument, the second infers Any. Since I had already observed that arguments to overloaded targets are typed more accurately than arguments to not-overloaded targets, I looked and indeed 'def ==' is overloaded between Any and AnyRef whereas 'def equals' is overridden in AnyRef.

          Show
          Paul Phillips added a comment - For another fascinating wrinkle, see https://github.com/puffnfresh/wartremover/pull/46 . class A { def f1 = Vector(1,2,3) == List(1).map(_ + 1) def f2 = Vector(1,2,3) equals List(1).map(_ + 1) } The first map call infers List [Int] for the type argument, the second infers Any. Since I had already observed that arguments to overloaded targets are typed more accurately than arguments to not-overloaded targets, I looked and indeed 'def ==' is overloaded between Any and AnyRef whereas 'def equals' is overridden in AnyRef.
          Hide
          Jason Zaugg added a comment -

          Funny, I noticed that overloading a few days back in SI-8219.

          Show
          Jason Zaugg added a comment - Funny, I noticed that overloading a few days back in SI-8219 .
          Hide
          Jason Zaugg added a comment -

          I've diagnosed the unwanted overloading in https://github.com/scala/scala/pull/3460

          `AnyRef` and `Object` don't fit into traditional binary notions of `isJava`.

          Show
          Jason Zaugg added a comment - I've diagnosed the unwanted overloading in https://github.com/scala/scala/pull/3460 `AnyRef` and `Object` don't fit into traditional binary notions of `isJava`.

            People

            • Assignee:
              Eugene Burmako
              Reporter:
              Eugene Burmako
            • Votes:
              1 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

              • Created:
                Updated:

                Development