Skip to content

Commit 42010e5

Browse files
committed
Skolemize unstable prefixes in asSeenFrom
Skolemize unstable prefixes in asSeenFrom provided - the prefix appears at least once in non-variant or contra-variant position - we are in phase typer. After typer, we have already established soundness, so there's no need to do skolemization again. We can simply do the (otherwise unsound) substitution from this-type to prefix.
1 parent 777bfaf commit 42010e5

File tree

6 files changed

+48
-10
lines changed

6 files changed

+48
-10
lines changed

src/dotty/tools/dotc/core/Phases.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ object Phases {
285285
*/
286286
def relaxedTyping: Boolean = false
287287

288+
/** Overridden by FrontEnd */
289+
def isTyper = false
290+
288291
def exists: Boolean = true
289292

290293
private var myPeriod: Period = Periods.InvalidPeriod

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
274274
case _ =>
275275
thirdTry(tp1, tp2)
276276
}
277+
case tp1: SkolemType =>
278+
tp2 match {
279+
case tp2: SkolemType if !ctx.phase.isTyper && tp1.info <:< tp2.info => true
280+
case _ => thirdTry(tp1, tp2)
281+
}
277282
case tp1: TypeVar =>
278283
isSubType(tp1.underlying, tp2)
279284
case tp1: WildcardType =>

src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ import ast.tpd._
1313
trait TypeOps { this: Context => // TODO: Make standalone object.
1414

1515
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol): Type = {
16-
val m = if (pre.isStable || ctx.isAfterTyper) null else new AsSeenFromMap(pre, cls)
17-
asSeenFrom(tp, pre, cls, null)
16+
val m = if (pre.isStable || !ctx.phase.isTyper) null else new AsSeenFromMap(pre, cls)
17+
var res = asSeenFrom(tp, pre, cls, m)
18+
if (m != null && m.unstable) asSeenFrom(tp, SkolemType(pre), cls) else res
1819
}
19-
20+
2021
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol, theMap: AsSeenFromMap): Type = {
2122

2223
def toPrefix(pre: Type, cls: Symbol, thiscls: ClassSymbol): Type = /*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"toPrefix($pre, $cls, $thiscls)") /*<|<*/ {
2324
if ((pre eq NoType) || (pre eq NoPrefix) || (cls is PackageClass))
2425
tp
2526
else if (thiscls.derivesFrom(cls) && pre.baseTypeRef(thiscls).exists) {
26-
if (!pre.isStable && theMap != null && theMap.currentVariance <= 0) {
27+
if (theMap != null && theMap.currentVariance <= 0 && !pre.isStable)
2728
theMap.unstable = true
28-
}
2929
pre match {
3030
case SuperType(thispre, _) => thispre
3131
case _ => pre
@@ -43,10 +43,13 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
4343
val sym = tp.symbol
4444
if (sym.isStatic) tp
4545
else {
46+
val prevStable = theMap == null || !theMap.unstable
4647
val pre1 = asSeenFrom(tp.prefix, pre, cls, theMap)
47-
if (theMap != null && theMap.unstable) {
48+
if (theMap != null && theMap.unstable && prevStable) {
4849
pre1.member(tp.name).info match {
49-
case TypeAlias(alias) => return alias
50+
case TypeAlias(alias) =>
51+
theMap.unstable = false
52+
return alias
5053
case _ =>
5154
}
5255
}
@@ -61,7 +64,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
6164
asSeenFrom(tp.parent, pre, cls, theMap),
6265
tp.refinedName,
6366
asSeenFrom(tp.refinedInfo, pre, cls, theMap))
64-
case tp: TypeAlias =>
67+
case tp: TypeAlias if theMap == null => // if theMap exists, need to do the variance calculation
6568
tp.derivedTypeAlias(asSeenFrom(tp.alias, pre, cls, theMap))
6669
case _ =>
6770
(if (theMap != null) theMap else new AsSeenFromMap(pre, cls))

src/dotty/tools/dotc/typer/FrontEnd.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import scala.util.control.NonFatal
1313
class FrontEnd extends Phase {
1414

1515
override def phaseName = "frontend"
16+
override def isTyper = true
1617

1718
def monitor(doing: String)(body: => Unit)(implicit ctx: Context) =
1819
try body

test/dotc/tests.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,14 @@ class tests extends CompilerTest {
133133
@Test def neg_i0091_infpaths = compileFile(negDir, "i0091-infpaths", xerrors = 3)
134134
@Test def neg_i0248_inherit_refined = compileFile(negDir, "i0248-inherit-refined", xerrors = 4)
135135
@Test def neg_i0281 = compileFile(negDir, "i0281-null-primitive-conforms", xerrors = 3)
136+
@Test def neg_i583 = compileFile(negDir, "i0583-skolemize", xerrors = 2)
136137
@Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4)
137138
@Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2)
138139
@Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8)
139140
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5)
140141

141-
142142
@Test def run_all = runFiles(runDir)
143143

144-
145144
@Test def dotty = compileDir(dottyDir, "tools", "-deep" :: allowDeepSubtypes ++ twice) // note the -deep argument
146145

147146

tests/neg/i0583-skolemize.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import scala.collection.mutable.ListBuffer
2+
3+
object Test1 {
4+
5+
class Box[T](x: T)
6+
def box[T](x: T) = new Box[T](x)
7+
8+
class C[T] { def x: T = ???; def x_=(y: T): Unit = ??? }
9+
10+
val c: C[Int] = ???
11+
val d: C[Float] = ???
12+
13+
val xs: List[C[_]] = List(c, d)
14+
15+
xs(0).x = xs(1).x
16+
17+
}
18+
object Test {
19+
def main(args: Array[String]): Unit = {
20+
val f: ListBuffer[Int] = ListBuffer(1,2)
21+
val g: ListBuffer[Double] = ListBuffer(3.0,4.0)
22+
val lb: ListBuffer[ListBuffer[_]] = ListBuffer(f, g)
23+
lb(0)(0) = lb(1)(0)
24+
val x: Int = f(0)
25+
}
26+
}
27+

0 commit comments

Comments
 (0)