@@ -913,7 +913,7 @@ class Objects(using Context @constructorOnly):
913
913
914
914
/**
915
915
* Handle new expression `new p.C(args)`.
916
- * The actual instance might be cached without running the constructor.
916
+ * The actual instance might be cached without running the constructor.
917
917
* See tests/init-global/pos/cache-constructor.scala
918
918
*
919
919
* @param outer The value for `p`.
@@ -1229,11 +1229,12 @@ class Objects(using Context @constructorOnly):
1229
1229
extendTrace(id) { evalType(prefix, thisV, klass) }
1230
1230
1231
1231
val value = eval(rhs, thisV, klass)
1232
+ val widened = widenEscapedValue(value, rhs)
1232
1233
1233
1234
if isLocal then
1234
- writeLocal(thisV, lhs.symbol, value )
1235
+ writeLocal(thisV, lhs.symbol, widened )
1235
1236
else
1236
- withTrace(trace2) { assign(receiver, lhs.symbol, value , rhs.tpe) }
1237
+ withTrace(trace2) { assign(receiver, lhs.symbol, widened , rhs.tpe) }
1237
1238
1238
1239
case closureDef(ddef) =>
1239
1240
Fun (ddef, thisV, klass, summon[Env .Data ])
@@ -1571,6 +1572,36 @@ class Objects(using Context @constructorOnly):
1571
1572
throw new Exception (" unexpected type: " + tp + " , Trace:\n " + Trace .show)
1572
1573
}
1573
1574
1575
+ /** Widen the escaped value (a method argument or rhs of an assignment)
1576
+ *
1577
+ * The default widening is 1 for most values, 2 for function values.
1578
+ * User-specified widening annotations are repected.
1579
+ */
1580
+ def widenEscapedValue (value : Value , annotatedTree : Tree ): Contextual [Value ] =
1581
+ def parseAnnotation : Option [Int ] =
1582
+ annotatedTree.tpe.getAnnotation(defn.InitWidenAnnot ).flatMap: annot =>
1583
+ annot.argument(0 ).get match
1584
+ case arg @ Literal (c : Constants .Constant ) =>
1585
+ val height = c.intValue
1586
+ if height < 0 then
1587
+ report.warning(" The argument should be positive" , arg)
1588
+ None
1589
+ else
1590
+ Some (height)
1591
+ case arg =>
1592
+ report.warning(" The argument should be a constant integer value" , arg)
1593
+ None
1594
+ end parseAnnotation
1595
+
1596
+ parseAnnotation match
1597
+ case Some (i) =>
1598
+ value.widen(i)
1599
+
1600
+ case None =>
1601
+ if value.isInstanceOf [Fun ]
1602
+ then value.widen(2 )
1603
+ else value.widen(1 )
1604
+
1574
1605
/** Evaluate arguments of methods and constructors */
1575
1606
def evalArgs (args : List [Arg ], thisV : ThisValue , klass : ClassSymbol ): Contextual [List [ArgInfo ]] =
1576
1607
val argInfos = new mutable.ArrayBuffer [ArgInfo ]
@@ -1581,23 +1612,7 @@ class Objects(using Context @constructorOnly):
1581
1612
else
1582
1613
eval(arg.tree, thisV, klass)
1583
1614
1584
- val widened =
1585
- arg.tree.tpe.getAnnotation(defn.InitWidenAnnot ) match
1586
- case Some (annot) =>
1587
- annot.argument(0 ).get match
1588
- case arg @ Literal (c : Constants .Constant ) =>
1589
- val height = c.intValue
1590
- if height < 0 then
1591
- report.warning(" The argument should be positive" , arg)
1592
- res.widen(1 )
1593
- else
1594
- res.widen(c.intValue)
1595
- case arg =>
1596
- report.warning(" The argument should be a constant integer value" , arg)
1597
- res.widen(1 )
1598
- case _ =>
1599
- if res.isInstanceOf [Fun ] then res.widen(2 ) else res.widen(1 )
1600
-
1615
+ val widened = widenEscapedValue(res, arg.tree)
1601
1616
argInfos += ArgInfo (widened, trace.add(arg.tree), arg.tree)
1602
1617
}
1603
1618
argInfos.toList
0 commit comments