-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
correctly type Expr.ofTupleFromSeq for arity > 22 (#17261)
identified that for all `Seq` with arity <= 22, the result had the most precise type possible, for > 22 then it was only `Tuple` fixes #17257
- Loading branch information
Showing
3 changed files
with
89 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package derivation | ||
import scala.quoted.* | ||
|
||
import scala.annotation.tailrec | ||
|
||
object Helpers: | ||
|
||
// file a.scala | ||
inline def summonAllOptimized[T <: Tuple]: T = | ||
${ summonAllOptimizedImpl[T] } | ||
|
||
inline def summon23[E]: (E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E) = | ||
${ summon23Impl[E] } | ||
|
||
private def summonAllOptimizedImpl[T <: Tuple: Type](using q: Quotes): Expr[T] = { | ||
import q.reflect.* | ||
|
||
Expr | ||
.ofTupleFromSeq(typesOfTuple(TypeRepr.of[T], Nil).map { tpe => | ||
tpe.asType match { | ||
case '[t] => | ||
Expr.summon[t].getOrElse(report.errorAndAbort(s"Unable to to find implicit instance for ${tpe.show}")) | ||
} | ||
}) | ||
.asExprOf[T] | ||
} | ||
|
||
private def summon23Impl[E: Type](using q: Quotes): Expr[(E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E)] = { | ||
import q.reflect.* | ||
|
||
val e = Expr.summon[E].getOrElse(report.errorAndAbort(s"Unable to to find implicit instance for ${TypeRepr.of[E].show}")) | ||
|
||
val tuple = (e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e) | ||
|
||
assert(tuple.size == 23) | ||
|
||
Expr.ofTuple(tuple) | ||
} | ||
|
||
@tailrec | ||
private[derivation] 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}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package derivation { | ||
//file b.scala | ||
val test = Helpers.summonAllOptimized[( | ||
ValueOf["a"], ValueOf["a"], ValueOf["a"], ValueOf["a"], ValueOf["a"], | ||
ValueOf["a"], ValueOf["a"], ValueOf["a"], ValueOf["a"], ValueOf["a"], | ||
ValueOf["a"], ValueOf["a"], ValueOf["a"], ValueOf["a"], ValueOf["a"], | ||
ValueOf["a"], ValueOf["a"], ValueOf["a"], ValueOf["a"], ValueOf["a"], | ||
ValueOf["a"], ValueOf["a"], ValueOf["a"] //Commenting out the last one here fixes the compile error | ||
)] | ||
val test2 = Helpers.summon23[ValueOf["a"]] | ||
} | ||
@main def Test = | ||
def assertions(list: List[ValueOf["a"]]): Unit = | ||
assert(list.size == 23) | ||
assert(list.map(_.value) == List( | ||
"a", "a", "a", "a", "a", | ||
"a", "a", "a", "a", "a", | ||
"a", "a", "a", "a", "a", | ||
"a", "a", "a", "a", "a", | ||
"a", "a", "a" | ||
)) | ||
assertions(derivation.test.toList) | ||
assertions(derivation.test2.toList) |