Skip to content

Commit 1185acd

Browse files
committed
Refactor errors
1 parent 3ba4869 commit 1185acd

File tree

4 files changed

+42
-56
lines changed

4 files changed

+42
-56
lines changed

compiler/src/dotty/tools/dotc/transform/init/Errors.scala

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object Errors {
1818

1919
sealed trait Error {
2020
def source: Tree
21-
def trace: Vector[Tree]
21+
def trace: Seq[Tree]
2222
def show(using Context): String
2323

2424
def issue(using Context): Unit =
@@ -58,7 +58,7 @@ object Errors {
5858
}
5959

6060
/** Access non-initialized field */
61-
case class AccessNonInit(field: Symbol, trace: Vector[Tree]) extends Error {
61+
case class AccessNonInit(field: Symbol, trace: Seq[Tree]) extends Error {
6262
def source: Tree = trace.last
6363
def show(using Context): String =
6464
"Access non-initialized " + field.show + "."
@@ -68,48 +68,36 @@ object Errors {
6868
}
6969

7070
/** Promote `this` under initialization to fully-initialized */
71-
case class PromoteThis(source: Tree, trace: Vector[Tree]) extends Error {
72-
def show(using Context): String = "Promote the value under initialization to fully-initialized."
71+
case class PromoteError(msg: String, source: Tree, trace: Seq[Tree]) extends Error {
72+
def show(using Context): String = "Promote the value under initialization to fully-initialized. " + msg
7373
}
7474

75-
/** Promote `this` under initialization to fully-initialized */
76-
case class PromoteWarm(source: Tree, trace: Vector[Tree]) extends Error {
77-
def show(using Context): String =
78-
"Promoting the value under initialization to fully-initialized."
79-
}
80-
81-
/** Promote a cold value under initialization to fully-initialized */
82-
case class PromoteCold(source: Tree, trace: Vector[Tree]) extends Error {
83-
def show(using Context): String =
84-
"Promoting the value " + source.show + " to fully-initialized while it is under initialization" + "."
85-
}
86-
87-
case class AccessCold(field: Symbol, source: Tree, trace: Vector[Tree]) extends Error {
75+
case class AccessCold(field: Symbol, source: Tree, trace: Seq[Tree]) extends Error {
8876
def show(using Context): String =
8977
"Access field " + source.show + " on a value with an unknown initialization status" + "."
9078
}
9179

92-
case class CallCold(meth: Symbol, source: Tree, trace: Vector[Tree]) extends Error {
80+
case class CallCold(meth: Symbol, source: Tree, trace: Seq[Tree]) extends Error {
9381
def show(using Context): String =
9482
"Call method " + source.show + " on a value with an unknown initialization" + "."
9583
}
9684

97-
case class CallUnknown(meth: Symbol, source: Tree, trace: Vector[Tree]) extends Error {
85+
case class CallUnknown(meth: Symbol, source: Tree, trace: Seq[Tree]) extends Error {
9886
def show(using Context): String =
9987
val prefix = if meth.is(Flags.Method) then "Calling the external method " else "Accessing the external field"
10088
prefix + meth.show + " may cause initialization errors" + "."
10189
}
10290

10391
/** Promote a value under initialization to fully-initialized */
104-
case class UnsafePromotion(source: Tree, trace: Vector[Tree], errors: Errors) extends Error {
92+
case class UnsafePromotion(msg: String, source: Tree, trace: Seq[Tree], errors: Errors) extends Error {
10593
assert(errors.nonEmpty)
10694

10795
override def issue(using Context): Unit =
10896
report.warning(show, source.srcPos)
10997

11098
def show(using Context): String = {
11199
var index = 0
112-
"Promoting the value to fully-initialized is unsafe.\n" + stacktrace +
100+
"Promoting the value to fully-initialized is unsafe. " + msg + "\n" + stacktrace +
113101
"\nThe unsafe promotion may cause the following problem(s):\n" +
114102
(errors.flatMap(_.flatten).map { error =>
115103
index += 1

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ class Semantic {
168168
extension (trace: Trace)
169169
def add(node: Tree): Trace = trace :+ node
170170

171-
val noErrors = Nil
172-
173171
// ----- Operations on domains -----------------------------
174172
extension (a: Value)
175173
def join(b: Value): Value =
@@ -199,7 +197,7 @@ class Semantic {
199197
def select(field: Symbol, source: Tree): Contextual[Result] =
200198
value match {
201199
case Hot =>
202-
Result(Hot, noErrors)
200+
Result(Hot, Errors.empty)
203201

204202
case Cold =>
205203
val error = AccessCold(field, source, trace)
@@ -236,7 +234,7 @@ class Semantic {
236234
def call(meth: Symbol, superType: Type, source: Tree): Contextual[Result] =
237235
value match {
238236
case Hot =>
239-
Result(Hot, noErrors)
237+
Result(Hot, Errors.empty)
240238

241239
case Cold =>
242240
val error = CallCold(meth, source, trace)
@@ -306,7 +304,7 @@ class Semantic {
306304
def instantiate(klass: ClassSymbol, ctor: Symbol, source: Tree): Contextual[Result] =
307305
value match {
308306
case Hot =>
309-
Result(Hot, noErrors)
307+
Result(Hot, Errors.empty)
310308

311309
case Cold =>
312310
val error = CallCold(ctor, source, trace)
@@ -390,12 +388,12 @@ class Semantic {
390388
value match
391389
case Hot => Nil
392390

393-
case Cold => PromoteCold(source, trace) :: Nil
391+
case Cold => PromoteError(msg, source, trace) :: Nil
394392

395393
case thisRef: ThisRef =>
396394
if heap.promotedValues.contains(thisRef) then Nil
397395
else if thisRef.canPromoteExtrinsic then Nil
398-
else PromoteThis(source, trace) :: Nil
396+
else PromoteError(msg, source, trace) :: Nil
399397

400398
case warm: Warm =>
401399
if heap.promotedValues.contains(warm) then Nil
@@ -413,7 +411,7 @@ class Semantic {
413411
val res = eval(body, thisV, klass)
414412
val errors2 = res.value.promote(msg, source)
415413
if (res.errors.nonEmpty || errors2.nonEmpty)
416-
UnsafePromotion(source, trace, res.errors ++ errors2) :: Nil
414+
UnsafePromotion(msg, source, trace, res.errors ++ errors2) :: Nil
417415
else
418416
heap.promotedValues += fun
419417
Nil
@@ -443,7 +441,7 @@ class Semantic {
443441
def tryPromote(msg: String, source: Tree): Contextual[List[Error]] = log("promote " + warm.show, printer) {
444442
val classRef = warm.klass.appliedRef
445443
if classRef.memberClasses.nonEmpty then
446-
return PromoteWarm(source, trace) :: Nil
444+
return PromoteError(msg, source, trace) :: Nil
447445

448446
val fields = classRef.fields
449447
val methods = classRef.membersBasedOnFlags(Flags.Method, Flags.Deferred | Flags.Accessor)
@@ -466,7 +464,7 @@ class Semantic {
466464
}
467465

468466
if buffer.isEmpty then Nil
469-
else UnsafePromotion(source, trace, buffer.toList) :: Nil
467+
else UnsafePromotion(msg, source, trace, buffer.toList) :: Nil
470468
}
471469

472470
end extension
@@ -502,7 +500,7 @@ class Semantic {
502500
*/
503501
def eval(expr: Tree, thisV: Value, klass: ClassSymbol, cacheResult: Boolean = false): Contextual[Result] = log("evaluating " + expr.show + ", this = " + thisV.show, printer, res => res.asInstanceOf[Result].show) {
504502
val innerMap = cache.getOrElseUpdate(thisV, new EqHashMap[Tree, Value])
505-
if (innerMap.contains(expr)) Result(innerMap(expr), noErrors)
503+
if (innerMap.contains(expr)) Result(innerMap(expr), Errors.empty)
506504
else {
507505
// no need to compute fix-point, because
508506
// 1. the result is decided by `cfg` for a legal program
@@ -544,7 +542,7 @@ class Semantic {
544542
expr match {
545543
case Ident(nme.WILDCARD) =>
546544
// TODO: disallow `var x: T = _`
547-
Result(Hot, noErrors)
545+
Result(Hot, Errors.empty)
548546

549547
case id @ Ident(name) if !id.symbol.is(Flags.Method) =>
550548
assert(name.isTermName, "type trees should not reach here")
@@ -596,10 +594,10 @@ class Semantic {
596594
cases(expr.tpe, thisV, klass, expr)
597595

598596
case Literal(_) =>
599-
Result(Hot, noErrors)
597+
Result(Hot, Errors.empty)
600598

601599
case Typed(expr, tpt) =>
602-
if (tpt.tpe.hasAnnotation(defn.UncheckedAnnot)) Result(Hot, noErrors)
600+
if (tpt.tpe.hasAnnotation(defn.UncheckedAnnot)) Result(Hot, Errors.empty)
603601
else eval(expr, thisV, klass) ++ checkTermUsage(tpt, thisV, klass)
604602

605603
case NamedArg(name, arg) =>
@@ -609,9 +607,9 @@ class Semantic {
609607
lhs match
610608
case Select(qual, _) =>
611609
val res = eval(qual, thisV, klass)
612-
eval(rhs, thisV, klass).ensureHot("May only assign initialized value", rhs) ++ res.errors
610+
eval(rhs, thisV, klass).ensureHot("May only assign fully initialized value", rhs) ++ res.errors
613611
case id: Ident =>
614-
eval(rhs, thisV, klass).ensureHot("May only assign initialized value", rhs)
612+
eval(rhs, thisV, klass).ensureHot("May only assign fully initialized value", rhs)
615613

616614
case closureDef(ddef) =>
617615
thisV match
@@ -645,11 +643,11 @@ class Semantic {
645643
Result(value, errors)
646644

647645
case Annotated(arg, annot) =>
648-
if (expr.tpe.hasAnnotation(defn.UncheckedAnnot)) Result(Hot, noErrors)
646+
if (expr.tpe.hasAnnotation(defn.UncheckedAnnot)) Result(Hot, Errors.empty)
649647
else eval(arg, thisV, klass)
650648

651649
case Match(selector, cases) =>
652-
val res1 = eval(selector, thisV, klass).ensureHot("The value to be matched needs to be initialized", selector)
650+
val res1 = eval(selector, thisV, klass).ensureHot("The value to be matched needs to be fully initialized", selector)
653651
val ress = eval(cases.map(_.body), thisV, klass)
654652
val value = ress.map(_.value).join
655653
val errors = res1.errors ++ ress.flatMap(_.errors)
@@ -678,7 +676,7 @@ class Semantic {
678676

679677
case SeqLiteral(elems, elemtpt) =>
680678
val ress = elems.map { elem =>
681-
eval(elem, thisV, klass).ensureHot("May only use initialized value as arguments", elem)
679+
eval(elem, thisV, klass).ensureHot("May only use initialized value as method arguments", elem)
682680
}
683681
Result(Hot, ress.flatMap(_.errors))
684682

@@ -688,7 +686,7 @@ class Semantic {
688686

689687
case Thicket(List()) =>
690688
// possible in try/catch/finally, see tests/crash/i6914.scala
691-
Result(Hot, noErrors)
689+
Result(Hot, Errors.empty)
692690

693691
case vdef : ValDef =>
694692
// local val definition
@@ -697,11 +695,11 @@ class Semantic {
697695

698696
case ddef : DefDef =>
699697
// local method
700-
Result(Hot, noErrors)
698+
Result(Hot, Errors.empty)
701699

702700
case tdef: TypeDef =>
703701
// local type definition
704-
if tdef.isClassDef then Result(Hot, noErrors)
702+
if tdef.isClassDef then Result(Hot, Errors.empty)
705703
else Result(Hot, checkTermUsage(tdef.rhs, thisV, klass))
706704

707705
case tpl: Template =>
@@ -710,7 +708,7 @@ class Semantic {
710708
case _ => ??? // impossible
711709

712710
case _: Import | _: Export =>
713-
Result(Hot, noErrors)
711+
Result(Hot, Errors.empty)
714712

715713
case _ =>
716714
throw new Exception("unexpected tree: " + expr.show)
@@ -720,23 +718,23 @@ class Semantic {
720718
def cases(tp: Type, thisV: Value, klass: ClassSymbol, source: Tree): Contextual[Result] = log("evaluating " + tp.show, printer, res => res.asInstanceOf[Result].show) {
721719
tp match {
722720
case _: ConstantType =>
723-
Result(Hot, noErrors)
721+
Result(Hot, Errors.empty)
724722

725723
case tmref: TermRef if tmref.prefix == NoPrefix =>
726-
Result(Hot, noErrors)
724+
Result(Hot, Errors.empty)
727725

728726
case tmref: TermRef =>
729727
cases(tmref.prefix, thisV, klass, source).select(tmref.symbol, source)
730728

731729
case tp @ ThisType(tref) =>
732-
if tref.symbol.is(Flags.Package) then Result(Hot, noErrors)
730+
if tref.symbol.is(Flags.Package) then Result(Hot, Errors.empty)
733731
else
734732
val value = resolveThis(tref.classSymbol.asClass, thisV, klass, source)
735-
Result(value, noErrors)
733+
Result(value, Errors.empty)
736734

737735
case _: TermParamRef | _: RecThis =>
738736
// possible from checking effects of types
739-
Result(Hot, noErrors)
737+
Result(Hot, Errors.empty)
740738

741739
case _ =>
742740
throw new Exception("unexpected type: " + tp)
@@ -774,7 +772,7 @@ class Semantic {
774772
if tref.prefix == NoPrefix then
775773
val enclosing = cls.owner.lexicallyEnclosingClass.asClass
776774
val outerV = resolveThis(enclosing, thisV, klass, source)
777-
Result(outerV, noErrors)
775+
Result(outerV, Errors.empty)
778776
else
779777
cases(tref.prefix, thisV, klass, source)
780778

tests/init/neg/promotion-loop.check

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
-- Error: tests/init/neg/promotion-loop.scala:16:10 --------------------------------------------------------------------
22
16 | println(b) // error
33
| ^
4-
| Promoting the value to fully-initialized is unsafe.
4+
|Promoting the value to fully-initialized is unsafe. May only use initialized value as arguments
55
|
6-
| The unsafe promotion may cause the following problem(s):
6+
|The unsafe promotion may cause the following problem(s):
77
|
8-
| 1. Promote the value under initialization to fully-initialized. Calling trace:
9-
| -> val outer = test [ promotion-loop.scala:12 ]
8+
|1. Promote the value under initialization to fully-initialized. May only use initialized value as arguments Calling trace:
9+
| -> val outer = test [ promotion-loop.scala:12 ]

tests/init/neg/t3273.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- Error: tests/init/neg/t3273.scala:4:42 ------------------------------------------------------------------------------
22
4 | val num1: LazyList[Int] = 1 #:: num1.map(_ + 1) // error
33
| ^^^^^^^^^^^^^^^
4-
| Promoting the value to fully-initialized is unsafe.
4+
| Promoting the value to fully-initialized is unsafe. May only use initialized value as arguments
55
|
66
| The unsafe promotion may cause the following problem(s):
77
|
@@ -10,7 +10,7 @@
1010
-- Error: tests/init/neg/t3273.scala:5:61 ------------------------------------------------------------------------------
1111
5 | val num2: LazyList[Int] = 1 #:: num2.iterator.map(_ + 1).to(LazyList) // error
1212
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13-
| Promoting the value to fully-initialized is unsafe.
13+
| Promoting the value to fully-initialized is unsafe. May only use initialized value as arguments
1414
|
1515
| The unsafe promotion may cause the following problem(s):
1616
|

0 commit comments

Comments
 (0)