Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rssh opened this issue Aug 8, 2020 · 2 comments · Fixed by #9699
Closed

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

rssh opened this issue Aug 8, 2020 · 2 comments · Fixed by #9699
Milestone

Comments

@rssh
Copy link
Contributor

rssh commented Aug 8, 2020

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

@rssh rssh added the itype:bug label Aug 8, 2020
@rssh
Copy link
Contributor Author

rssh commented Aug 8, 2020

cast1.tar.gz

full sbt projet

@nicolasstucki
Copy link
Contributor

nicolasstucki commented Sep 1, 2020

Minimized

import scala.quoted._

trait CB[T]

inline def shift : Unit = ${ shiftTerm }

def shiftTerm(using QuoteContext): Expr[Unit] = {
  import qctx.tasty._
  val nTree = '{ ??? : CB[Int] }.unseal
  val tp1 = '[CB[Int]].unseal.tpe
  val tp2 = '[([X] =>> CB[X])[Int]].unseal.tpe
  val ta = '[[X] =>> CB[X]]
  val tp3 = '[ta.T[Int]].unseal.tpe
  val tp4 = AppliedType('[CB].unseal.tpe, List(typeOf[Int]))
  assert(nTree.tpe <:< tp1)
  assert(nTree.tpe <:< tp2)
  assert(nTree.tpe <:< tp3)
  assert(nTree.tpe <:< tp4) // fails but should not
  '{}
}
def test: Unit = shift

nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Sep 1, 2020
@nicolasstucki nicolasstucki linked a pull request Sep 1, 2020 that will close this issue
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Sep 2, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Sep 2, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Sep 2, 2020
nicolasstucki added a commit that referenced this issue Sep 3, 2020
Fix #9518: Instantiate HKTypeLambda in AppliedTypes
@Kordyjan Kordyjan added this to the 3.0.0 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants