Skip to content

Commit

Permalink
Merge pull request #15655 from dotty-staging/fix-implicit-loop-check
Browse files Browse the repository at this point in the history
Fix looping implicits check
  • Loading branch information
WojciechMazur authored Jul 12, 2022
2 parents 8fc154e + 8aa8cfe commit 7e20b81
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class CheckLoopingImplicits extends MiniPhase:
checkNotLooping(finalizer)
case SeqLiteral(elems, _) =>
elems.foreach(checkNotLooping)
case t: ValDef =>
case t: ValDef if !t.symbol.is(Lazy) =>
checkNotLooping(t.rhs)
case _ =>

Expand Down
2 changes: 1 addition & 1 deletion tests/neg-custom-args/fatal-warnings/i13542.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ val x5 =

val x6 =
implicit def barToFoo4(bar: Bar): Foo =
lazy val y = bar.toFoo // error
lazy val y = bar.toFoo
if false then y else ???
val foo: Foo = Bar(1)

Expand Down
132 changes: 0 additions & 132 deletions tests/neg/i13044.check
Original file line number Diff line number Diff line change
@@ -1,135 +1,3 @@
-- Warning: tests/neg/i13044.scala:50:40 -------------------------------------------------------------------------------
50 | implicit def typeSchema: Schema[A] = Schema.gen // error // error
| ^^^^^^^^^^
|Infinite loop in function body
|{
| val SchemaDerivation_this: Schema.type = Schema
| {
| val SchemaDerivation_this: (SchemaDerivation_this : Schema.type) = SchemaDerivation_this
| {
| val $scrutinee1:
| scala.deriving.Mirror.Product{
| MirroredMonoType = A; MirroredType = A; MirroredLabel = ("A" : String); MirroredElemTypes = (A, B);
| MirroredElemLabels = (("a" : String), ("b" : String))
| }
| =
| A.$asInstanceOf[
| scala.deriving.Mirror.Product{
| MirroredMonoType = A; MirroredType = A; MirroredLabel = ("A" : String); MirroredElemTypes = (A, B);
| MirroredElemLabels = (("a" : String), ("b" : String))
| }
| ]
| val m:
| scala.deriving.Mirror.Product{
| MirroredMonoType = A; MirroredType = A; MirroredLabel = ("A" : String); MirroredElemTypes = (A, B);
| MirroredElemLabels = (("a" : String), ("b" : String))
| }
| = $scrutinee1
| lazy val fields: List[Schema[Any]] =
| {
| val SchemaDerivation_this: (SchemaDerivation_this : (SchemaDerivation_this : Schema.type)) =
| SchemaDerivation_this
| {
| val builder: Schema[Any] = TestApp.typeSchema.asInstanceOf[Schema[Any]]
| {
| val SchemaDerivation_this:
| (SchemaDerivation_this : (SchemaDerivation_this : (SchemaDerivation_this : Schema.type)))
| = SchemaDerivation_this
| (
| {
| val builder: Schema[Any] =
| {
| val SchemaDerivation_this: Schema.type = Schema
| (
| {
| val SchemaDerivation_this: (SchemaDerivation_this : Schema.type) = SchemaDerivation_this
| {
| val $scrutinee4:
| scala.deriving.Mirror.Product{
| MirroredMonoType = B; MirroredType = B; MirroredLabel = ("B" : String);
| MirroredElemTypes = C *: EmptyTuple.type
| ; MirroredElemLabels = ("c" : String) *: EmptyTuple.type
| }
| =
| B.$asInstanceOf[
| scala.deriving.Mirror.Product{
| MirroredMonoType = B; MirroredType = B; MirroredLabel = ("B" : String);
| MirroredElemTypes = C *: EmptyTuple.type
| ; MirroredElemLabels = ("c" : String) *: EmptyTuple.type
| }
| ]
| val m:
| scala.deriving.Mirror.Product{
| MirroredMonoType = B; MirroredType = B; MirroredLabel = ("B" : String);
| MirroredElemTypes = C *: EmptyTuple.type
| ; MirroredElemLabels = ("c" : String) *: EmptyTuple.type
| }
| = $scrutinee4
| lazy val fields: List[Schema[Any]] =
| {
| val SchemaDerivation_this:
| (SchemaDerivation_this : (SchemaDerivation_this : Schema.type))
| = SchemaDerivation_this
| {
| val builder: Schema[Any] =
| {
| val SchemaDerivation_this: Schema.type = Schema
| (
| {
| val SchemaDerivation_this: (...SchemaDerivation_this : ....type) =
| SchemaDerivation_this
| {
| val $scrutinee6:
| ...{
| MirroredMonoType...; MirroredType...; MirroredLabel...;
| MirroredElemTypes...
| ; MirroredElemLabels...
| }
| = ....$asInstanceOf[...]
| val m: ... = ...$scrutinee6
| lazy val fields: ... =
| {
| val SchemaDerivation_this: ... = ...
| ...:...
| }
| {
| final class $anon() extends ...(), ... {
| def build: ... = ...
| }
| ...():...
| }
| }:...[...]
| }
| :Schema[C])
| }.asInstanceOf[Schema[Any]]
| SchemaDerivation_this.recurse[EmptyTuple.type].::[Schema[Any]](builder)
| }:List[Schema[Any]]
| }
| {
| final class $anon() extends Object(), Schema[B] {
| def build: B = ???
| }
| new Object with Schema[B] {...}():Schema[B]
| }
| }:Schema[B]
| }
| :Schema[B])
| }.asInstanceOf[Schema[Any]]
| SchemaDerivation_this.recurse[EmptyTuple.type].::[Schema[Any]](builder)
| }
| :List[Schema[Any]])
| }.::[Schema[Any]](builder)
| }:List[Schema[Any]]
| }
| {
| final class $anon() extends Object(), Schema[A] {
| def build: A = ???
| }
| new Object with Schema[A] {...}():Schema[A]
| }
| }:Schema[A]
| }:Schema[A]
|}
-- Error: tests/neg/i13044.scala:50:40 ---------------------------------------------------------------------------------
50 | implicit def typeSchema: Schema[A] = Schema.gen // error // error
| ^^^^^^^^^^
Expand Down
43 changes: 43 additions & 0 deletions tests/pos-special/fatal-warnings/not-looping-implicit.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import scala.deriving.Mirror
import scala.compiletime._

