Skip to content

Commit 02c6f81

Browse files
committed
Refactor code: introduce ArgInfo instead of Value.source
1 parent d12ebde commit 02c6f81

File tree

1 file changed

+31
-44
lines changed

1 file changed

+31
-44
lines changed

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

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -57,28 +57,6 @@ class Semantic {
5757
*/
5858
sealed abstract class Value extends Cloneable {
5959
def show: String = this.toString()
60-
61-
/** Source code where the value originates from
62-
*
63-
* It is used for displaying friendly messages
64-
*/
65-
private var mySource: Tree = EmptyTree
66-
67-
def source: Tree = mySource
68-
69-
def attachSource(source: Tree): this.type =
70-
assert(mySource.isEmpty, "Update existing source of value " + this)
71-
mySource = source
72-
this
73-
74-
def withSource(source: Tree): Value =
75-
if mySource.isEmpty then attachSource(source)
76-
else if this == Hot || this == Cold then this
77-
else {
78-
val value2 = this.clone.asInstanceOf[Value]
79-
value2.mySource = source
80-
value2
81-
}
8260
}
8361

8462
/** A transitively initialized object */
@@ -265,13 +243,11 @@ class Semantic {
265243
def select(f: Symbol, source: Tree): Contextual[Result] =
266244
value.select(f, source) ++ errors
267245

268-
def call(meth: Symbol, args: List[Value], superType: Type, source: Tree): Contextual[Result] =
246+
def call(meth: Symbol, args: List[ArgInfo], superType: Type, source: Tree): Contextual[Result] =
269247
value.call(meth, args, superType, source) ++ errors
270248

271-
def instantiate(klass: ClassSymbol, ctor: Symbol, args: List[Value], source: Tree): Contextual[Result] =
249+
def instantiate(klass: ClassSymbol, ctor: Symbol, args: List[ArgInfo], source: Tree): Contextual[Result] =
272250
value.instantiate(klass, ctor, args, source) ++ errors
273-
274-
def withSource(source: Tree): Result = Result(value.withSource(source), errors)
275251
}
276252

277253
/** The state that threads through the interpreter */
@@ -379,8 +355,8 @@ class Semantic {
379355
}
380356
}
381357

