Skip to content

Commit 8043497

Browse files
Merge pull request #8414 from dotty-staging/fix-#8405
Give reasonable error messages when classfiles are not found
2 parents f6e057c + dbe86f5 commit 8043497

File tree

6 files changed

+50
-10
lines changed

6 files changed

+50
-10
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -832,9 +832,10 @@ object Denotations {
832832

833833
private def updateValidity()(implicit ctx: Context): this.type = {
834834
assert(
835-
ctx.runId >= validFor.runId ||
836-
ctx.settings.YtestPickler.value || // mixing test pickler with debug printing can travel back in time
837-
symbol.is(Permanent), // Permanent symbols are valid in all runIds
835+
ctx.runId >= validFor.runId
836+
|| ctx.settings.YtestPickler.value // mixing test pickler with debug printing can travel back in time
837+
|| ctx.mode.is(Mode.Printing) // no use to be picky when printing error messages
838+
|| symbol.isOneOf(ValidForeverFlags),
838839
s"denotation $this invalid in run ${ctx.runId}. ValidFor: $validFor")
839840
var d: SingleDenotation = this
840841
while ({

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ import config.Printers.cyclicErrors
1717

1818
class TypeError(msg: String) extends Exception(msg) {
1919
def this() = this("")
20-
def toMessage(implicit ctx: Context): Message = super.getMessage
20+
final def toMessage(implicit ctx: Context): Message =
21+
produceMessage(using ctx.addMode(Mode.Printing))
22+
def produceMessage(using Context): Message = super.getMessage
2123
override def getMessage: String = super.getMessage
2224
}
2325

2426
class MalformedType(pre: Type, denot: Denotation, absMembers: Set[Name]) extends TypeError {
25-
override def toMessage(implicit ctx: Context): Message =
27+
override def produceMessage(implicit ctx: Context): Message =
2628
i"malformed type: $pre is not a legal prefix for $denot because it contains abstract type member${if (absMembers.size == 1) "" else "s"} ${absMembers.mkString(", ")}"
2729
}
2830

@@ -33,7 +35,7 @@ class MissingType(pre: Type, name: Name) extends TypeError {
3335
case _ => ""
3436
}
3537

36-
override def toMessage(implicit ctx: Context): Message = {
38+
override def produceMessage(implicit ctx: Context): Message = {
3739
if (ctx.debug) printStackTrace()
3840
i"""cannot resolve reference to type $pre.$name
3941
|the classfile defining the type might be missing from the classpath${otherReason(pre)}"""
@@ -67,7 +69,7 @@ class RecursionOverflow(val op: String, details: => String, val previous: Throwa
6769
(rs.map(_.explanation): List[String]).mkString("\n ", "\n| ", "")
6870
}
6971

70-
override def toMessage(implicit ctx: Context): Message = {
72+
override def produceMessage(implicit ctx: Context): Message = {
7173
val mostCommon = recursions.groupBy(_.op).toList.maxBy(_._2.map(_.weight).sum)._2.reverse
7274
s"""Recursion limit exceeded.
7375
|Maybe there is an illegal cyclic reference?
@@ -109,7 +111,7 @@ object handleRecursive {
109111
class CyclicReference private (val denot: SymDenotation) extends TypeError {
110112
var inImplicitSearch: Boolean = false
111113

112-
override def toMessage(implicit ctx: Context): Message = {
114+
override def produceMessage(implicit ctx: Context): Message = {
113115
val cycleSym = denot.symbol
114116

115117
// cycleSym.flags would try completing denot and would fail, but here we can use flagsUNSAFE to detect flags
@@ -182,7 +184,7 @@ class MergeError(val sym1: Symbol, val sym2: Symbol, val tp1: Type, val tp2: Typ
182184
s"\nas members of $owner"
183185
}
184186

185-
override def toMessage(implicit ctx: Context): Message = {
187+
override def produceMessage(implicit ctx: Context): Message = {
186188
if (ctx.debug) printStackTrace()
187189
i"""cannot merge
188190
| ${showSymbol(sym1)} of type ${showType(tp1)} and

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,8 @@ class TreePickler(pickler: TastyPickler) {
606606
}
607607
}
608608
catch {
609+
case ex: TypeError =>
610+
ctx.error(ex.toMessage, tree.sourcePos.focus)
609611
case ex: AssertionError =>
610612
println(i"error when pickling tree $tree")
611613
throw ex

compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class NoExplanation(val msg: String) extends Message(ErrorMessageID.NoExplanatio
124124
val explanation: String = ""
125125
val kind: String = ""
126126

127-
override def toString(): String = s"NoExplanation($msg)"
127+
override def toString(): String = msg
128128
}
129129

130130
/** The extractor for `NoExplanation` can be used to check whether any error

tests/neg/i6501.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import scala.collection.immutable.HashMap
2+
3+
trait MapImpl {
4+
type Key
5+
type Value
6+
type Map
7+
val lookup: Map => Key => Value
8+
}
9+
class HashMapImpl[K, V] extends MapImpl {
10+
type Key = K
11+
type Value = V
12+
type Map = HashMap[K, V]
13+
val lookup: Map => Key => Value = m => k => m(k)
14+
}
15+
object Foo {
16+
val Server0:
17+
(mImpl: MapImpl) => mImpl.Map => mImpl.Key => mImpl.Value
18+
= mImpl => mImpl.lookup
19+
val Client:
20+
(server: (mImpl: MapImpl & {type Key = String} & {type Value = Int}) => mImpl.Map => String => Int) => Int =
21+
// server => server(??? : (HashMapImpl[String, Int]))(???)("test lookup key") //works
22+
// server => server(HashMapImpl[String, Int])(???)("") //works
23+
server => server(???)(???)("test lookup key") // error
24+
}

tests/neg/i8405.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class ActorRef
2+
trait ActorEventBus {
3+
type Subscriber = ActorRef
4+
}
5+
trait ManagedActorClassification { this: ActorEventBus =>
6+
def unsubscribe(subscriber: Subscriber): Unit = ???
7+
}
8+
class ActorClassificationUnsubscriber(bus: ManagedActorClassification) {
9+
val actor = ???
10+
bus.unsubscribe(actor) // error
11+
}

0 commit comments

Comments
 (0)