trait Schema[T]

object Schema {
implicit val stringSchema: Schema[String] = new Schema[String] {}
implicit def listSchema[A](implicit ev: Schema[A]): Schema[List[A]] = new Schema[List[A]] {}
implicit def mapSchema[A, B](implicit evA: Schema[A], evB: Schema[B]): Schema[Map[A, B]] =
new Schema[Map[A, B]] {}

inline def recurse[Label, A <: Tuple](index: Int = 0): List[(String, Schema[Any], Int)] =
inline erasedValue[(Label, A)] match {
case (_: (name *: names), _: (t *: ts)) =>
val label = constValue[name].toString
val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]]
(label, builder, index) :: recurse[names, ts](index + 1)
case (_: EmptyTuple, _) => Nil
}

inline def derived[A]: Schema[A] =
inline summonInline[Mirror.Of[A]] match {
case m: Mirror.SumOf[A] =>
lazy val members = recurse[m.MirroredElemLabels, m.MirroredElemTypes]()
new Schema[A] {}
case m: Mirror.ProductOf[A] =>
lazy val fields = recurse[m.MirroredElemLabels, m.MirroredElemTypes]()
new Schema[A] {}
}

inline given gen[A]: Schema[A] = derived[A]
}

sealed trait InputValue
object InputValue {
case class ListValue(values: List[InputValue]) extends InputValue
case class ObjectValue(fields: Map[String, InputValue]) extends InputValue
case class VariableValue(name: String) extends InputValue
}

@main def Test =
implicit lazy val inputValueSchema: Schema[InputValue] = Schema.gen
println(summon[Schema[InputValue]])

0 comments on commit 7e20b81

Please sign in to comment.