From c0db02cddc0ca21824f143a14917ef81b0421d34 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 2 Oct 2021 21:26:35 +0200 Subject: [PATCH 1/3] Harden orDominator Fixes #13435 --- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 6 +++++- tests/neg/i13435.check | 12 ++++++++++++ tests/neg/i13435.scala | 8 ++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i13435.check create mode 100644 tests/neg/i13435.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 6a5145ffd202..05453d3c8d51 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -349,7 +349,11 @@ object TypeOps: val doms = dominators(commonBaseClasses, Nil) def baseTp(cls: ClassSymbol): Type = tp.baseType(cls).mapReduceOr(identity)(mergeRefinedOrApplied) - doms.map(baseTp).reduceLeft(AndType.apply) + def meet(tp1: Type, tp2: Type) = + if !tp1.exists then tp2 + else if !tp2.exists then tp1 + else AndType(tp1, tp2) + doms.map(baseTp).reduceLeft(meet) } tp match { diff --git a/tests/neg/i13435.check b/tests/neg/i13435.check new file mode 100644 index 000000000000..d60bea7ab588 --- /dev/null +++ b/tests/neg/i13435.check @@ -0,0 +1,12 @@ +-- [E029] Pattern Match Exhaustivity Warning: tests/neg/i13435.scala:7:2 ----------------------------------------------- +7 | s match + | ^ + | match may not be exhaustive. + | + | It would fail on pattern case: (_), ((_, _), (_, _)) + +longer explanation available when compiling with `-explain` +-- Error: tests/neg/i13435.scala:8:10 ---------------------------------------------------------------------------------- +8 | case (dim: Axis, size: Int) => dim // error + | ^^^^^^^^^ + | trait Singleton cannot be used in runtime type tests diff --git a/tests/neg/i13435.scala b/tests/neg/i13435.scala new file mode 100644 index 000000000000..eaff4976eb71 --- /dev/null +++ b/tests/neg/i13435.scala @@ -0,0 +1,8 @@ +type Axis = String&Singleton +type ShapeTuple = Tuple1[(Axis, Int)]|Tuple2[(Axis, Int), (Axis, Int)] +type Shape = (Axis, Int) |ShapeTuple + + +def mkSchema(s: Shape) = + s match + case (dim: Axis, size: Int) => dim // error \ No newline at end of file From 837afec243a343a08d0d8f8774abc48576f9370f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 5 Oct 2021 16:53:09 +0200 Subject: [PATCH 2/3] Better fix: Fix parents of tuple classes We inserted the :* class not in the correct place, so the linearizations of Tuple1..Tuple22 were messed up. --- compiler/src/dotty/tools/dotc/core/Definitions.scala | 10 +++++----- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 6 +----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index c3b462f3b179..b593159a7e10 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1620,11 +1620,11 @@ class Definitions { /** If `cls` is Tuple1..Tuple22, add the corresponding *: type as last parent to `parents` */ def adjustForTuple(cls: ClassSymbol, tparams: List[TypeSymbol], parents: List[Type]): List[Type] = { - def syntheticParent(tparams: List[TypeSymbol]): Type = - if (tparams.isEmpty) TupleTypeRef - else TypeOps.nestedPairs(tparams.map(_.typeRef)) - if (isTupleClass(cls)) parents :+ syntheticParent(tparams) - else parents + if !isTupleClass(cls) then parents + else if tparams.isEmpty then parents :+ TupleTypeRef + else + assert(parents.head.typeSymbol == ObjectClass) + TypeOps.nestedPairs(tparams.map(_.typeRef)) :: parents.tail } /** If it is BoxedUnit, remove `java.io.Serializable` from `parents`. */ diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 05453d3c8d51..6a5145ffd202 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -349,11 +349,7 @@ object TypeOps: val doms = dominators(commonBaseClasses, Nil) def baseTp(cls: ClassSymbol): Type = tp.baseType(cls).mapReduceOr(identity)(mergeRefinedOrApplied) - def meet(tp1: Type, tp2: Type) = - if !tp1.exists then tp2 - else if !tp2.exists then tp1 - else AndType(tp1, tp2) - doms.map(baseTp).reduceLeft(meet) + doms.map(baseTp).reduceLeft(AndType.apply) } tp match { From eb810765214b82ad07ff3be83f1dbd3f51dc78b3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 6 Oct 2021 00:12:59 +0200 Subject: [PATCH 3/3] Fix tuple erasure (2nd attempt) --- compiler/src/dotty/tools/dotc/core/Definitions.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index b593159a7e10..4a48eccffec9 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1777,6 +1777,7 @@ class Definitions { .updated(SingletonClass, ObjectClass) .updated(TupleClass, ProductClass) .updated(NonEmptyTupleClass, ProductClass) + .updated(PairClass, ObjectClass) // ----- Initialization ---------------------------------------------------