Skip to content

Commit 18b8daa

Browse files
authored
Merge pull request #1817 from dotty-staging/fix-#1802
Fix #1802: Make sure errors are not swept under the carpet
2 parents 5df985c + 1f9990b commit 18b8daa

19 files changed

+102
-55
lines changed

compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
10241024
case JavaArrayType(elem) => elem
10251025
case _ =>
10261026
ctx.error(s"JavaSeqArray with type ${field.tpe} reached backend: $field", field.pos)
1027-
ErrorType
1027+
UnspecifiedErrorType
10281028
}
10291029
def _2: List[Tree] = field.elems
10301030
}

compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import dotty.tools.dotc.ast.tpd._
1212
import dotty.tools.dotc.core.Names.TermName
1313
import dotty.tools.dotc.core.StdNames
1414
import dotty.tools.dotc.core.StdNames._
15-
import dotty.tools.dotc.core.Types.{JavaArrayType, ErrorType, Type}
15+
import dotty.tools.dotc.core.Types.{JavaArrayType, UnspecifiedErrorType, Type}
1616

1717
import scala.collection.{ mutable, immutable }
1818

@@ -73,7 +73,7 @@ class DottyPrimitives(ctx: Context) {
7373
case JavaArrayType(el) => el
7474
case _ =>
7575
ctx.error(s"expected Array $tpe")
76-
ErrorType
76+
UnspecifiedErrorType
7777
}
7878

