Skip to content

restrict mirrors of any union type #15279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.