Skip to content

Commit

Permalink
Add test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Oct 25, 2023
1 parent f995a8c commit 125612f
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
75 changes: 75 additions & 0 deletions tests/neg-macros/i18695.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import scala.annotation.{tailrec, unused}
import scala.deriving.Mirror
import scala.quoted.*

trait TypeLength[A] {
type Length <: Int
def length: Length
}
object TypeLength extends TypeLengthLowPriority:
type Aux[A, Length0 <: Int] = TypeLength[A] {
type Length = Length0
}

transparent inline given fromMirror[A](using m: Mirror.Of[A]): TypeLength[A] =
${ macroImpl[A, m.MirroredElemTypes] }

@tailrec
private def typesOfTuple(
using q: Quotes
)(tpe: q.reflect.TypeRepr, acc: List[q.reflect.TypeRepr]): List[q.reflect.TypeRepr] =
import q.reflect.*
val cons = Symbol.classSymbol("scala.*:")
tpe.widenTermRefByName.dealias match
case AppliedType(fn, tpes) if defn.isTupleClass(fn.typeSymbol) =>
tpes.reverse_:::(acc)
case AppliedType(tp, List(headType, tailType)) if tp.derivesFrom(cons) =>
typesOfTuple(tailType, headType :: acc)
case tpe =>
if tpe.derivesFrom(Symbol.classSymbol("scala.EmptyTuple")) then acc.reverse
else report.errorAndAbort(s"Unknown type encountered in tuple ${tpe.show}")

def macroImpl[A: Type, T <: Tuple: scala.quoted.Type](
using q: scala.quoted.Quotes
): scala.quoted.Expr[TypeLength[A]] =
import q.reflect.*
val l = typesOfTuple(TypeRepr.of[T], Nil).length
ConstantType(IntConstant(l)).asType match
case '[lt] =>
val le = Expr[Int](l).asExprOf[lt & Int]
'{
val r: TypeLength.Aux[A, lt & Int] = new TypeLength[A] {
type Length = lt & Int
val length: Length = ${ le }
}
r
}

transparent inline given fromTuple[T <: Tuple]: TypeLength[T] =
${ macroImpl[T, T] }

trait TypeLengthLowPriority:
self: TypeLength.type =>
given tupleFromMirrorAndLength[A, T <: Tuple](
using @unused m: Mirror.Of[A] { type MirroredElemTypes = T },
length: TypeLength[A]
): TypeLength.Aux[T, length.Length] = length.asInstanceOf[TypeLength.Aux[T, length.Length]]

trait HKDSumGeneric[A]
object HKDSumGeneric:
type NotZero[N <: Int] = N match
case 0 => false
case _ => true

transparent inline given derived[A](using m: Mirror.SumOf[A], typeLength: TypeLength[A])(
using NotZero[typeLength.Length] =:= true
): HKDSumGeneric[A] =
derivedImpl[A, m.MirroredElemTypes, m.MirroredLabel] // error

def derivedImpl[A, ElemTypes <: Tuple, Label <: String](
using m: Mirror.SumOf[A] {
type MirroredElemTypes = ElemTypes; type MirroredLabel = Label;
},
typeLength: TypeLength[ElemTypes],
nz: NotZero[typeLength.Length] =:= true
): HKDSumGeneric[A] = ???
3 changes: 3 additions & 0 deletions tests/neg/i18695.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
trait Foo { type Num <: Int }
given derived[A](using foo: Foo): Any = derivedImpl(foo) // error
def derivedImpl(foo: Foo)(using bar: foo.Num =:= Int): Any = ???

0 comments on commit 125612f

Please sign in to comment.