aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Typer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-12-11 19:59:04 +0100
committerMartin Odersky <odersky@gmail.com>2015-12-21 18:02:09 +0100
commit5103f1720a26ac16c2b6b8bde1fe5717b3e5b78f (patch)
treefb87b835ef95af91f5d9303d5f596285ac2b525b /src/dotty/tools/dotc/typer/Typer.scala
parent4163b249428d1f27843ecc4e5b7c9c7dac0698dd (diff)
downloaddotty-5103f1720a26ac16c2b6b8bde1fe5717b3e5b78f.tar.gz
dotty-5103f1720a26ac16c2b6b8bde1fe5717b3e5b78f.tar.bz2
dotty-5103f1720a26ac16c2b6b8bde1fe5717b3e5b78f.zip
Make asSeenFrom idempotent
Let asSeenFrom generate a marker annotated type for any unsafe instantiation. Then cleanup in typedSelect.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala34
1 files changed, 29 insertions, 5 deletions
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index e5509d50f..1747d1442 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -282,12 +282,35 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
checkValue(tree1, pt)
}
+ private def typedSelect(tree: untpd.Select, pt: Type, qual: Tree)(implicit ctx: Context): Select =
+ healNonvariant(
+ checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt),
+ pt)
+
+ /** Let `tree = p.n` where `p: T`. If tree's type is an unsafe instantiation
+ * (see TypeOps#asSeenFrom for how this can happen), rewrite the prefix `p`
+ * to `(p: <unknown skolem of type T>)` and try again with the new (stable)
+ * prefix. If the result has another unsafe instantiation, raise an error.
+ */
+ private def healNonvariant[T <: Tree](tree: T, pt: Type)(implicit ctx: Context): T =
+ if (ctx.unsafeNonvariant == ctx.runId && tree.tpe.widen.hasUnsafeNonvariant)
+ tree match {
+ case tree @ Select(qual, _) if !qual.tpe.isStable =>
+ val alt = typedSelect(tree, pt, Typed(qual, TypeTree(SkolemType(qual.tpe.widen))))
+ /*typr.*/println(d"healed type: ${tree.tpe} --> $alt")
+ alt.asInstanceOf[T]
+ case _ =>
+ ctx.error(d"unsafe instantiation of type ${tree.tpe}", tree.pos)
+ tree
+ }
+ else tree
+
def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = track("typedSelect") {
def asSelect(implicit ctx: Context): Tree = {
val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this))
if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos)
- checkValue(assignType(cpy.Select(tree)(qual1, tree.name), qual1), pt)
- }
+ typedSelect(tree, pt, qual1)
+ }
def asJavaSelectFromTypeTree(implicit ctx: Context): Tree = {
// Translate names in Select/Ident nodes to type names.
@@ -382,7 +405,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
checkSimpleKinded(typedType(tree.tpt))
val expr1 =
if (isWildcard) tree.expr withType tpt1.tpe
- else typed(tree.expr, tpt1.tpe)
+ else typed(tree.expr, tpt1.tpe.widenSkolem)
assignType(cpy.Typed(tree)(expr1, tpt1), tpt1)
}
tree.expr match {
@@ -438,9 +461,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val setter = pre.member(setterName)
lhsCore match {
case lhsCore: RefTree if setter.exists =>
- val setterTypeRaw = pre select (setterName, setter)
+ val setterTypeRaw = pre.select(setterName, setter)
val setterType = ensureAccessible(setterTypeRaw, isSuperSelection(lhsCore), tree.pos)
- val lhs2 = untpd.rename(lhsCore, setterName).withType(setterType)
+ val lhs2 = healNonvariant(
+ untpd.rename(lhsCore, setterName).withType(setterType), WildcardType)
typedUnadapted(cpy.Apply(tree)(untpd.TypedSplice(lhs2), tree.rhs :: Nil))
case _ =>
reassignmentToVal