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

Illegal type selection from volatile type null in return type projection

    Details

      Description

      The code below worked in 2.9.2 but not in 2.10.0-M4.
      The return type projection Exp#OpSemExp#Val raises the obscure compile time error "Illegal type selection from volatile type null", so Exp#Val is not seen as a subtype of Exp#OpSemExp#Val anymore. For semantic reasons it is not allowed to remove #Val. It must work like that.

      case class LamExpWaiter(xs: Seq[Idn]) { 
        def apply[Exp <: LazyExp[_]](e: Exp): Exp#OpSemExp#Val = 
          apply_helper(e.asInstanceOf[Exp#OpSemExp]) 
        def apply_helper[Exp <: LazyExp[Exp]](e: Exp): Exp#Val = 
          e.reify_lam(xs, e) 
      } 
      

      This issue seems to be a blocker, because the coder has to go to 2.10 for TypeTag, because there is another problem in which Manifest is too limited.
      see thread http://groups.google.com/group/scala-user/browse_thread/thread/599b99bb2ee9ddd2

      The associated thread of this issue is:
      http://groups.google.com/group/scala-user/browse_thread/thread/ab77f705fe22a246

      I have narrowed the code below. If I narrow it further then I get errors in 2.9.2 too, so this is the minimal representative (I assume, because I don't know if semantically that statement is true, I don't understand this kind of type level programming) and maybe can be used as unit test. However use the project EDSL as regression test, because there might be some other issue connected that can popup and then is useless for the original coder.

      class BaseApp[+Exp <: LazyExp[_]](val e: Exp, val x: String) 
      
      trait AbsVal[+Exp <: LazyExp[_]] 
      
      trait LamReifierBase { 
        def reify_lam[Exp <: LazyExp[Exp]](xs: Seq[String], e: Exp): Exp#Val 
      } 
      
      trait LazyExp[+This <: LazyExp[This]] {
        type OpSemExp <: LazyExp[OpSemExp] with This 
        type Val <: AbsVal[This] with This 
        type App <: BaseApp[This] with This 
      
        protected val lr: LamReifierBase 
        def reify_lam[Thiz >: This](xs: Seq[String], e: Thiz): This#Val = 
          lr.reify_lam(xs, e.asInstanceOf[This]) 
      }
      
      case class LamExpWaiter(xs: Seq[String]) { 
        def apply[Exp <: LazyExp[_]](e: Exp): Exp#OpSemExp#Val = 
          apply_helper(e.asInstanceOf[Exp#OpSemExp]) 
        def apply_helper[Exp <: LazyExp[Exp]](e: Exp): Exp#Val = 
          e.reify_lam(xs, e) 
      }  
      

        Issue Links

          Activity

          Hide
          Mark Harrah added a comment -

          Somewhat related is SI-3443. Relying on two consecutive type projections is probably risky.

          Show
          Mark Harrah added a comment - Somewhat related is SI-3443 . Relying on two consecutive type projections is probably risky.
          Hide
          Jason Zaugg added a comment - - edited

          I believe that the error is accurate. I've improved the error message a little:

          https://github.com/scala/scala/pull/850

          It will now issue:

           t6042.scala:7: error: illegal type selection from volatile type a.OpSemExp (with upper bound LazyExp[a.OpSemExp] with _$1)
          

          The with _$1 part is the reason we can't project the type Val. It corresponds to with This in type alias definition, substituted with a existential skolem.

          Show
          Jason Zaugg added a comment - - edited I believe that the error is accurate. I've improved the error message a little: https://github.com/scala/scala/pull/850 It will now issue: t6042.scala:7: error: illegal type selection from volatile type a.OpSemExp (with upper bound LazyExp[a.OpSemExp] with _$1) The with _$1 part is the reason we can't project the type Val . It corresponds to with This in type alias definition, substituted with a existential skolem.
          Hide
          DaveScala added a comment -

          I indeed found that removing 'with This' in

          type OpSemExp <: LazyExp[OpSemExp] with This
          

          into

          type OpSemExp <: LazyExp[OpSemExp]
          

          did make the error go away and then projecting on Val is possible.
          but it probably means something else.

          But is the type selection volatile because of type erasure?
          Then the workaround would be to put a typetag somewhere.

          Only this

          trait LazyExp[+This <: LazyExp[This]: TypeTag] 
          

          is not allowed.

          scala> trait LazyExp[+This <: LazyExp[This]: TypeTag]
          <console>:1: error: traits cannot have type parameters with context bounds `: ..
          .' nor view bounds `<% ...'
                 trait LazyExp[+This <: LazyExp[This]: TypeTag]
                                                                ^
          

          Probably the type parameter This is volatile because of type erasure.

          Maybe macros?

          Show
          DaveScala added a comment - I indeed found that removing 'with This' in type OpSemExp <: LazyExp[OpSemExp] with This into type OpSemExp <: LazyExp[OpSemExp] did make the error go away and then projecting on Val is possible. but it probably means something else. But is the type selection volatile because of type erasure? Then the workaround would be to put a typetag somewhere. Only this trait LazyExp[+This <: LazyExp[This]: TypeTag] is not allowed. scala> trait LazyExp[+This <: LazyExp[This]: TypeTag] <console>:1: error: traits cannot have type parameters with context bounds `: .. .' nor view bounds `<% ...' trait LazyExp[+This <: LazyExp[This]: TypeTag] ^ Probably the type parameter This is volatile because of type erasure. Maybe macros?
          Hide
          Jason Zaugg added a comment - - edited

          The problem is existential types. Erasure / Type Tags / Manifest are unrelated to this completely – they determine how type information is carried from compile time to runtime; this program doesn't compile at all so that's not relevant.

          Dependent method types might offer a solution here. It would be best to move further discussion to the mailing list.

          (Closed as "not a bug" because the type error is correct, the error message itself was buggy and has been fixed)

          Show
          Jason Zaugg added a comment - - edited The problem is existential types. Erasure / Type Tags / Manifest are unrelated to this completely – they determine how type information is carried from compile time to runtime; this program doesn't compile at all so that's not relevant. Dependent method types might offer a solution here. It would be best to move further discussion to the mailing list. (Closed as "not a bug" because the type error is correct, the error message itself was buggy and has been fixed)
          Hide
          DaveScala added a comment -

          Okay thanks

          Show
          DaveScala added a comment - Okay thanks

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              DaveScala
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development