7979
code match {

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ object Trees {
113113
* type. (Overridden by empty trees)
114114
*/
115115
def withType(tpe: Type)(implicit ctx: Context): ThisTree[Type] = {
116-
if (tpe == ErrorType) assert(ctx.reporter.errorsReported)
116+
if (tpe.isInstanceOf[ErrorType]) assert(ctx.reporter.errorsReported)
117117
withTypeUnchecked(tpe)
118118
}
119119

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,12 +1937,12 @@ object SymDenotations {
19371937
/** A completer for missing references */
19381938
class StubInfo() extends LazyType {
19391939

1940-
def initializeToDefaults(denot: SymDenotation)(implicit ctx: Context) = {
1940+
def initializeToDefaults(denot: SymDenotation, errMsg: => String)(implicit ctx: Context) = {
19411941
denot.info = denot match {
19421942
case denot: ClassDenotation =>
19431943
ClassInfo(denot.owner.thisType, denot.classSymbol, Nil, EmptyScope)
19441944
case _ =>
1945-
ErrorType
1945+
new ErrorType(errMsg)
19461946
}
19471947
denot.privateWithin = NoSymbol
19481948
}
@@ -1954,13 +1954,14 @@ object SymDenotations {
19541954
if (file != null) (s" in $file", file.toString)
19551955
else ("", "the signature")
19561956
val name = ctx.fresh.setSetting(ctx.settings.debugNames, true).nameString(denot.name)
1957-
ctx.error(
1957+
def errMsg =
19581958
i"""bad symbolic reference. A signature$location
19591959
|refers to $name in ${denot.owner.showKind} ${denot.owner.showFullName} which is not available.
19601960
|It may be completely missing from the current classpath, or the version on
1961-
|the classpath might be incompatible with the version used when compiling $src.""")
1961+
|the classpath might be incompatible with the version used when compiling $src."""
1962+
ctx.error(errMsg)
19621963
if (ctx.debug) throw new Error()
1963-
initializeToDefaults(denot)
1964+
initializeToDefaults(denot, errMsg)
19641965
}
19651966
}
19661967

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import NameOps._
2222
import ast.tpd.Tree
2323
import ast.TreeTypeMap
2424
import Constants.Constant
25+
import reporting.diagnostic.Message
2526
import Denotations.{ Denotation, SingleDenotation, MultiDenotation }
2627
import collection.mutable
2728
import io.AbstractFile
@@ -290,9 +291,11 @@ trait Symbols { this: Context =>
290291
*/
291292
def newSkolem(tp: Type) = newSymbol(defn.RootClass, nme.SKOLEM, SyntheticArtifact | Permanent, tp)
292293

293-
def newErrorSymbol(owner: Symbol, name: Name) =
294+
def newErrorSymbol(owner: Symbol, name: Name, msg: => Message) = {
295+
val errType = new ErrorType(msg)
294296
newSymbol(owner, name, SyntheticArtifact,
295-
if (name.isTypeName) TypeAlias(ErrorType) else ErrorType)
297+
if (name.isTypeName) TypeAlias(errType) else errType)
298+
}
296299

297300
/** Map given symbols, subjecting their attributes to the mappings
298301
* defined in the given TreeTypeMap `ttmap`.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
265265
case ConstantType(v1) => v1.value == v2.value
266266
case _ => secondTry(tp1, tp2)
267267
}
268-
case ErrorType =>
268+
case _: FlexType =>
269269
true
270270
case _ =>
271271
secondTry(tp1, tp2)
@@ -341,7 +341,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
341341
false
342342
}
343343
joinOK || isSubType(tp11, tp2) && isSubType(tp12, tp2)
344-
case ErrorType =>
344+
case _: FlexType =>
345345
true
346346
case _ =>
347347
thirdTry(tp1, tp2)

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ object TypeErasure {
5555
tp.paramTypes.forall(isErasedType) && isErasedType(tp.resultType)
5656
case tp @ ClassInfo(pre, _, parents, decls, _) =>
5757
isErasedType(pre) && parents.forall(isErasedType) //&& decls.forall(sym => isErasedType(sym.info)) && isErasedType(tp.selfType)
58-
case NoType | NoPrefix | WildcardType | ErrorType | SuperType(_, _) =>
58+
case NoType | NoPrefix | WildcardType | _: ErrorType | SuperType(_, _) =>
5959
true
6060
case _ =>
6161
false
@@ -398,7 +398,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
398398
tp.derivedClassInfo(NoPrefix, parents, erasedDecls, erasedRef(tp.selfType))
399399
// can't replace selftype by NoType because this would lose the sourceModule link
400400
}
401-
case NoType | NoPrefix | ErrorType | JavaArrayType(_) =>
401+
case NoType | NoPrefix | _: ErrorType | JavaArrayType(_) =>
402402
tp
403403
case tp: WildcardType if wildcardOK =>
404404
tp
@@ -506,7 +506,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
506506
if (inst.exists) sigName(inst) else tpnme.Uninstantiated
507507
case tp: TypeProxy =>
508508
sigName(tp.underlying)
509-
case ErrorType | WildcardType =>
509+
case _: ErrorType | WildcardType =>
510510
tpnme.WILDCARD
511511
case tp: WildcardType =>
512512
sigName(tp.optBounds)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
433433
formals = formals.updated(name, tp1.typeParamNamed(name))
434434
}
435435
normalizeToRef(tp1)
436-
case ErrorType =>
436+
case _: ErrorType =>
437437
defn.AnyType
438438
case AnnotatedType(tpe, _) =>
439439
normalizeToRef(tpe)

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

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ import SymDenotations._
1515
import Decorators._
1616
import Denotations._
1717
import Periods._
18-
import util.Positions.Position
18+
import util.Positions.{Position, NoPosition}
1919
import util.Stats._
2020
import util.{DotClass, SimpleMap}
21+
import reporting.diagnostic.Message
2122
import ast.tpd._
2223
import ast.TreeTypeMap
2324
import printing.Texts._
@@ -176,7 +177,7 @@ object Types {
176177

177178
/** Is this type produced as a repair for an error? */
178179
final def isError(implicit ctx: Context): Boolean = stripTypeVar match {
179-
case ErrorType => true
180+
case _: ErrorType => true
180181
case tp => (tp.typeSymbol is Erroneous) || (tp.termSymbol is Erroneous)
181182
}
182183

@@ -387,8 +388,8 @@ object Types {
387388
tp.decls.denotsNamed(name).filterExcluded(excluded).toDenot(NoPrefix)
388389
case tp: TypeProxy =>
389390
tp.underlying.findDecl(name, excluded)
390-
case ErrorType =>
391-
ctx.newErrorSymbol(classSymbol orElse defn.RootClass, name)
391+
case err: ErrorType =>
392+
ctx.newErrorSymbol(classSymbol orElse defn.RootClass, name, err.msg)
392393
case _ =>
393394
NoDenotation
394395
}
@@ -453,8 +454,8 @@ object Types {
453454
go(tp.join)
454455
case tp: JavaArrayType =>
455456
defn.ObjectType.findMember(name, pre, excluded)
456-
case ErrorType =>
457-
ctx.newErrorSymbol(pre.classSymbol orElse defn.RootClass, name)
457+
case err: ErrorType =>
458+
ctx.newErrorSymbol(pre.classSymbol orElse defn.RootClass, name, err.msg)
458459
case _ =>
459460
NoDenotation
460461
}
@@ -1497,7 +1498,7 @@ object Types {
14971498
(lastDefRunId != sym.defRunId) ||
14981499
(lastDefRunId == NoRunId)
14991500
} ||
1500-
(lastSymbol.infoOrCompleter == ErrorType ||
1501+
(lastSymbol.infoOrCompleter.isInstanceOf[ErrorType] ||
15011502
sym.owner != lastSymbol.owner &&
15021503
(sym.owner.derivesFrom(lastSymbol.owner) ||
15031504
selfTypeOf(sym).derivesFrom(lastSymbol.owner) ||
@@ -2693,7 +2694,7 @@ object Types {
26932694
protected def checkInst(implicit ctx: Context): this.type = {
26942695
def check(tycon: Type): Unit = tycon.stripTypeVar match {
26952696
case tycon: TypeRef if !tycon.symbol.isClass =>
2696-
case _: PolyParam | ErrorType | _: WildcardType =>
2697+
case _: PolyParam | _: ErrorType | _: WildcardType =>
26972698
case _: PolyType =>
26982699
assert(args.exists(_.isInstanceOf[TypeBounds]), s"unreduced type apply: $this")
26992700
case tycon: AnnotatedType =>
@@ -3251,12 +3252,19 @@ object Types {
32513252
override def computeHash = hashSeed
32523253
}
32533254

3254-
abstract class ErrorType extends UncachedGroundType with ValueType
3255+
/** A common superclass of `ErrorType` and `TryDynamicCallSite`. Instances of this
3256+
* class are at the same time subtypes and supertypes of every other type.
3257+
*/
3258+
abstract class FlexType extends UncachedGroundType with ValueType
3259+
3260+
class ErrorType(_msg: => Message) extends FlexType {
3261+
val msg = _msg
3262+
}
32553263

3256-
object ErrorType extends ErrorType
3264+
object UnspecifiedErrorType extends ErrorType("unspecified error")
32573265

32583266
/* Type used to track Select nodes that could not resolve a member and their qualifier is a scala.Dynamic. */
3259-
object TryDynamicCallType extends ErrorType
3267+
object TryDynamicCallType extends FlexType
32603268

32613269
/** Wildcard type, possibly with bounds */
32623270
abstract case class WildcardType(optBounds: Type) extends CachedGroundType with TermType {

compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ object JavaParsers {
9090
if (skipIt)
9191
skip()
9292
}
93-
def errorTypeTree = TypeTree().withType(ErrorType) withPos Position(in.offset)
93+
94+
def errorTypeTree = TypeTree().withType(UnspecifiedErrorType) withPos Position(in.offset)
9495

9596
// --------- tree building -----------------------------
9697

compiler/src/dotty/tools/dotc/printing/Formatting.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ object Formatting {
9696
case tpe: Type =>
9797
tpe.exists && !tpe.isErroneous
9898
case sym: Symbol if sym.isCompleted =>
99-
sym.info != ErrorType && sym.info != TypeAlias(ErrorType) && sym.info.exists
99+
sym.info match {
100+
case _: ErrorType | TypeAlias(_: ErrorType) | NoType => false
101+
case _ => true
102+
}
100103
case _ => true
101104
}
102105

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
154154
changePrec(AndPrec) { toText(tp1) ~ " & " ~ toText(tp2) }
155155
case OrType(tp1, tp2) =>
156156
changePrec(OrPrec) { toText(tp1) ~ " | " ~ toText(tp2) }
157-
case ErrorType =>
157+
case _: ErrorType =>
158158
"<error>"
159159
case tp: WildcardType =>
160160
if (tp.optBounds.exists) "(?" ~ toTextRHS(tp.bounds) ~ ")" else "?"

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
561561
var typedArgs = typedArgBuf.toList
562562
def app0 = cpy.Apply(app)(normalizedFun, typedArgs) // needs to be a `def` because typedArgs can change later
563563
val app1 =
564-
if (!success) app0.withType(ErrorType)
564+
if (!success) app0.withType(UnspecifiedErrorType)
565565
else {
566566
if (!sameSeq(args, orderedArgs)) {
567567
// need to lift arguments to maintain evaluation order in the
@@ -654,7 +654,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
654654
}
655655

656656
fun1.tpe match {
657-
case ErrorType => untpd.cpy.Apply(tree)(fun1, tree.args).withType(ErrorType)
657+
case err: ErrorType => untpd.cpy.Apply(tree)(fun1, tree.args).withType(err)
658658
case TryDynamicCallType => typedDynamicApply(tree, pt)
659659
case _ =>
660660
tryEither {
@@ -918,7 +918,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
918918
case tp =>
919919
val unapplyErr = if (tp.isError) unapplyFn else notAnExtractor(unapplyFn)
920920
val typedArgsErr = args mapconserve (typed(_, defn.AnyType))
921-
cpy.UnApply(tree)(unapplyErr, Nil, typedArgsErr) withType ErrorType
921+
cpy.UnApply(tree)(unapplyErr, Nil, typedArgsErr) withType unapplyErr.tpe
922922
}
923923
}
924924

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ object Checking {
5656
def checkBounds(args: List[tpd.Tree], poly: PolyType)(implicit ctx: Context): Unit =
5757
checkBounds(args, poly.paramBounds, _.substParams(poly, _))
5858

59-
/** Check applied type trees for well-formedness. This means
59+
/** Check applied type trees for well-formedness. This means
6060
* - all arguments are within their corresponding bounds
6161
* - if type is a higher-kinded application with wildcard arguments,
6262
* check that it or one of its supertypes can be reduced to a normal application.
@@ -237,8 +237,7 @@ object Checking {
237237
catch {
238238
case ex: CyclicReference =>
239239
if (reportErrors) {
240-
ctx.error(i"illegal cyclic reference: ${checker.where} ${checker.lastChecked} of $sym refers back to the type itself", sym.pos)
241-
ErrorType
240+
errorType(i"illegal cyclic reference: ${checker.where} ${checker.lastChecked} of $sym refers back to the type itself", sym.pos)
242241
}
243242
else info
244243
}

compiler/src/dotty/tools/dotc/typer/Dynamic.scala

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import dotty.tools.dotc.core.Names.Name
1111
import dotty.tools.dotc.core.StdNames._
1212
import dotty.tools.dotc.core.Types._
1313
import dotty.tools.dotc.core.Decorators._
14+
import ErrorReporting._
1415

1516
object Dynamic {
1617
def isDynamicMethod(name: Name): Boolean =
@@ -41,10 +42,9 @@ trait Dynamic { self: Typer with Applications =>
4142
def isNamedArg(arg: untpd.Tree): Boolean = arg match { case NamedArg(_, _) => true; case _ => false }
4243
val args = tree.args
4344
val dynName = if (args.exists(isNamedArg)) nme.applyDynamicNamed else nme.applyDynamic
44-
if (dynName == nme.applyDynamicNamed && untpd.isWildcardStarArgList(args)) {
45-
ctx.error("applyDynamicNamed does not support passing a vararg parameter", tree.pos)
46-
tree.withType(ErrorType)
47-
} else {
45+
if (dynName == nme.applyDynamicNamed && untpd.isWildcardStarArgList(args))
46+
errorTree(tree, "applyDynamicNamed does not support passing a vararg parameter")
47+
else {
4848
def namedArgTuple(name: String, arg: untpd.Tree) = untpd.Tuple(List(Literal(Constant(name)), arg))
4949
def namedArgs = args.map {
5050
case NamedArg(argName, arg) => namedArgTuple(argName.toString, arg)
@@ -89,8 +89,7 @@ trait Dynamic { self: Typer with Applications =>
8989
case TypeApply(Select(qual, name), targs) if !isDynamicMethod(name) =>
9090
typedDynamicAssign(qual, name, targs)
9191
case _ =>
92-
ctx.error("reassignment to val", tree.pos)
93-
tree.withType(ErrorType)
92+
errorTree(tree, "reassignment to val")
9493
}
9594
}
9695

compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ object ErrorReporting {
2323

2424
def errorType(msg: => Message, pos: Position)(implicit ctx: Context): ErrorType = {
2525
ctx.error(msg, pos)
26-
ErrorType
26+
new ErrorType(msg)
2727
}
2828

2929
def cyclicErrorMsg(ex: CyclicReference)(implicit ctx: Context) = {

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,8 @@ trait TypeAssigner {
189189
val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else ""
190190
val whyNot = new StringBuffer
191191
alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot))
192-
if (!tpe.isError)
193-
ctx.error(ex"$what cannot be accessed as a member of $pre$where.$whyNot", pos)
194-
ErrorType
192+
if (tpe.isError) tpe
193+
else errorType(ex"$what cannot be accessed as a member of $pre$where.$whyNot", pos)
195194
}
196195
}
197196
else if (d.symbol is TypeParamAccessor)
@@ -215,17 +214,17 @@ trait TypeAssigner {
215214
else if (site.derivesFrom(defn.DynamicClass) && !Dynamic.isDynamicMethod(name)) {
216215
TryDynamicCallType
217216
} else {
218-
if (!site.isErroneous) {
217+
if (site.isErroneous) UnspecifiedErrorType
218+
else {
219219
def kind = if (name.isTypeName) "type" else "value"
220220
def addendum =
221221
if (site.derivesFrom(defn.DynamicClass)) "\npossible cause: maybe a wrong Dynamic method signature?"
222222
else ""
223-
ctx.error(
223+
errorType(
224224
if (name == nme.CONSTRUCTOR) ex"$site does not have a constructor"
225225
else NotAMember(site, name, kind),
226226
pos)
227227
}
228-
ErrorType
229228
}
230229
}
231230

0 commit comments

Comments
 (0)