Skip to content

Commit 7e20b81

Browse files
Merge pull request #15655 from dotty-staging/fix-implicit-loop-check
Fix looping implicits check
2 parents 8fc154e + 8aa8cfe commit 7e20b81

File tree

4 files changed

+45
-134
lines changed

4 files changed

+45
-134
lines changed

compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class CheckLoopingImplicits extends MiniPhase:
9898
checkNotLooping(finalizer)
9999
case SeqLiteral(elems, _) =>
100100
elems.foreach(checkNotLooping)
101-
case t: ValDef =>
101+
case t: ValDef if !t.symbol.is(Lazy) =>
102102
checkNotLooping(t.rhs)
103103
case _ =>
104104

tests/neg-custom-args/fatal-warnings/i13542.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ val x5 =
4040

4141
val x6 =
4242
implicit def barToFoo4(bar: Bar): Foo =
43-
lazy val y = bar.toFoo // error
43+
lazy val y = bar.toFoo
4444
if false then y else ???
4545
val foo: Foo = Bar(1)
4646

tests/neg/i13044.check

Lines changed: 0 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,3 @@
1-
-- Warning: tests/neg/i13044.scala:50:40 -------------------------------------------------------------------------------
2-
50 | implicit def typeSchema: Schema[A] = Schema.gen // error // error
3-
| ^^^^^^^^^^
4-
|Infinite loop in function body
5-
|{
6-
| val SchemaDerivation_this: Schema.type = Schema
7-
| {
8-
| val SchemaDerivation_this: (SchemaDerivation_this : Schema.type) = SchemaDerivation_this
9-
| {
10-
| val $scrutinee1:
11-
| scala.deriving.Mirror.Product{
12-
| MirroredMonoType = A; MirroredType = A; MirroredLabel = ("A" : String); MirroredElemTypes = (A, B);
13-
| MirroredElemLabels = (("a" : String), ("b" : String))
14-
| }
15-
| =
16-
| A.$asInstanceOf[
17-
| scala.deriving.Mirror.Product{
18-
| MirroredMonoType = A; MirroredType = A; MirroredLabel = ("A" : String); MirroredElemTypes = (A, B);
19-
| MirroredElemLabels = (("a" : String), ("b" : String))
20-
| }
21-
| ]
22-
| val m:
23-
| scala.deriving.Mirror.Product{
24-
| MirroredMonoType = A; MirroredType = A; MirroredLabel = ("A" : String); MirroredElemTypes = (A, B);
25-
| MirroredElemLabels = (("a" : String), ("b" : String))
26-
| }
27-
| = $scrutinee1
28-
| lazy val fields: List[Schema[Any]] =
29-
| {
30-
| val SchemaDerivation_this: (SchemaDerivation_this : (SchemaDerivation_this : Schema.type)) =
31-
| SchemaDerivation_this
32-
| {
33-
| val builder: Schema[Any] = TestApp.typeSchema.asInstanceOf[Schema[Any]]
34-
| {
35-
| val SchemaDerivation_this:
36-
| (SchemaDerivation_this : (SchemaDerivation_this : (SchemaDerivation_this : Schema.type)))
37-
| = SchemaDerivation_this
38-
| (
39-
| {
40-
| val builder: Schema[Any] =
41-
| {
42-
| val SchemaDerivation_this: Schema.type = Schema
43-
| (
44-
| {
45-
| val SchemaDerivation_this: (SchemaDerivation_this : Schema.type) = SchemaDerivation_this
46-
| {
47-
| val $scrutinee4:
48-
| scala.deriving.Mirror.Product{
49-
| MirroredMonoType = B; MirroredType = B; MirroredLabel = ("B" : String);
50-
| MirroredElemTypes = C *: EmptyTuple.type
51-
| ; MirroredElemLabels = ("c" : String) *: EmptyTuple.type
52-
| }
53-
| =
54-
| B.$asInstanceOf[
55-
| scala.deriving.Mirror.Product{
56-
| MirroredMonoType = B; MirroredType = B; MirroredLabel = ("B" : String);
57-
| MirroredElemTypes = C *: EmptyTuple.type
58-
| ; MirroredElemLabels = ("c" : String) *: EmptyTuple.type
59-
| }
60-
| ]
61-
| val m:
62-
| scala.deriving.Mirror.Product{
63-
| MirroredMonoType = B; MirroredType = B; MirroredLabel = ("B" : String);
64-
| MirroredElemTypes = C *: EmptyTuple.type
65-
| ; MirroredElemLabels = ("c" : String) *: EmptyTuple.type
66-
| }
67-
| = $scrutinee4
68-
| lazy val fields: List[Schema[Any]] =
69-
| {
70-
| val SchemaDerivation_this:
71-
| (SchemaDerivation_this : (SchemaDerivation_this : Schema.type))
72-
| = SchemaDerivation_this
73-
| {
74-
| val builder: Schema[Any] =
75-
| {
76-
| val SchemaDerivation_this: Schema.type = Schema
77-
| (
78-
| {
79-
| val SchemaDerivation_this: (...SchemaDerivation_this : ....type) =
80-
| SchemaDerivation_this
81-
| {
82-
| val $scrutinee6:
83-
| ...{
84-
| MirroredMonoType...; MirroredType...; MirroredLabel...;
85-
| MirroredElemTypes...
86-
| ; MirroredElemLabels...
87-
| }
88-
| = ....$asInstanceOf[...]
89-
| val m: ... = ...$scrutinee6
90-
| lazy val fields: ... =
91-
| {
92-
| val SchemaDerivation_this: ... = ...
93-
| ...:...
94-
| }
95-
| {
96-
| final class $anon() extends ...(), ... {
97-
| def build: ... = ...
98-
| }
99-
| ...():...
100-
| }
101-
| }:...[...]
102-
| }
103-
| :Schema[C])
104-
| }.asInstanceOf[Schema[Any]]
105-
| SchemaDerivation_this.recurse[EmptyTuple.type].::[Schema[Any]](builder)
106-
| }:List[Schema[Any]]
107-
| }
108-
| {
109-
| final class $anon() extends Object(), Schema[B] {
110-
| def build: B = ???
111-
| }
112-
| new Object with Schema[B] {...}():Schema[B]
113-
| }
114-
| }:Schema[B]
115-
| }
116-
| :Schema[B])
117-
| }.asInstanceOf[Schema[Any]]
118-
| SchemaDerivation_this.recurse[EmptyTuple.type].::[Schema[Any]](builder)
119-
| }
120-
| :List[Schema[Any]])
121-
| }.::[Schema[Any]](builder)
122-
| }:List[Schema[Any]]
123-
| }
124-
| {
125-
| final class $anon() extends Object(), Schema[A] {
126-
| def build: A = ???
127-
| }
128-
| new Object with Schema[A] {...}():Schema[A]
129-
| }
130-
| }:Schema[A]
131-
| }:Schema[A]
132-
|}
1331
-- Error: tests/neg/i13044.scala:50:40 ---------------------------------------------------------------------------------
1342
50 | implicit def typeSchema: Schema[A] = Schema.gen // error // error
1353
| ^^^^^^^^^^
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import scala.deriving.Mirror
2+
import scala.compiletime._
3+
4+
trait Schema[T]
5+
6+
object Schema {
7+
implicit val stringSchema: Schema[String] = new Schema[String] {}
8+
implicit def listSchema[A](implicit ev: Schema[A]): Schema[List[A]] = new Schema[List[A]] {}
9+
implicit def mapSchema[A, B](implicit evA: Schema[A], evB: Schema[B]): Schema[Map[A, B]] =
10+
new Schema[Map[A, B]] {}
11+
12+
inline def recurse[Label, A <: Tuple](index: Int = 0): List[(String, Schema[Any], Int)] =
13+
inline erasedValue[(Label, A)] match {
14+
case (_: (name *: names), _: (t *: ts)) =>
15+
val label = constValue[name].toString
16+
val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]]
17+
(label, builder, index) :: recurse[names, ts](index + 1)
18+
case (_: EmptyTuple, _) => Nil
19+
}
20+
21+
inline def derived[A]: Schema[A] =
22+
inline summonInline[Mirror.Of[A]] match {
23+
case m: Mirror.SumOf[A] =>
24+
lazy val members = recurse[m.MirroredElemLabels, m.MirroredElemTypes]()
25+
new Schema[A] {}
26+
case m: Mirror.ProductOf[A] =>
27+
lazy val fields = recurse[m.MirroredElemLabels, m.MirroredElemTypes]()
28+
new Schema[A] {}
29+
}
30+
31+
inline given gen[A]: Schema[A] = derived[A]
32+
}
33+
34+
sealed trait InputValue
35+
object InputValue {
36+
case class ListValue(values: List[InputValue]) extends InputValue
37+
case class ObjectValue(fields: Map[String, InputValue]) extends InputValue
38+
case class VariableValue(name: String) extends InputValue
39+
}
40+
41+
@main def Test =
42+
implicit lazy val inputValueSchema: Schema[InputValue] = Schema.gen
43+
println(summon[Schema[InputValue]])

0 commit comments

Comments
 (0)