Skip to content

Commit 6bbef4e

Browse files
committed
Eliminate TypeVars and Wildcards early in glb/lub
Type variables and wildcards can act both as subtypes and supertypes depending on the direction of the test. This means types with variables and/or wildcards can shadow other types in `glb/lub`. Consider the following examples: ```scala lub((Int, ? ) :: (Int, String) :: Nil) glb((Int, ?A) :: (Int, String) :: Nil) ``` Intuitively both should return `(Int, String)`, but this depends on the order of types in the list passed to `glb/lub`. This commit incorporates the simple heuristic of moving types that contain variables and/or wildcards to the end of the list. Fixes scala/bug#10686 and fixes scala/bug#10740
1 parent 8c9c70d commit 6bbef4e

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

src/reflect/scala/reflect/internal/tpe/GlbLubs.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,14 @@ private[internal] trait GlbLubs {
167167
case Nil => Nil
168168
}
169169

170-
loop(ts)
170+
// The order here matters because type variables and
171+
// wildcards can act both as subtypes and supertypes.
172+
val (ts2, ts1) = ts.partition(_ exists {
173+
case tv: TypeVar => !tv.isGround
174+
case t => t.isWildcard
175+
})
176+
177+
loop(ts1 ::: ts2)
171178
}
172179

173180
/** Eliminate from list of types all elements which are a supertype

test/files/pos/t10686.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object Test {
2+
def ltr[A](implicit ev: (Int, A) =:= (Int, String)) = null
3+
def rtl[A](implicit ev: (Int, String) =:= (Int, A)) = null
4+
ltr
5+
rtl
6+
}

test/files/pos/t10740.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
object Test {
2+
case class Inv[A](x: A)
3+
def diff1[A](i: Inv[A], j: Inv[_ <: A]) = 1
4+
def diff2[A](i: Inv[_ >: A], j: Inv[A]) = 2
5+
def diff3[A](i: Inv[_ >: A], j: Inv[_ <: A]) = 3
6+
val i = Inv(Option(42))
7+
val j = Inv(Some(42))
8+
diff1(i, j)
9+
diff2(i, j)
10+
diff3(i, j)
11+
}

0 commit comments

Comments
 (0)