@@ -15,7 +15,7 @@ import util.NoSourcePosition
15
15
import reporting .trace
16
16
import config .Printers .init
17
17
18
- import Effects ._ , Potentials ._ , Summary ._ , Util ._
18
+ import Effects ._ , Potentials ._ , Summary ._ , Util ._ , Errors . _
19
19
20
20
object Checking {
21
21
/** The checking state
@@ -41,26 +41,6 @@ object Checking {
41
41
visited += eff
42
42
copy(path = this .path :+ eff.source)
43
43
}
44
-
45
- def trace (implicit state : State ): String = {
46
- var indentCount = 0
47
- var last = " "
48
- val sb = new StringBuilder
49
- this .path.foreach { tree =>
50
- indentCount += 1
51
- val pos = tree.sourcePos
52
- val line = " [ " + pos.source.file.name + " :" + (pos.line + 1 ) + " ]"
53
- if (last != line)
54
- sb.append(
55
- if (pos.source.exists)
56
- i " ${ " " * indentCount }-> ${pos.lineContent.trim}\t $line\n "
57
- else
58
- i " ${tree.show}\n "
59
- )
60
- last = line
61
- }
62
- sb.toString
63
- }
64
44
}
65
45
66
46
private implicit def theEnv (implicit state : State ): Env = state.env
@@ -158,66 +138,36 @@ object Checking {
158
138
}
159
139
}
160
140
161
- private def nonInitError (field : Symbol )(implicit state : State ) = {
162
- traceIndented(" initialized: " + state.fieldsInited, init)
163
-
164
- // should issue error, use warning so that it will continue compile subprojects
165
- theCtx.warning(
166
- " Access non-initialized field " + field.show +
167
- " . Calling trace:\n " + state.trace,
168
- field.sourcePos
169
- )
170
- }
171
-
172
- private def externalCallError (sym : Symbol , source : Tree )(implicit state : State ) =
173
- theCtx.warning(
174
- " Calling the external method " + sym.show +
175
- " may cause initialization errors" +
176
- " . Calling trace:\n " + state.trace,
177
- source.sourcePos
178
- )
179
-
180
141
private def checkEffectsIn (effs : Effects , cls : ClassSymbol )(implicit state : State ): Unit = {
181
142
val rebased = Effects .asSeenFrom(effs, ThisRef (state.thisClass)(null ), cls, Potentials .empty)
182
143
rebased.foreach { check(_) }
183
144
}
184
145
185
- private def check (eff : Effect )(implicit state : State ): Unit =
186
- if (! state.visited.contains(eff)) traceOp (" checking effect " + eff.show, init) {
146
+ private def check (eff : Effect )(implicit state : State ): Errors =
147
+ if (state.visited.contains(eff)) Errors .empty else trace (" checking effect " + eff.show, init, errs => Errors .show(errs. asInstanceOf [ Errors ]) ) {
187
148
implicit val state2 : State = state.withVisited(eff)
188
149
189
150
eff match {
190
151
case Promote (pot) =>
191
152
pot match {
192
- case ThisRef (cls) =>
153
+ case pot @ ThisRef (cls) =>
193
154
assert(cls == state.thisClass, " unexpected potential " + pot.show)
194
-
195
- theCtx.warning(
196
- " Promote `this` to be initialized while it is not. Calling trace:\n " + state.trace,
197
- eff.source.sourcePos
198
- )
155
+ PromoteThis (pot, eff.source, state.path).toErrors
199
156
200
157
case _ : Cold =>
201
- theCtx.warning(
202
- " Promoting the value " + eff.source.show + " to be initialized while it is under initialization" +
203
- " . Calling trace:\n " + state.trace,
204
- eff.source.sourcePos
205
- )
158
+ PromoteCold (eff.source, state.path).toErrors
206
159
207
- case Warm (cls, outer) =>
208
- theCtx.warning(
209
- " Promoting the value under initialization to be initialized: " + pot.source.show +
210
- " . Calling trace:\n " + state.trace,
211
- eff.source.sourcePos
212
- )
160
+ case pot @ Warm (cls, outer) =>
161
+ PromoteWarm (pot, eff.source, state.path).toErrors
213
162
214
163
case Fun (pots, effs) =>
215
- effs.foreach { check(_) }
216
- pots.foreach { pot => check(Promote (pot)(eff.source)) }
164
+ val errs1 = effs.flatMap { check(_) }
165
+ val errs2 = pots.flatMap { pot => check(Promote (pot)(eff.source)) }
166
+ UnsafePromotion (pot, eff.source, state.path, errs1 ++ errs2).toErrors
217
167
218
168
case pot =>
219
169
val pots = expand(pot)
220
- pots.foreach { pot => check(Promote (pot)(eff.source)) }
170
+ pots.flatMap { pot => check(Promote (pot)(eff.source)) }
221
171
}
222
172
223
173
case FieldAccess (pot, field) =>
@@ -228,33 +178,32 @@ object Checking {
228
178
229
179
val target = resolve(cls, field)
230
180
if (target.is(Flags .Lazy )) check(MethodCall (pot, target)(eff.source))
231
- else if (! state.fieldsInited.contains(target)) nonInitError(target)
181
+ else if (! state.fieldsInited.contains(target)) AccessNonInit (target, state.path).toErrors
182
+ else Errors .empty
232
183
233
184
case SuperRef (ThisRef (cls), supercls) =>
234
185
assert(cls == state.thisClass, " unexpected potential " + pot.show)
235
186
236
187
val target = resolveSuper(cls, supercls, field)
237
188
if (target.is(Flags .Lazy )) check(MethodCall (pot, target)(eff.source))
238
- else if (! state.fieldsInited.contains(target)) nonInitError(target)
189
+ else if (! state.fieldsInited.contains(target)) AccessNonInit (target, state.path).toErrors
190
+ else Errors .empty
239
191
240
192
case Warm (cls, outer) =>
241
193
// all fields of warm values are initialized
242
194
val target = resolve(cls, field)
243
195
if (target.is(Flags .Lazy )) check(MethodCall (pot, target)(eff.source))
196
+ else Errors .empty
244
197
245
198
case _ : Cold =>
246
- theCtx.warning(
247
- " Access field " + eff.source.show + " on a known value under initialization" +
248
- " . Calling trace:\n " + state.trace,
249
- eff.source.sourcePos
250
- )
199
+ AccessCold (field, eff.source, state.path).toErrors
251
200
252
201
case Fun (pots, effs) =>
253
202
throw new Exception (" Unexpected effect " + eff.show)
254
203
255
204
case pot =>
256
205
val pots = expand(pot)
257
- pots.foreach { pot => check(FieldAccess (pot, field)(eff.source)) }
206
+ pots.flatMap { pot => check(FieldAccess (pot, field)(eff.source)) }
258
207
}
259
208
260
209
case MethodCall (pot, sym) =>
@@ -267,9 +216,9 @@ object Checking {
267
216
check(FieldAccess (pot, target)(eff.source))
268
217
else if (target.isInternal) {
269
218
val effs = thisRef.effectsOf(target)
270
- effs.foreach { check(_) }
219
+ effs.flatMap { check(_) }
271
220
}
272
- else externalCallError (target, eff.source)
221
+ else CallUnknown (target, eff.source, state.path).toErrors
273
222
274
223
case SuperRef (thisRef @ ThisRef (cls), supercls) =>
275
224
assert(cls == state.thisClass, " unexpected potential " + pot.show)
@@ -279,37 +228,32 @@ object Checking {
279
228
check(FieldAccess (pot, target)(eff.source))
280
229
else if (target.isInternal) {
281
230
val effs = thisRef.effectsOf(target)
282
- effs.foreach { check(_) }
231
+ effs.flatMap { check(_) }
283
232
}
284
- else externalCallError (target, eff.source)
233
+ else CallUnknown (target, eff.source, state.path).toErrors
285
234
286
235
case warm @ Warm (cls, outer) =>
287
236
val target = resolve(cls, sym)
288
237
289
238
if (target.isInternal) {
290
239
val effs = warm.effectsOf(target)
291
- effs.foreach { check(_) }
240
+ effs.flatMap { check(_) }
292
241
}
293
- else if (! sym.isConstructor) externalCallError(target, eff.source)
242
+ else if (! sym.isConstructor) CallUnknown (target, eff.source, state.path).toErrors
243
+ else Errors .empty
294
244
295
245
case _ : Cold =>
296
- theCtx.warning(
297
- " Call method " + eff.source.show + " on a cold value" +
298
- " . Calling trace:\n " + state.trace,
299
- eff.source.sourcePos
300
- )
246
+ CallCold (sym, eff.source, state.path).toErrors
301
247
302
248
case Fun (pots, effs) =>
303
249
// TODO: assertion might be false, due to SAM
304
- if (sym.name.toString == " apply" ) {
305
- effs.foreach { check(_) }
306
- pots.foreach { pot => check(Promote (pot)(eff.source)) }
307
- }
250
+ if (sym.name.toString == " apply" ) effs.flatMap { check(_) }
251
+ else Errors .empty
308
252
// curried, tupled, toString are harmless
309
253
310
254
case pot =>
311
255
val pots = expand(pot)
312
- pots.foreach { pot =>
256
+ pots.flatMap { pot =>
313
257
check(MethodCall (pot, sym)(eff.source))
314
258
}
315
259
}
0 commit comments