Skip to content

Commit

Permalink
Merge pull request scala#15279 from dotty-staging/no-union-in-mirror
Browse files Browse the repository at this point in the history
restrict mirrors of any union type
  • Loading branch information
bishabosha committed May 30, 2022
2 parents 135500a + 1a035fc commit 77bcd0d
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 31 deletions.
16 changes: 7 additions & 9 deletions compiler/src/dotty/tools/dotc/typer/Synthesizer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,9 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):

def whyNotAcceptableType(tp: Type, cls: Symbol): String = tp match
case tp: HKTypeLambda if tp.resultType.isInstanceOf[HKTypeLambda] =>
i"its subpart $tp is not a supported kind (either `*` or `* -> *`)"
i"its subpart `$tp` is not a supported kind (either `*` or `* -> *`)"
case tp: TypeProxy => whyNotAcceptableType(tp.underlying, cls)
case OrType(tp1, tp2) =>
Seq(tp1, tp2).map(whyNotAcceptableType(_, cls)).find(_.nonEmpty).getOrElse("")
case OrType(tp1, tp2) => i"its subpart `$tp` is a top-level union type."
case _ =>
if tp.classSymbol eq cls then ""
else i"a subpart reduces to the more precise ${tp.classSymbol}, expected $cls"
Expand Down Expand Up @@ -339,7 +338,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
if acceptableMsg.isEmpty then
if cls.isGenericProduct then makeProductMirror(cls)
else withErrors(i"$cls is not a generic product because ${cls.whyNotGenericProduct}")
else withErrors(i"type $mirroredType is not a generic product because $acceptableMsg")
else withErrors(i"type `$mirroredType` is not a generic product because $acceptableMsg")
end productMirror

private def sumMirror(mirroredType: Type, formal: Type, span: Span)(using Context): TreeWithErrors =
Expand All @@ -348,12 +347,11 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
val clsIsGenericSum = cls.isGenericSum

