From f25de738b80aac325b10e4348a81602121063345 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 3 Apr 2021 20:33:06 +0200 Subject: [PATCH 1/2] When simplifying match types, ensure fully defined before reducing Fixes #11977 Previously the match types were more often fully defined because inlining at Typer caused more situations where type variables were instantiated. Now that inlining is done later, we need to compensate. I believe it's a good idea anyway since it means we can reduce more match types. --- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 4 ++++ compiler/src/dotty/tools/dotc/core/Types.scala | 10 ++++++---- tests/pos/i11977.scala | 7 +++++++ 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 tests/pos/i11977.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 3c4db42b293b..46ab01cd58a1 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -139,6 +139,10 @@ object TypeOps: case tp1 => tp1 } case tp: AppliedType => + tp.tycon match + case tycon: TypeRef if tycon.info.isInstanceOf[MatchAlias] => + isFullyDefined(tp, ForceDegree.all) + case _ => val normed = tp.tryNormalize if normed.exists then normed else tp.map(simplify(_, theMap)) case tp: TypeParamRef => diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 24537ac288cd..10f1996001e9 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1816,10 +1816,12 @@ object Types { /** A simplified version of this type which is equivalent wrt =:= to this type. * This applies a typemap to the type which (as all typemaps) follows type * variable instances and reduces typerefs over refined types. It also - * re-evaluates all occurrences of And/OrType with &/| because - * what was a union or intersection of type variables might be a simpler type - * after the type variables are instantiated. Finally, it - * maps poly params in the current constraint set back to their type vars. + * + * - re-evaluates all occurrences of And/OrType with &/| because + * what was a union or intersection of type variables might be a simpler type + * after the type variables are instantiated. + * - maps poly params in the current constraint set back to their type vars. + * - forces match types to be fully defined and tries to normalize them. * * NOTE: Simplifying an intersection type might change its erasure (for * example, the Java erasure of `Object & Serializable` is `Object`, diff --git a/tests/pos/i11977.scala b/tests/pos/i11977.scala new file mode 100644 index 000000000000..fa634b3a257d --- /dev/null +++ b/tests/pos/i11977.scala @@ -0,0 +1,7 @@ +object Test: + + def add0(a : (Int, String), b : (Int, String)): Int = + val x = 3 + x + b(0) + + def add(a : (Int, String), b : (Int, String)) : (Int, String) = (a(0) + b(0), a(1) + b(1)) From e5d9983e82d6089e4dcf18de985c72731610191b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 3 Apr 2021 21:41:22 +0200 Subject: [PATCH 2/2] Fix repltest --- compiler/test-resources/repl/i5218 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/test-resources/repl/i5218 b/compiler/test-resources/repl/i5218 index e99590d0315d..bdf8325b6962 100644 --- a/compiler/test-resources/repl/i5218 +++ b/compiler/test-resources/repl/i5218 @@ -3,4 +3,5 @@ val tuple: (Int, String, Long) = (1,2,3) scala> 0.0 *: tuple val res0: (Double, Int, String, Long) = (0.0,1,2,3) scala> tuple ++ tuple -val res1: Int *: scala.Tuple.Concat[(String, Long), tuple.type] = (1,2,3,1,2,3) +val res1: Int *: String *: Long *: + scala.Tuple.Concat[scala.Tuple$package.EmptyTuple.type, tuple.type] = (1,2,3,1,2,3)