From 34dbdd8f0351563e9736e4b6bfb4bc091e87214a Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 14 Aug 2023 12:14:29 +0100 Subject: [PATCH] Fix MT separate compilation bug --- .../tools/dotc/core/tasty/TreeUnpickler.scala | 17 ++++++++++++++++- tests/pos/i18261.min/Main_0.scala | 5 +++++ tests/pos/i18261.min/Test_1.scala | 4 ++++ tests/pos/i18261/DFBits_0.scala | 7 +++++++ tests/pos/i18261/Foo_0.scala | 2 ++ tests/pos/i18261/Test_1.scala | 5 +++++ 6 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i18261.min/Main_0.scala create mode 100644 tests/pos/i18261.min/Test_1.scala create mode 100644 tests/pos/i18261/DFBits_0.scala create mode 100644 tests/pos/i18261/Foo_0.scala create mode 100644 tests/pos/i18261/Test_1.scala diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 0645ebecd1d0..7fa335afbf44 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1463,7 +1463,22 @@ class TreeUnpickler(reader: TastyReader, val fst = readTpt() val (bound, scrut) = if (nextUnsharedTag == CASEDEF) (EmptyTree, fst) else (fst, readTpt()) - MatchTypeTree(bound, scrut, readCases(end)) + val tpt = MatchTypeTree(bound, scrut, readCases(end)) + // If a match type definition can reduce (e.g. Id in i18261.min) + // then it's important to trigger that reduction + // before a TypeVar is added to the constraint, + // associated to the match type's type parameter. + // Otherwise, if the reduction is triggered with that constraint, + // the reduction will be simplified, + // at which point the TypeVar will replace the type parameter + // and then that TypeVar will be cached + // as the reduction of the match type definition! + // + // We also override the type, as that's what Typer does. + // The difference here is that a match type that reduces to a non-match type + // makes the TypeRef for that definition will have a TypeAlias info instead of a MatchAlias. + tpt.overwriteType(tpt.tpe.normalized) + tpt case TYPEBOUNDStpt => val lo = readTpt() val hi = if currentAddr == end then lo else readTpt() diff --git a/tests/pos/i18261.min/Main_0.scala b/tests/pos/i18261.min/Main_0.scala new file mode 100644 index 000000000000..23d7cbe28198 --- /dev/null +++ b/tests/pos/i18261.min/Main_0.scala @@ -0,0 +1,5 @@ +type Id[T] = Any match { case Any => T } + +class Foo[A] +object Foo: + given inst[X, Y <: Id[X]]: Foo[Y] = new Foo[Y] diff --git a/tests/pos/i18261.min/Test_1.scala b/tests/pos/i18261.min/Test_1.scala new file mode 100644 index 000000000000..24536da598d3 --- /dev/null +++ b/tests/pos/i18261.min/Test_1.scala @@ -0,0 +1,4 @@ +class Test: + def test: Unit = + summon[Foo[Int]] + summon[Foo[Long]] diff --git a/tests/pos/i18261/DFBits_0.scala b/tests/pos/i18261/DFBits_0.scala new file mode 100644 index 000000000000..63b5abb495ef --- /dev/null +++ b/tests/pos/i18261/DFBits_0.scala @@ -0,0 +1,7 @@ +trait DFBits[W <: Int] + +trait Candidate[R]: + type OutW <: Int +object Candidate: + given [W <: Int, R <: Foo[DFBits[W]]]: Candidate[R] with + type OutW = W diff --git a/tests/pos/i18261/Foo_0.scala b/tests/pos/i18261/Foo_0.scala new file mode 100644 index 000000000000..bd3486ac7a30 --- /dev/null +++ b/tests/pos/i18261/Foo_0.scala @@ -0,0 +1,2 @@ +type Foo[T] = T match + case Any => T diff --git a/tests/pos/i18261/Test_1.scala b/tests/pos/i18261/Test_1.scala new file mode 100644 index 000000000000..3b91847e3326 --- /dev/null +++ b/tests/pos/i18261/Test_1.scala @@ -0,0 +1,5 @@ +def baz[L](lhs: L)(using icL: Candidate[L]): DFBits[Int] = ??? +object Test: + val x: DFBits[8] = ??? + val z: DFBits[Int] = baz(x) + summon[Candidate[z.type]]