def whyNotAcceptableType(tp: Type): String = tp match
case tp: TermRef => i"its subpart $tp is a term reference"
case tp: TermRef => i"its subpart `$tp` is a term reference"
case tp: HKTypeLambda if tp.resultType.isInstanceOf[HKTypeLambda] =>
i"its subpart $tp is not a supported kind (either `*` or `* -> *`)"
i"its subpart `$tp` is not a supported kind (either `*` or `* -> *`)"
case tp: TypeProxy => whyNotAcceptableType(tp.underlying)
case OrType(tp1, tp2) =>
Seq(tp1, tp2).map(whyNotAcceptableType).find(_.nonEmpty).getOrElse("")
case OrType(tp1, tp2) => i"its subpart `$tp` is a top-level union type."
case _ =>
if tp.classSymbol eq cls then ""
else i"a subpart reduces to the more precise ${tp.classSymbol}, expected $cls"
Expand Down Expand Up @@ -416,7 +414,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
else anonymousMirror(monoType, ExtendsSumMirror, span)
withNoErrors(mirrorRef.cast(mirrorType))
else if acceptableMsg.nonEmpty then
withErrors(i"type $mirroredType is not a generic sum because $acceptableMsg")
withErrors(i"type `$mirroredType` is not a generic sum because $acceptableMsg")
else if !clsIsGenericSum then
withErrors(i"$cls is not a generic sum because ${cls.whyNotGenericSum}")
else
Expand Down
4 changes: 2 additions & 2 deletions tests/neg/i14025.check
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
-- Error: tests/neg/i14025.scala:1:88 ----------------------------------------------------------------------------------
1 |val foo = summon[deriving.Mirror.Product { type MirroredType = [X] =>> [Y] =>> (X, Y) }] // error
| ^
|No given instance of type deriving.Mirror.Product{MirroredType[X] = [Y] =>> (X, Y)} was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Product{MirroredType[X] = [Y] =>> (X, Y)}: type [X] =>> [Y] =>> (X, Y) is not a generic product because its subpart [X] =>> [Y] =>> (X, Y) is not a supported kind (either `*` or `* -> *`)
|No given instance of type deriving.Mirror.Product{MirroredType[X] = [Y] =>> (X, Y)} was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Product{MirroredType[X] = [Y] =>> (X, Y)}: type `[X] =>> [Y] =>> (X, Y)` is not a generic product because its subpart `[X] =>> [Y] =>> (X, Y)` is not a supported kind (either `*` or `* -> *`)
-- Error: tests/neg/i14025.scala:2:90 ----------------------------------------------------------------------------------
2 |val bar = summon[deriving.Mirror.Sum { type MirroredType = [X] =>> [Y] =>> List[(X, Y)] }] // error
| ^
|No given instance of type deriving.Mirror.Sum{MirroredType[X] = [Y] =>> List[(X, Y)]} was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Sum{MirroredType[X] = [Y] =>> List[(X, Y)]}: type [X] =>> [Y] =>> List[(X, Y)] is not a generic sum because its subpart [X] =>> [Y] =>> List[(X, Y)] is not a supported kind (either `*` or `* -> *`)
|No given instance of type deriving.Mirror.Sum{MirroredType[X] = [Y] =>> List[(X, Y)]} was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Sum{MirroredType[X] = [Y] =>> List[(X, Y)]}: type `[X] =>> [Y] =>> List[(X, Y)]` is not a generic sum because its subpart `[X] =>> [Y] =>> List[(X, Y)]` is not a supported kind (either `*` or `* -> *`)
4 changes: 2 additions & 2 deletions tests/neg/i14823.check
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
8 |val baz = summon[Mirror.Of[SubA[Int] | SubB[Int]]] // error
| ^
|No given instance of type deriving.Mirror.Of[SubA[Int] | SubB[Int]] was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Of[SubA[Int] | SubB[Int]]:
| * type SubA[Int] | SubB[Int] is not a generic product because a subpart reduces to the more precise class SubA, expected class Cov
| * type SubA[Int] | SubB[Int] is not a generic sum because a subpart reduces to the more precise class SubA, expected class Cov
| * type `SubA[Int] | SubB[Int]` is not a generic product because its subpart `SubA[Int] | SubB[Int]` is a top-level union type.
| * type `SubA[Int] | SubB[Int]` is not a generic sum because its subpart `SubA[Int] | SubB[Int]` is a top-level union type.
24 changes: 24 additions & 0 deletions tests/neg/i14823a.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-- Error: tests/neg/i14823a.scala:16:48 --------------------------------------------------------------------------------
16 |val foo = summon[Mirror.Of[Box[Int] | Box[Int]]] // error
| ^
|No given instance of type deriving.Mirror.Of[Box[Int] | Box[Int]] was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Of[Box[Int] | Box[Int]]:
| * type `Box[Int] | Box[Int]` is not a generic product because its subpart `Box[Int] | Box[Int]` is a top-level union type.
| * type `Box[Int] | Box[Int]` is not a generic sum because its subpart `Box[Int] | Box[Int]` is a top-level union type.
-- Error: tests/neg/i14823a.scala:17:58 --------------------------------------------------------------------------------
17 |val bar = summon[MirrorK1.Of[[X] =>> Box[Int] | Box[Int]]] // error
| ^
|No given instance of type MirrorK1.Of[[X] =>> Box[Int] | Box[Int]] was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type MirrorK1.Of[[X] =>> Box[Int] | Box[Int]]:
| * type `[A] =>> Box[Int] | Box[Int]` is not a generic product because its subpart `Box[Int] | Box[Int]` is a top-level union type.
| * type `[A] =>> Box[Int] | Box[Int]` is not a generic sum because its subpart `Box[Int] | Box[Int]` is a top-level union type.
-- Error: tests/neg/i14823a.scala:18:63 --------------------------------------------------------------------------------
18 |def baz = summon[deriving.Mirror.Of[Foo[String] | Foo[String]]] // error
| ^
|No given instance of type deriving.Mirror.Of[Foo[String] | Foo[String]] was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Of[Foo[String] | Foo[String]]:
| * type `Foo[String] | Foo[String]` is not a generic product because its subpart `Foo[String] | Foo[String]` is a top-level union type.
| * type `Foo[String] | Foo[String]` is not a generic sum because its subpart `Foo[String] | Foo[String]` is a top-level union type.
-- Error: tests/neg/i14823a.scala:20:66 --------------------------------------------------------------------------------
20 |def qux = summon[deriving.Mirror.Of[Option[Int] | Option[String]]] // error
| ^
|No given instance of type deriving.Mirror.Of[Option[Int] | Option[String]] was found for parameter x of method summon in object Predef. Failed to synthesize an instance of type deriving.Mirror.Of[Option[Int] | Option[String]]:
| * type `Option[Int] | Option[String]` is not a generic product because its subpart `Option[Int] | Option[String]` is a top-level union type.
| * type `Option[Int] | Option[String]` is not a generic sum because its subpart `Option[Int] | Option[String]` is a top-level union type.
20 changes: 20 additions & 0 deletions tests/neg/i14823a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import deriving.Mirror

object MirrorK1:
type Of[F[_]] = Mirror { type MirroredType[A] = F[A] }

sealed trait Box[T]
object Box

case class Child[T]() extends Box[T]

sealed abstract class Foo[T]
object Foo {
case class A[T]() extends Foo[T]
}

val foo = summon[Mirror.Of[Box[Int] | Box[Int]]] // error
val bar = summon[MirrorK1.Of[[X] =>> Box[Int] | Box[Int]]] // error
def baz = summon[deriving.Mirror.Of[Foo[String] | Foo[String]]] // error

def qux = summon[deriving.Mirror.Of[Option[Int] | Option[String]]] // error
18 changes: 0 additions & 18 deletions tests/pos/i14823.scala

This file was deleted.

0 comments on commit 77bcd0d

Please sign in to comment.