Skip to content

Commit ace48a2

Browse files
Add a subtype check with Wildcard types
This breaks tests/run/typeclass-derivation2c.scala There is no way to statically know that the type passed to constValue reduces.
1 parent 3f89e4c commit ace48a2

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

compiler/src/dotty/tools/dotc/core/TypeApplications.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ class TypeApplications(val self: Type) extends AnyVal {
405405
case dealiased: LazyRef =>
406406
LazyRef(c => dealiased.ref(c).appliedTo(args))
407407
case dealiased: WildcardType =>
408-
WildcardType(dealiased.optBounds.appliedTo(args).bounds)
408+
WildcardType(dealiased.optBounds.orElse(TypeBounds.empty).appliedTo(args).bounds)
409409
case dealiased: TypeRef if dealiased.symbol == defn.NothingClass =>
410410
dealiased
411411
case dealiased =>

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

+13-2
Original file line numberDiff line numberDiff line change
@@ -2152,6 +2152,15 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
21522152
case _ =>
21532153
cas
21542154
}
2155+
def widenAbstractTypes(tp: Type) = new TypeMap {
2156+
def apply(tp: Type) = tp match {
2157+
case tp: TypeRef if tp.symbol.isAbstractOrParamType | tp.symbol.isOpaqueAlias => WildcardType
2158+
case tp: TypeVar if !tp.isInstantiated => WildcardType
2159+
case _: SkolemType | _: TypeParamRef => WildcardType
2160+
case _ => mapOver(tp)
2161+
}
2162+
}.apply(tp)
2163+
21552164
val defn.MatchCase(pat, body) = cas1
21562165
if (isSubType(scrut, pat))
21572166
// `scrut` is a subtype of `pat`: *It's a Match!*
@@ -2164,12 +2173,14 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
21642173
body
21652174
}
21662175
}
2167-
else if (intersecting(scrut, pat))
2176+
else if (isSubType(widenAbstractTypes(scrut), widenAbstractTypes(pat)))
21682177
Some(NoType)
2169-
else
2178+
else if (!intersecting(scrut, pat))
21702179
// We found a proof that `scrut` and `pat` are incompatible.
21712180
// The search continues.
21722181
None
2182+
else
2183+
Some(NoType)
21732184
}
21742185

21752186
def recur(cases: List[Type]): Type = cases match {

tests/neg/6314-1.scala

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
object G {
2+
final class X
3+
final class Y
4+
5+
trait FooSig {
6+
type Type
7+
def apply[F[_]](fa: F[X & Y]): F[Y & Type]
8+
}
9+
val Foo: FooSig = new FooSig {
10+
type Type = X & Y
11+
def apply[F[_]](fa: F[X & Y]): F[Y & Type] = fa
12+
}
13+
type Foo = Foo.Type
14+
15+
type Bar[A] = A match {
16+
case X & Y => String
17+
case Y => Int
18+
}
19+
20+
def main(args: Array[String]): Unit = {
21+
val a: Bar[X & Y] = "hello"
22+
val i: Bar[Y & Foo] = Foo.apply[Bar](a)
23+
val b: Int = i // error
24+
println(b + 1)
25+
}
26+
}

tests/run/typeclass-derivation2c.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,9 @@ object Pickler {
305305
}
306306

307307
inline def unpickleProduct[T](g: Generic.Product[T])(buf: mutable.ListBuffer[Int]): T = {
308-
inline val size = constValue[Tuple.Size[g.ElemTypes]]
309-
val elems = new Array[Object](size)
308+
// inline val size = constValue[Tuple.Size[g.ElemTypes]]
309+
// val elems = new Array[Object](size)
310+
val elems = new Array[Object](buf.size)
310311
unpickleElems[g.ElemTypes](0)(buf, elems)
311312
g.fromProduct(ArrayProduct(elems))
312313
}

0 commit comments

Comments
 (0)