-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Global Initialization checker: Widen values in assignment #21512
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1226,11 +1226,12 @@ class Objects(using Context @constructorOnly): | |
extendTrace(id) { evalType(prefix, thisV, klass) } | ||
|
||
val value = eval(rhs, thisV, klass) | ||
val widened = widenEscapedValue(value, rhs) | ||
|
||
if isLocal then | ||
writeLocal(thisV, lhs.symbol, value) | ||
writeLocal(thisV, lhs.symbol, widened) | ||
else | ||
withTrace(trace2) { assign(receiver, lhs.symbol, value, rhs.tpe) } | ||
withTrace(trace2) { assign(receiver, lhs.symbol, widened, rhs.tpe) } | ||
|
||
case closureDef(ddef) => | ||
Fun(ddef, thisV, klass, summon[Env.Data]) | ||
|
@@ -1568,6 +1569,28 @@ class Objects(using Context @constructorOnly): | |
throw new Exception("unexpected type: " + tp + ", Trace:\n" + Trace.show) | ||
} | ||
|
||
/** Widen the escaped value (a method argument or rhs of an assignment) | ||
* | ||
* The default widening is 1 for most values, 2 for function values. | ||
* User-specified widening annotations are repected. | ||
*/ | ||
def widenEscapedValue(value: Value, expr: Tree): Contextual[Value] = | ||
expr.tpe.getAnnotation(defn.InitWidenAnnot) match | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This implements the default as 1 or 2 if there is no annotation, but the default when there is a malformed annotation is always 1. It would be cleaner to first compute the default widening level (1 or 2), and then do the parsing of the annotation, using that default widening level if annotation parsing fails. Even cleaner would be a function like: def parseAnnotation: Option[Int] that returns parseAnnotation match
case Some(i) => value.widen(i)
case None => if ... then value.widen(2) else value.widen(1) |
||
case Some(annot) => | ||
annot.argument(0).get match | ||
case arg @ Literal(c: Constants.Constant) => | ||
val height = c.intValue | ||
if height < 0 then | ||
report.warning("The argument should be positive", arg) | ||
value.widen(1) | ||
else | ||
value.widen(c.intValue) | ||
case arg => | ||
report.warning("The argument should be a constant integer value", arg) | ||
value.widen(1) | ||
case _ => | ||
if value.isInstanceOf[Fun] then value.widen(2) else value.widen(1) | ||
|
||
/** Evaluate arguments of methods and constructors */ | ||
def evalArgs(args: List[Arg], thisV: ThisValue, klass: ClassSymbol): Contextual[List[ArgInfo]] = | ||
val argInfos = new mutable.ArrayBuffer[ArgInfo] | ||
|
@@ -1578,23 +1601,7 @@ class Objects(using Context @constructorOnly): | |
else | ||
eval(arg.tree, thisV, klass) | ||
|
||
val widened = | ||
arg.tree.tpe.getAnnotation(defn.InitWidenAnnot) match | ||
case Some(annot) => | ||
annot.argument(0).get match | ||
case arg @ Literal(c: Constants.Constant) => | ||
val height = c.intValue | ||
if height < 0 then | ||
report.warning("The argument should be positive", arg) | ||
res.widen(1) | ||
else | ||
res.widen(c.intValue) | ||
case arg => | ||
report.warning("The argument should be a constant integer value", arg) | ||
res.widen(1) | ||
case _ => | ||
if res.isInstanceOf[Fun] then res.widen(2) else res.widen(1) | ||
|
||
val widened = widenEscapedValue(res, arg.tree) | ||
argInfos += ArgInfo(widened, trace.add(arg.tree), arg.tree) | ||
} | ||
argInfos.toList | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest renaming
expr
to something more specific such asannotatedTree
orannotationHost
.