Skip to content

cast fail when have HK-type unreducted, but equal expression as type. #9518

Closed
@rssh

Description

@rssh

Minimized code

X.scala:

package x

import scala.quoted._


trait CB[T]

trait M[F[_]] {
   def pure[T](x:T):F[T]
}

object MCB extends M[CB] {
   def pure[T](x:T):CB[T] = ???
}

given M[CB] = MCB

object X {

 inline def shift[F[_],A,B](inline f: PartialFunction[A,B] )(using M[F]) : A => F[B] = ${
   shiftImpl[F,A,B]('f)
 }


 def shiftImpl[F[_]:Type,A:Type, B:Type](f:Expr[PartialFunction[A,B]])(using qctx: QuoteContext):Expr[A => F[B]] = {
   import qctx.tasty._
   shiftTerm[F,A,B](using qctx)(f.unseal)
 }

 def shiftTerm[F[_]:Type,A:Type, B:Type](using qctx: QuoteContext)(f:qctx.tasty.Term):Expr[A => F[B]] = {
   import qctx.tasty._

   def castTerm[T](x:Term, xt: quoted.Type[T]):Expr[T] =
        given quoted.Type[T] = xt
        x.seal.cast[T]

   def unAnnotate(x:Type):Type =
     x match
       case AnnotatedType(tp,_) => tp
       case _ => x

   val mcb = Expr.summon[M[F]].get.unseal
   val fTypeTree = summon[quoted.Type[F]].unseal
   val partialFunctionType = TypeIdent(Symbol.classSymbol("scala.PartialFunction")).tpe

   f match
      case Lambda(params, Match(scr,caseDefs)) =>
        unAnnotate(f.tpe) match
           case AppliedType(tp,tparams) =>
             if (tp <:< partialFunctionType)
                val (tInBounds, tOutBounds) = tparams match
                   case tIn::tOut::Nil => (tIn, tOut)
                   case _ => ???
                val tIn = tInBounds match
                   case TypeBounds(lo,hi) => hi
                   case tpIn: Type => tpIn
                val tOutInMonad = AppliedType(fTypeTree.tpe, List(tOutBounds))
                (tIn.seal, tOutInMonad.seal) match
                  case ( '[$nt], '[$tt] ) =>
                     val f1 = '{ (v: $nt) => ${
                        val nTree = Match(scr, caseDefs.map( x =>
                                             CaseDef(x.pattern, x.guard,
                                               Apply(
                                                TypeApply(Select.unique(mcb,"pure"),List(Inferred(x.rhs.tpe))),
                                                List(x.rhs))
                                          )                )
                                    )
                        println(s"beforeCast, tt = ${tt.unseal}, tree.tpe=${nTree.tpe}")
                        val r = castTerm(nTree, tt)
                        println("afterCast")
                        r
                        }
                     }
                     // in real world A and B is not accessible here
                     f1.cast[A => F[B]]
             else
                println(s"partialFunction was expected, we have ${f.tpe}")
                ???
      case Inlined(_,List(),x) => shiftTerm[F,A,B](using qctx)(x)


      case _ => println(s"Lambda was expected, we have ${f}")
                ???
  }
}

and
Main.scala

package x


object Main {

 X.shift[CB,Int,Int]({ case x if x > 1 => x+10 })

}

Output

info] welcome to sbt 1.3.13 (N/A Java 14.0.1)
[info] loading settings for project cast1-build from plugins.sbt ...
[info] loading project definition from /Users/rssh/tests/dotty/cast1/project
Fetching latest Dotty nightly version...
Latest Dotty nightly build version: 0.27.0-bin-20200807-dfcc0b1-NIGHTLY
[info] loading settings for project root from build.sbt ...
[info] set current project to test (in build file:/Users/rssh/tests/dotty/cast1/)
[info] Compiling 2 Scala sources to /Users/rssh/tests/dotty/cast1/target/scala-0.27/classes ...
beforeCast, tt = TypeTree[AppliedType(HKTypeLambda(List(T), List(TypeBounds(TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Nothing),TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Any))), AppliedType(TypeRef(ThisType(TypeRef(NoPrefix,module class x)),trait CB),List(TypeParamRef(T)))),List(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),module scala),class Int)))], tree.tpe=AppliedType(TypeRef(ThisType(TypeRef(NoPrefix,module class x)),trait CB),List(TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Int)))
[error] -- Error: /Users/rssh/tests/dotty/cast1/src/main/scala/x/Main.scala:6:1 --------
[error] 6 | X.shift[CB,Int,Int]({ case x if x > 1 => x+10 })
[error]   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]   |Exception occurred while executing macro expansion.
[error]   |scala.tasty.reflect.ExprCastError: Expr: (x$1: @scala.unchecked) match {
[error]   |  case x if x.>(1) =>
[error]   |    x.given_M_CB.pure[scala.Int](x.+(10))
[error]   |}
[error]   |did not conform to type: ([T >: scala.Nothing <: scala.Any] => x.CB[T])[scala.Int]
[error]   |
[error]   |	at scala.quoted.Expr.cast(Expr.scala:52)
[error]   |	at x.X$.castTerm$1(X.scala:37)
[error]   |	at x.X$.$anonfun$9$2$$anonfun$1(X.scala:71)
[error]   |	at dotty.tools.dotc.core.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:84)
[error]   |	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1306)
[error]   |	at dotty.tools.dotc.core.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:108)
[error]   |	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1286)
[error]   |	at dotty.tools.dotc.core.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:108)
[error]   |	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1345)
[error]   |	at dotty.tools.dotc.core.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:108)
[error]   |	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform$$anonfun$2(Trees.scala:1371)
[error]   |	at scala.collection.immutable.List.mapConserve(List.scala:472)
[error]   |	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1371)
[error]   |	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transformStats(Trees.scala:1369)
[error]   |	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1286)
[error]   |	at dotty.tools.dotc.core.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:108)
[error]   |	at dotty.tools.dotc.core.quoted.PickledQuotes$.spliceTerms(PickledQuotes.scala:123)
[error]   |	at dotty.tools.dotc.core.quoted.PickledQuotes$.unpickleExpr(PickledQuotes.scala:61)
[error]   |	at dotty.tools.dotc.tastyreflect.ReflectionCompilerInterface.unpickleExpr(ReflectionCompilerInterface.scala:40)
[error]   |	at dotty.tools.dotc.tastyreflect.ReflectionCompilerInterface.unpickleExpr(ReflectionCompilerInterface.scala:39)
[error]   |	at scala.internal.quoted.Unpickler$.unpickleExpr(Unpickler.scala:16)
[error]   |	at x.X$.shiftTerm(X.scala:62)
[error]   |	at x.X$.shiftImpl(X.scala:29)
[error]   |
[error]   | This location contains code that was inlined from Main.scala:6
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 4 s, completed 8 Aug 2020, 14:16:44

Expectation

should compiled

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions