Skip to content

Commit 081aa78

Browse files
committed
Refactor check
- Make summary a proper class - Rename isInternal to hasSource - Refactor: remove useless parameter - Split effect check into multiple methods - Refactor ignored methods handling Ignore constructor call on Any, Object and AnyVal - Fix missing return
1 parent fbff070 commit 081aa78

22 files changed

+457
-371
lines changed

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

Lines changed: 177 additions & 156 deletions
Large diffs are not rendered by default.

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,20 @@ import scala.collection.mutable
1818

1919
import Effects._, Potentials._, Summary._
2020

21-
implicit def theCtx(implicit env: Env): Context = env.ctx
21+
given theCtx(using Env): Context = summon[Env].ctx
2222

2323
case class Env(ctx: Context) {
2424
private implicit def self: Env = this
2525

26-
// Methods that should be ignored in the checking
27-
lazy val ignoredMethods: Set[Symbol] = Set(
28-
defn.Any_getClass,
29-
defn.Any_isInstanceOf,
30-
defn.Object_eq,
31-
defn.Object_ne,
32-
defn.Object_synchronized
33-
)
26+
/** Can the method call be ignored? */
27+
def canIgnoreMethod(symbol: Symbol): Boolean =
28+
!symbol.exists || // possible with outer selection, tests/init/crash/i1990b.scala
29+
canIgnoreClass(symbol.owner)
30+
31+
def canIgnoreClass(cls: Symbol): Boolean =
32+
cls == defn.AnyClass ||
33+
cls == defn.AnyValClass ||
34+
cls == defn.ObjectClass
3435

3536
def withCtx(newCtx: Context): Env = this.copy(ctx = newCtx)
3637

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import Types._, Symbols._, Contexts._
1212
import Effects._, Potentials._
1313

1414
object Errors {
15-
type Errors = Set[Error]
16-
val empty: Errors = Set.empty
15+
type Errors = List[Error]
16+
val empty: Errors = Nil
1717

1818
def show(errs: Errors)(using Context): String =
1919
errs.map(_.show).mkString(", ")
@@ -26,7 +26,7 @@ object Errors {
2626
def issue(using Context): Unit =
2727
report.warning(show + stacktrace, source.srcPos)
2828

29-
def toErrors: Errors = Set(this)
29+
def toErrors: Errors = this :: Nil
3030

3131
def stacktrace(using Context): String = if (trace.isEmpty) "" else " Calling trace:\n" + {
3232
var indentCount = 0
@@ -55,15 +55,15 @@ object Errors {
5555
*/
5656
def flatten: Errors = this match {
5757
case unsafe: UnsafePromotion => unsafe.errors.flatMap(_.flatten)
58-
case _ => Set(this)
58+
case _ => this :: Nil
5959
}
6060
}
6161

6262
/** Access non-initialized field */
6363
case class AccessNonInit(field: Symbol, trace: Vector[Tree]) extends Error {
6464
def source: Tree = trace.last
6565
def show(using Context): String =
66-
"Access non-initialized field " + field.name.show + "."
66+
"Access non-initialized " + field.show + "."
6767

6868
override def issue(using Context): Unit =
6969
report.warning(show + stacktrace, field.srcPos)

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

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,37 @@ object Potentials {
3333
def source: Tree
3434
}
3535

36-
/** The object pointed by `this` */
37-
case class ThisRef()(val source: Tree) extends Potential {
38-
def show(using Context): String = "this"
39-
36+
sealed trait Refinable extends Potential {
4037
/** Effects of a method call or a lazy val access
38+
*
39+
* The method performs prefix substitution
4140
*/
4241
def effectsOf(sym: Symbol)(implicit env: Env): Effects = trace("effects of " + sym.show, init, r => Effects.show(r.asInstanceOf)) {
4342
val cls = sym.owner.asClass
44-
env.summaryOf(cls).effectsOf(sym)
43+
val effs = env.summaryOf(cls).effectsOf(sym)
44+
this match
45+
case _: ThisRef => effs
46+
case _ => Effects.asSeenFrom(effs, this)
4547
}
4648

4749
/** Potentials of a field, a method call or a lazy val access
50+
*
51+
* The method performs prefix substitution
4852
*/
4953
def potentialsOf(sym: Symbol)(implicit env: Env): Potentials = trace("potentials of " + sym.show, init, r => Potentials.show(r.asInstanceOf)) {
5054
val cls = sym.owner.asClass
51-
env.summaryOf(cls).potentialsOf(sym)
55+
val pots = env.summaryOf(cls).potentialsOf(sym)
56+
this match
57+
case _: ThisRef => pots
58+
case _ => Potentials.asSeenFrom(pots, this)
5259
}
5360
}
5461

62+
/** The object pointed by `this` */
63+
case class ThisRef()(val source: Tree) extends Refinable {
64+
def show(using Context): String = "this"
65+
}
66+
5567
/** The object pointed by `C.super.this`, mainly used for override resolution */
5668
case class SuperRef(pot: Potential, supercls: ClassSymbol)(val source: Tree) extends Potential {
5769
override def size: Int = pot.size
@@ -65,30 +77,10 @@ object Potentials {
6577
* @param classSymbol The concrete class of the object
6678
* @param outer The potential for `this` of the enclosing class
6779
*/
68-
case class Warm(classSymbol: ClassSymbol, outer: Potential)(val source: Tree) extends Potential {
80+
case class Warm(classSymbol: ClassSymbol, outer: Potential)(val source: Tree) extends Refinable {
6981
override def level: Int = 1 + outer.level
7082
def show(using Context): String = "Warm[" + classSymbol.show + ", outer = " + outer.show + "]"
7183

72-
/** Effects of a method call or a lazy val access
73-
*
74-
* The method performs prefix substitution
75-
*/
76-
def effectsOf(sym: Symbol)(implicit env: Env): Effects = trace("effects of " + sym.show, init, r => Effects.show(r.asInstanceOf)) {
77-
val cls = sym.owner.asClass
78-
val effs = env.summaryOf(cls).effectsOf(sym)
79-
Effects.asSeenFrom(effs, this)
80-
}
81-
82-
/** Potentials of a field, a method call or a lazy val access
83-
*
84-
* The method performs prefix substitution
85-
*/
86-
def potentialsOf(sym: Symbol)(implicit env: Env): Potentials = trace("potentials of " + sym.show, init, r => Potentials.show(r.asInstanceOf)) {
87-
val cls = sym.owner.asClass
88-
val pots = env.summaryOf(cls).potentialsOf(sym)
89-
Potentials.asSeenFrom(pots, this)
90-
}
91-
9284
def resolveOuter(cls: ClassSymbol)(implicit env: Env): Potentials =
9385
env.resolveOuter(this, cls)
9486
}
@@ -118,7 +110,7 @@ object Potentials {
118110
case class Outer(pot: Potential, classSymbol: ClassSymbol)(val source: Tree) extends Potential {
119111
// be lenient with size of outer selection, no worry for non-termination
120112
override def size: Int = pot.size
121-
override def level: Int = pot.size
113+
override def level: Int = pot.level
122114
def show(using Context): String = pot.show + ".outer[" + classSymbol.show + "]"
123115
}
124116

@@ -127,7 +119,7 @@ object Potentials {
127119
assert(field != NoSymbol)
128120

129121
override def size: Int = potential.size + 1
130-
override def level: Int = potential.size
122+
override def level: Int = potential.level
131123
def show(using Context): String = potential.show + "." + field.name.show
132124
}
133125

@@ -136,7 +128,7 @@ object Potentials {
136128
assert(method != NoSymbol)
137129

138130
override def size: Int = potential.size + 1
139-
override def level: Int = potential.size
131+
override def level: Int = potential.level
140132
def show(using Context): String = potential.show + "." + method.name.show
141133
}
142134

@@ -164,20 +156,20 @@ object Potentials {
164156
extension (pot: Potential) def toPots: Potentials = Potentials.empty + pot
165157

166158
extension (ps: Potentials) def select (symbol: Symbol, source: Tree)(using Context): Summary =
167-
ps.foldLeft(Summary.empty) { case ((pots, effs), pot) =>
159+
ps.foldLeft(Summary.empty) { case (Summary(pots, effs), pot) =>
168160
// max potential length
169161
// TODO: it can be specified on a project basis via compiler options
170162
if (pot.size > 2)
171-
(pots, effs + Promote(pot)(source))
163+
summary + Promote(pot)(pot.source)
172164
else if (symbol.isConstructor)
173-
(pots + pot, effs + MethodCall(pot, symbol)(source))
165+
Summary(pots + pot, effs + MethodCall(pot, symbol)(source))
174166
else if (symbol.isOneOf(Flags.Method | Flags.Lazy))
175-
(
167+
Summary(
176168
pots + MethodReturn(pot, symbol)(source),
177169
effs + MethodCall(pot, symbol)(source)
178170
)
179171
else
180-
(pots + FieldReturn(pot, symbol)(source), effs + FieldAccess(pot, symbol)(source))
172+
Summary(pots + FieldReturn(pot, symbol)(source), effs + FieldAccess(pot, symbol)(source))
181173
}
182174

183175
extension (ps: Potentials) def promote(source: Tree): Effects = ps.map(Promote(_)(source))
@@ -206,13 +198,11 @@ object Potentials {
206198

207199
case Warm(cls, outer2) =>
208200
// widening to terminate
209-
val thisValue2 = thisValue match {
210-
case Warm(cls, outer) if outer.level > 2 =>
211-
Warm(cls, Cold()(outer2.source))(thisValue.source)
212-
213-
case _ =>
201+
val thisValue2 =
202+
if thisValue.level + outer2.level > 4 then
203+
Cold()(outer2.source)
204+
else
214205
thisValue
215-
}
216206

217207
val outer3 = asSeenFrom(outer2, thisValue2)
218208
Warm(cls, outer3)(pot.source)

0 commit comments

Comments
 (0)