382-
def call(meth: Symbol, args: List[Value], superType: Type, source: Tree, needResolve: Boolean = true): Contextual[Result] = log("call " + meth.show + ", args = " + args, printer, res => res.asInstanceOf[Result].show) {
383-
def checkArgs = args.flatMap { arg => arg.promote("May only use initialized value as arguments", arg.source) }
358+
def call(meth: Symbol, args: List[ArgInfo], superType: Type, source: Tree, needResolve: Boolean = true): Contextual[Result] = log("call " + meth.show + ", args = " + args, printer, res => res.asInstanceOf[Result].show) {
359+
def checkArgs = args.flatMap(_.promote)
384360

385361
// fast track if the current object is already initialized
386362
if promoted.isCurrentObjectPromoted then Result(Hot, Nil)
@@ -408,7 +384,7 @@ class Semantic {
408384
given Trace = trace1
409385
val cls = target.owner.enclosingClass.asClass
410386
val ddef = target.defTree.asInstanceOf[DefDef]
411-
val env2 = Env(ddef, args.widen)
387+
val env2 = Env(ddef, args.map(_.value).widen)
412388
if target.isPrimaryConstructor then
413389
given Env = env2
414390
val tpl = cls.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]
@@ -437,7 +413,7 @@ class Semantic {
437413
// meth == NoSymbol for poly functions
438414
if meth.name.toString == "tupled" then Result(value, Nil) // a call like `fun.tupled`
439415
else
440-
val env3 = Env(params.zip(args.widen).toMap).union(env2)
416+
val env3 = Env(params.zip(args.map(_.value).widen).toMap).union(env2)
441417
use(env3) {
442418
eval(body, thisV, klass, cacheResult = true)
443419
}
@@ -451,17 +427,17 @@ class Semantic {
451427
}
452428

453429
/** Handle a new expression `new p.C` where `p` is abstracted by `value` */
454-
def instantiate(klass: ClassSymbol, ctor: Symbol, args: List[Value], source: Tree): Contextual[Result] = log("instantiating " + klass.show + ", args = " + args, printer, res => res.asInstanceOf[Result].show) {
430+
def instantiate(klass: ClassSymbol, ctor: Symbol, args: List[ArgInfo], source: Tree): Contextual[Result] = log("instantiating " + klass.show + ", args = " + args, printer, res => res.asInstanceOf[Result].show) {
455431
val trace1 = trace.add(source)
456432
if promoted.isCurrentObjectPromoted then Result(Hot, Nil)
457433
else value match {
458434
case Hot =>
459435
val buffer = new mutable.ArrayBuffer[Error]
460436
val args2 = args.map { arg =>
461-
val errors = arg.promote("May only use initialized value as arguments", arg.source)
437+
val errors = arg.promote
462438
buffer ++= errors
463439
if errors.isEmpty then Hot
464-
else arg.widen
440+
else arg.value.widen
465441
}
466442

467443
if buffer.isEmpty then Result(Hot, Errors.empty)
@@ -485,7 +461,7 @@ class Semantic {
485461
case Warm(_, _: Warm, _, _) => Cold
486462
case _ => addr
487463

488-
val value = Warm(klass, outer, ctor, args.widen)
464+
val value = Warm(klass, outer, ctor, args.map(_.value).widen)
489465
if !heap.contains(value) then
490466
val obj = Objekt(klass, fields = mutable.Map.empty, outers = mutable.Map(klass -> outer))
491467
heap.update(value, obj)
@@ -616,7 +592,7 @@ class Semantic {
616592
val trace2 = trace.add(m.defTree)
617593
locally {
618594
given Trace = trace2
619-
val args = m.info.paramInfoss.flatten.map(_ => Hot)
595+
val args = m.info.paramInfoss.flatten.map(_ => ArgInfo(Hot, EmptyTree))
620596
val res = warm.call(m, args, superType = NoType, source = source)
621597
buffer ++= res.ensureHot(msg, source).errors
622598
}
@@ -643,6 +619,11 @@ class Semantic {
643619

644620
// ----- Semantic definition --------------------------------
645621

622+
/** Utility definition used for better error-reporting of argument errors */
623+
case class ArgInfo(value: Value, source: Tree) {
624+
def promote: Contextual[List[Error]] = value.promote("May only use initialized value as arguments", source)
625+
}
626+
646627
/** Evaluate an expression with the given value for `this` in a given class `klass`
647628
*
648629
* Note that `klass` might be a super class of the object referred by `thisV`.
@@ -678,15 +659,21 @@ class Semantic {
678659
exprs.map { expr => eval(expr, thisV, klass) }
679660

680661
/** Evaluate arguments of methods */
681-
def evalArgs(args: List[Arg], thisV: Addr, klass: ClassSymbol): Contextual[(List[Error], List[Value])] =
682-
val ress = args.map { arg =>
683-
if arg.isByName then
684-
val fun = Fun(arg.tree, Nil, thisV, klass, env)
685-
Result(fun, Nil).withSource(arg.tree)
686-
else
687-
eval(arg.tree, thisV, klass).withSource(arg.tree)
662+
def evalArgs(args: List[Arg], thisV: Addr, klass: ClassSymbol): Contextual[(List[Error], List[ArgInfo])] =
663+
val errors = new mutable.ArrayBuffer[Error]
664+
val argInfos = new mutable.ArrayBuffer[ArgInfo]
665+
args.foreach { arg =>
666+
val res =
667+
if arg.isByName then
668+
val fun = Fun(arg.tree, Nil, thisV, klass, env)
669+
Result(fun, Nil)
670+
else
671+
eval(arg.tree, thisV, klass)
672+
673+
errors ++= res.errors
674+
argInfos += ArgInfo(res.value, arg.tree)
688675
}
689-
(ress.flatMap(_.errors), ress.map(_.value))
676+
(errors.toList, argInfos.toList)
690677

691678
/** Handles the evaluation of different expressions
692679
*
@@ -939,7 +926,7 @@ class Semantic {
939926
printer.println(acc.show + " initialized with " + value)
940927
}
941928

942-
def superCall(tref: TypeRef, ctor: Symbol, args: List[Value], source: Tree)(using Env): Unit =
929+
def superCall(tref: TypeRef, ctor: Symbol, args: List[ArgInfo], source: Tree)(using Env): Unit =
943930
val cls = tref.classSymbol.asClass
944931
// update outer for super class
945932
val res = outerValue(tref, thisV, klass, source)

0 commit comments

Comments
 (0)