Skip to content

Commit 1061743

Browse files
committed
Error instead of crash when sigName comes up with a missing reference.
A TypeRef can have be unresolved, either because it refers to something that's missing from the classpath or because of transitive self type references. Instead of crashing in sigName, we now report the error. Achieved by defining a new exception type, MissingType, which derives from TypeError. This catches t7933.scala, now integrated in the neg/selfreq.scala. The problem there was a reference to AbsSettings, which was not a member of StandardScalaSettings.this, but was a member of the required type of AbsSettings, which itself appeared in the required type of StandardScalaSettings. We will outlaw in the next commit such transitive required references. Also collapsed TypeError and FatalTypeError. It was a misnomer anyway. Fatal were those type errors that were caught and reported! Open: Where else we should check for unresolved NamedTypes.
1 parent c277b98 commit 1061743

File tree

5 files changed

+55
-6
lines changed

5 files changed

+55
-6
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
439439
case ErasedValueType(_, underlying) =>
440440
sigName(underlying)
441441
case tp: TypeRef =>
442+
if (!tp.denot.exists) throw new MissingType(tp.prefix, tp.name)
442443
val sym = tp.symbol
443444
if (!sym.isClass) sigName(tp.info)
444445
else if (isDerivedValueClass(sym)) sigName(eraseDerivedValueClassRef(tp))

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,7 @@ object Types {
936936
/** the self type of the underlying classtype */
937937
def givenSelfType(implicit ctx: Context): Type = this match {
938938
case tp @ RefinedType(parent, name) => tp.wrapIfMember(parent.givenSelfType)
939+
case tp: ThisType => tp.tref.givenSelfType
939940
case tp: TypeProxy => tp.underlying.givenSelfType
940941
case _ => NoType
941942
}
@@ -3181,14 +3182,23 @@ object Types {
31813182
// ----- Exceptions -------------------------------------------------------------
31823183

31833184
class TypeError(msg: String) extends Exception(msg)
3184-
class FatalTypeError(msg: String) extends TypeError(msg)
31853185

31863186
class MalformedType(pre: Type, denot: Denotation, absMembers: Set[Name])
3187-
extends FatalTypeError(
3188-
s"""malformed type: $pre is not a legal prefix for $denot because it contains abstract type member${if (absMembers.size == 1) "" else "s"} ${absMembers.mkString(", ")}""")
3187+
extends TypeError(
3188+
s"malformed type: $pre is not a legal prefix for $denot because it contains abstract type member${if (absMembers.size == 1) "" else "s"} ${absMembers.mkString(", ")}")
3189+
3190+
class MissingType(pre: Type, name: Name)(implicit ctx: Context) extends TypeError(
3191+
i"""cannot resolve reference to type $pre.$name
3192+
|the classfile defining the type might be missing from the classpath${otherReason(pre)}""".stripMargin)
3193+
3194+
private def otherReason(pre: Type)(implicit ctx: Context): String = pre match {
3195+
case pre: ThisType if pre.givenSelfType.exists =>
3196+
i"\nor the self type of $pre might not contain all transitive dependencies"
3197+
case _ => ""
3198+
}
31893199

31903200
class CyclicReference private (val denot: SymDenotation)
3191-
extends FatalTypeError(s"cyclic reference involving $denot") {
3201+
extends TypeError(s"cyclic reference involving $denot") {
31923202
def show(implicit ctx: Context) = s"cyclic reference involving ${denot.show}"
31933203
}
31943204

@@ -3204,7 +3214,7 @@ object Types {
32043214
}
32053215
}
32063216

3207-
class MergeError(msg: String) extends FatalTypeError(msg)
3217+
class MergeError(msg: String) extends TypeError(msg)
32083218

32093219
// ----- Debug ---------------------------------------------------------
32103220

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
10871087
try adapt(typedUnadapted(tree, pt), pt, tree)
10881088
catch {
10891089
case ex: CyclicReference => errorTree(tree, cyclicErrorMsg(ex))
1090-
case ex: FatalTypeError => errorTree(tree, ex.getMessage)
1090+
case ex: TypeError => errorTree(tree, ex.getMessage)
10911091
}
10921092
}
10931093

test/dotc/tests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ class tests extends CompilerTest {
139139
@Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2)
140140
@Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8)
141141
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5)
142+
@Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 4)
142143
@Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2)
143144
@Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5)
144145
@Test def neg_traitParamsMixin = compileFile(negDir, "traitParamsMixin", xerrors = 2)

tests/neg/selfreq.scala

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
trait X { self: Y =>
2+
3+
type T <: self.U
4+
5+
def foo(x: T): T
6+
def foo(x: String): String
7+
8+
}
9+
10+
trait Y { self: Z =>
11+
12+
type U <: self.V
13+
14+
}
15+
16+
trait Z {
17+
18+
class V
19+
20+
}
21+
22+
object O {
23+
val x: X = ???
24+
x.foo("a")
25+
}
26+
27+
import scala.tools.nsc.interpreter.IMain
28+
29+
object Test extends dotty.runtime.LegacyApp {
30+
val engine = new IMain.Factory getScriptEngine()
31+
engine.asInstanceOf[IMain].settings.usejavacp.value = true
32+
val res2 = engine.asInstanceOf[javax.script.Compilable]
33+
res2 compile "8" eval()
34+
val res5 = res2 compile """println("hello") ; 8"""
35+
res5 eval()
36+
res5 eval()
37+
}

0 commit comments

Comments
 (0)