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

report error when using wildcard for top-level type parameter name

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: Scala 2.9.1
    • Fix Version/s: Backlog
    • Component/s: Type Checker
    • Labels:

      Description

      I am able to crash the compiler with the following code:

      object TestModel {
      }
       
      case class CaseTest[_](someData:String)
      

      The error is the following:

       java.lang.AssertionError: assertion failed: transformCaseApply: name = _! tree = _ / class scala.reflect.generic.Trees$Ident
      at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer$$anonfun$2.apply$mcV$sp(RefChecks.scala:1493)
      at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformCaseApply(RefChecks.scala:1309)
      etc..
      

      (I really hope I was supposed to issue this as a bug, first time ever I do this kind of thing. If I shouldnt, I am very sorry for the inconvenience)

        Attachments

          Activity

          Hide
          moors Adriaan Moors added a comment -

          thanks for reporting! yes, that should give a clean error instead of crashing

          Show
          moors Adriaan Moors added a comment - thanks for reporting! yes, that should give a clean error instead of crashing
          Hide
          moors Adriaan Moors added a comment -

          this should give a parse error

          Show
          moors Adriaan Moors added a comment - this should give a parse error
          Hide
          extempore Paul Phillips added a comment -

          Interesting what happens when one tries to disallow it. (It's clearly a bug it was allowed - try using a second "wildcard" and it fails.)

          [scalacfork] /scratch/trunk1/src/library/scala/collection/immutable/RedBlackTree.scala:88: error: identifier expected but '_' found.
          [scalacfork]   def keysIterator[A, _](tree: Tree[A, _]): Iterator[A] = new KeysIterator(tree)
          [scalacfork]                       ^
          [scalacfork] /scratch/trunk1/src/library/scala/collection/immutable/RedBlackTree.scala:89: error: ']' expected but ';' found.
          [scalacfork]   def valuesIterator[_, B](tree: Tree[_, B]): Iterator[B] = new ValuesIterator(tree)
          [scalacfork] ^
          [scalacfork] /scratch/trunk1/src/library/scala/collection/immutable/RedBlackTree.scala:89: error: identifier expected but '_' found.
          [scalacfork]   def valuesIterator[_, B](tree: Tree[_, B]): Iterator[B] = new ValuesIterator(tree)
          [scalacfork]                      ^
          

          Show
          extempore Paul Phillips added a comment - Interesting what happens when one tries to disallow it. (It's clearly a bug it was allowed - try using a second "wildcard" and it fails.) [scalacfork] /scratch/trunk1/src/library/scala/collection/immutable/RedBlackTree.scala:88: error: identifier expected but '_' found. [scalacfork] def keysIterator[A, _](tree: Tree[A, _]): Iterator[A] = new KeysIterator(tree) [scalacfork] ^ [scalacfork] /scratch/trunk1/src/library/scala/collection/immutable/RedBlackTree.scala:89: error: ']' expected but ';' found. [scalacfork] def valuesIterator[_, B](tree: Tree[_, B]): Iterator[B] = new ValuesIterator(tree) [scalacfork] ^ [scalacfork] /scratch/trunk1/src/library/scala/collection/immutable/RedBlackTree.scala:89: error: identifier expected but '_' found. [scalacfork] def valuesIterator[_, B](tree: Tree[_, B]): Iterator[B] = new ValuesIterator(tree) [scalacfork] ^
          Hide
          apm A. P. Marki added a comment -

          This is degenerate, but ought it to be illegal?

          In the real world, there are many behaviors that are degenerate but not illegal, or no longer illegal, except in certain states of the Union where they frown on that sort of thing. (For instance, buying beer on Sunday.)

          I took a quick look, and the example CaseTest[_] fails in the "copy" method but not in the companion module factory method, which are not exactly the same for some reason. The error is the wildcard in the new expr. (-Xprint:typer shows new pkg.this.CaseTest[_](data) versus new pkg.CaseTest[Any](data).) So this comes close to passing under the radar.

          The spec says that the motivation for the shorthand A[_] is visibility and relevance.

          One use case for top-level _, in quick test code, is to stub some UserKlass[This, That, Other] as class UserKlass[_,_,_].

          I have to come up with symbols? Couldn't the compiler just make me a symbol? So I don't have to remember if we prefer A,B,C or T,U,V? This goes to relevance. And it depletes my decision-making budget.

          Another use case is where a type param is deprecated because improvements in type inference make it superfluous.
          trait T[@deprecated("I'm free","2.11") _, B <: S[_]]
          Then, hypothetically, one could warn on usage of T[X, Y] but not T[_, Y].

          Just thinking aloud.

          Show
          apm A. P. Marki added a comment - This is degenerate, but ought it to be illegal? In the real world, there are many behaviors that are degenerate but not illegal, or no longer illegal, except in certain states of the Union where they frown on that sort of thing. (For instance, buying beer on Sunday.) I took a quick look, and the example CaseTest [_] fails in the "copy" method but not in the companion module factory method, which are not exactly the same for some reason. The error is the wildcard in the new expr. (-Xprint:typer shows new pkg.this.CaseTest [_] (data) versus new pkg.CaseTest [Any] (data).) So this comes close to passing under the radar. The spec says that the motivation for the shorthand A [_] is visibility and relevance. One use case for top-level _, in quick test code, is to stub some UserKlass [This, That, Other] as class UserKlass [_,_,_] . I have to come up with symbols? Couldn't the compiler just make me a symbol? So I don't have to remember if we prefer A,B,C or T,U,V? This goes to relevance. And it depletes my decision-making budget. Another use case is where a type param is deprecated because improvements in type inference make it superfluous. trait T[@deprecated("I'm free","2.11") _, B <: S [_] ] Then, hypothetically, one could warn on usage of T [X, Y] but not T [_, Y] . Just thinking aloud.
          Hide
          extempore Paul Phillips added a comment -

          It could be allowed to work; my point is that it would be better for it not to work at all than for it to accidentally work for the one-type-parameter case only.

          Show
          extempore Paul Phillips added a comment - It could be allowed to work; my point is that it would be better for it not to work at all than for it to accidentally work for the one-type-parameter case only.
          Hide
          retronym Jason Zaugg added a comment -

          The failure mode changed in 2.10.0. In https://github.com/scala/scala/pull/826, the return type of the synthetic copy method was inferred, rather than explicitly provided. If the type parameter is named _, it is inferred as CaseClass[Any].

          ~/code/scala2 scala210
          Welcome to Scala version 2.10.0-20121024-085118-2c554249fd (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_27).
          Type in expressions to have them evaluated.
          Type :help for more information.
           
          scala> case class CaseTest[_](someData:String)
          defined class CaseTest
           
          scala> new CaseTest[Int]("").copy()
          res0: CaseTest[Any] = CaseTest()
           
          scala> case class CaseTest[A](someData:String)
          defined class CaseTest
           
          scala> new CaseTest[Int]("").copy()
          res1: CaseTest[Nothing] = CaseTest()
           
          scala> case class CaseTest[_](someData:String)
          defined class CaseTest
           
          scala> new CaseTest[Int]("").copy[Int]()
          res2: CaseTest[Any] = CaseTest()
           
          scala> case class CaseTest[A](someData:String)
          defined class CaseTest
           
          scala> new CaseTest[Int]("").copy[Int]()
          res3: CaseTest[Int] = CaseTest()
           
          scala> case class CaseTest[_](someData:String)
          defined class CaseTest
           
          scala> val x = CaseTest[Int]("")
          x: CaseTest[Any] = CaseTest()
           
          scala> x.copy
                                                         def copy[_](someData: String): CaseTest[Any]  
          

          I figured I'd be able to trip up Value Classes with this, but while we can generate some funny looking signatures, they seem to go unnoticed.

          scala> class CCC[_](val value: String) extends AnyVal { def foo[_]: Option[`_`] = None }
          ...
                    final def foo$extension[_ >: Nothing <: Any, _ >: Nothing <: Any]($this: CCC[_]): Option[Any] = scala.None;
          

          That sort of signature comes up without the _, of course, but seems to be innocuous as everything is symful by that stage.

          scala> class C[A](val value: String) extends AnyVal { def foo[A] = this }
          ...
                    final def foo$extension[A >: Nothing <: Any, A >: Nothing <: Any]($this: C[A]): C[A] = $this;
          

          Show
          retronym Jason Zaugg added a comment - The failure mode changed in 2.10.0. In https://github.com/scala/scala/pull/826 , the return type of the synthetic copy method was inferred, rather than explicitly provided. If the type parameter is named _ , it is inferred as CaseClass [Any] . ~/code/scala2 scala210 Welcome to Scala version 2.10.0-20121024-085118-2c554249fd (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_27). Type in expressions to have them evaluated. Type :help for more information.   scala> case class CaseTest[_](someData:String) defined class CaseTest   scala> new CaseTest[Int]("").copy() res0: CaseTest[Any] = CaseTest()   scala> case class CaseTest[A](someData:String) defined class CaseTest   scala> new CaseTest[Int]("").copy() res1: CaseTest[Nothing] = CaseTest()   scala> case class CaseTest[_](someData:String) defined class CaseTest   scala> new CaseTest[Int]("").copy[Int]() res2: CaseTest[Any] = CaseTest()   scala> case class CaseTest[A](someData:String) defined class CaseTest   scala> new CaseTest[Int]("").copy[Int]() res3: CaseTest[Int] = CaseTest()   scala> case class CaseTest[_](someData:String) defined class CaseTest   scala> val x = CaseTest[Int]("") x: CaseTest[Any] = CaseTest()   scala> x.copy def copy[_](someData: String): CaseTest[Any] I figured I'd be able to trip up Value Classes with this, but while we can generate some funny looking signatures, they seem to go unnoticed. scala> class CCC[_](val value: String) extends AnyVal { def foo[_]: Option[`_`] = None } ... final def foo$extension[_ >: Nothing <: Any, _ >: Nothing <: Any]($this: CCC[_]): Option[Any] = scala.None; That sort of signature comes up without the _, of course, but seems to be innocuous as everything is symful by that stage. scala> class C[A](val value: String) extends AnyVal { def foo[A] = this } ... final def foo$extension[A >: Nothing <: Any, A >: Nothing <: Any]($this: C[A]): C[A] = $this;
          Hide
          jamesiry James Iry added a comment -

          2.10.2 is about to be cut. Kicking down the road and un-assigning to foster work stealing.

          Show
          jamesiry James Iry added a comment - 2.10.2 is about to be cut. Kicking down the road and un-assigning to foster work stealing.
          Hide
          jamesiry James Iry added a comment -

          2.10.2 is about to be cut. Kicking down the road and un-assigning to foster work stealing.

          Show
          jamesiry James Iry added a comment - 2.10.2 is about to be cut. Kicking down the road and un-assigning to foster work stealing.

            People

            • Assignee:
              Unassigned
              Reporter:
              whiteancient Jonas Ohlsson
            • Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated: