@@ -913,7 +913,7 @@ class Objects(using Context @constructorOnly):
913913
914914 /**
915915 * 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.
917917 * See tests/init-global/pos/cache-constructor.scala
918918 *
919919 * @param outer The value for `p`.
@@ -1229,11 +1229,12 @@ class Objects(using Context @constructorOnly):
12291229 extendTrace(id) { evalType(prefix, thisV, klass) }
12301230
12311231 val value = eval(rhs, thisV, klass)
1232+ val widened = widenEscapedValue(value, rhs)
12321233
12331234 if isLocal then
1234- writeLocal(thisV, lhs.symbol, value )
1235+ writeLocal(thisV, lhs.symbol, widened )
12351236 else
1236- withTrace(trace2) { assign(receiver, lhs.symbol, value , rhs.tpe) }
1237+ withTrace(trace2) { assign(receiver, lhs.symbol, widened , rhs.tpe) }
12371238
12381239 case closureDef(ddef) =>
12391240 Fun (ddef, thisV, klass, summon[Env .Data ])
@@ -1571,6 +1572,36 @@ class Objects(using Context @constructorOnly):
15711572 throw new Exception (" unexpected type: " + tp + " , Trace:\n " + Trace .show)
15721573 }
15731574
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+
15741605 /** Evaluate arguments of methods and constructors */
15751606 def evalArgs (args : List [Arg ], thisV : ThisValue , klass : ClassSymbol ): Contextual [List [ArgInfo ]] =
15761607 val argInfos = new mutable.ArrayBuffer [ArgInfo ]
@@ -1581,23 +1612,7 @@ class Objects(using Context @constructorOnly):
15811612 else
15821613 eval(arg.tree, thisV, klass)
15831614
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)
16011616 argInfos += ArgInfo (widened, trace.add(arg.tree), arg.tree)
16021617 }
16031618 argInfos.toList
0 commit comments