Skip to content

Commit 533ee8a

Browse files
committed
Widen values in assignment
1 parent 5e83606 commit 533ee8a

File tree

1 file changed

+26
-19
lines changed

1 file changed

+26
-19
lines changed

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

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,11 +1226,12 @@ class Objects(using Context @constructorOnly):
12261226
extendTrace(id) { evalType(prefix, thisV, klass) }
12271227

12281228
val value = eval(rhs, thisV, klass)
1229+
val widened = widenEscapedValue(value, rhs)
12291230

12301231
if isLocal then
1231-
writeLocal(thisV, lhs.symbol, value)
1232+
writeLocal(thisV, lhs.symbol, widened)
12321233
else
1233-
withTrace(trace2) { assign(receiver, lhs.symbol, value, rhs.tpe) }
1234+
withTrace(trace2) { assign(receiver, lhs.symbol, widened, rhs.tpe) }
12341235

12351236
case closureDef(ddef) =>
12361237
Fun(ddef, thisV, klass, summon[Env.Data])
@@ -1568,6 +1569,28 @@ class Objects(using Context @constructorOnly):
15681569
throw new Exception("unexpected type: " + tp + ", Trace:\n" + Trace.show)
15691570
}
15701571

1572+
/** Widen the escaped value (a method argument or rhs of an assignment)
1573+
*
1574+
* The default widening is 1 for most values, 2 for function values.
1575+
* User-specified widening annotations are repected.
1576+
*/
1577+
def widenEscapedValue(value: Value, expr: Tree): Contextual[Value] =
1578+
expr.tpe.getAnnotation(defn.InitWidenAnnot) match
1579+
case Some(annot) =>
1580+
annot.argument(0).get match
1581+
case arg @ Literal(c: Constants.Constant) =>
1582+
val height = c.intValue
1583+
if height < 0 then
1584+
report.warning("The argument should be positive", arg)
1585+
value.widen(1)
1586+
else
1587+
value.widen(c.intValue)
1588+
case arg =>
1589+
report.warning("The argument should be a constant integer value", arg)
1590+
value.widen(1)
1591+
case _ =>
1592+
if value.isInstanceOf[Fun] then value.widen(2) else value.widen(1)
1593+
15711594
/** Evaluate arguments of methods and constructors */
15721595
def evalArgs(args: List[Arg], thisV: ThisValue, klass: ClassSymbol): Contextual[List[ArgInfo]] =
15731596
val argInfos = new mutable.ArrayBuffer[ArgInfo]
@@ -1578,23 +1601,7 @@ class Objects(using Context @constructorOnly):
15781601
else
15791602
eval(arg.tree, thisV, klass)
15801603

1581-
val widened =
1582-
arg.tree.tpe.getAnnotation(defn.InitWidenAnnot) match
1583-
case Some(annot) =>
1584-
annot.argument(0).get match
1585-
case arg @ Literal(c: Constants.Constant) =>
1586-
val height = c.intValue
1587-
if height < 0 then
1588-
report.warning("The argument should be positive", arg)
1589-
res.widen(1)
1590-
else
1591-
res.widen(c.intValue)
1592-
case arg =>
1593-
report.warning("The argument should be a constant integer value", arg)
1594-
res.widen(1)
1595-
case _ =>
1596-
if res.isInstanceOf[Fun] then res.widen(2) else res.widen(1)
1597-
1604+
val widened = widenEscapedValue(res, arg.tree)
15981605
argInfos += ArgInfo(widened, trace.add(arg.tree), arg.tree)
15991606
}
16001607
argInfos.toList

0 commit comments

Comments
 (0)