@@ -93,7 +93,7 @@ class Objects(using Context @constructorOnly):
93
93
* | OfClass(class, vs[outer], ctor, args, env) // instance of a class
94
94
* | OfArray(object[owner], regions)
95
95
* | Fun(..., env) // value elements that can be contained in ValueSet
96
- * | BaseValue // Int, String, etc.
96
+ * | SafeValue // values on which method calls and fields won't cause warnings. Int, String, etc.
97
97
* vs ::= ValueSet(ve) // set of abstract values
98
98
* Bottom ::= ValueSet(Empty)
99
99
* val ::= ve | UnknownValue | vs | Package // all possible abstract values in domain
@@ -229,8 +229,9 @@ class Objects(using Context @constructorOnly):
229
229
230
230
/** Represents common base values like Int, String, etc.
231
231
*/
232
- case object BaseValue extends ValueElement :
233
- def show (using Context ): String = " BaseValue"
232
+ case object SafeValue extends ValueElement :
233
+ val safeTypes = defn.ScalaNumericValueTypeList ++ List (defn.UnitType , defn.BooleanType , defn.StringType )
234
+ def show (using Context ): String = " SafeValue"
234
235
235
236
/**
236
237
* Represents a set of values
@@ -703,7 +704,7 @@ class Objects(using Context @constructorOnly):
703
704
a match
704
705
case UnknownValue => UnknownValue
705
706
case Package (_) => a
706
- case BaseValue => BaseValue
707
+ case SafeValue => SafeValue
707
708
case ref : Ref => if ref.klass.isSubClass(klass) then ref else Bottom
708
709
case ValueSet (values) => values.map(v => v.filterClass(klass)).join
709
710
case arr : OfArray => if defn.ArrayClass .isSubClass(klass) then arr else Bottom
@@ -745,8 +746,8 @@ class Objects(using Context @constructorOnly):
745
746
report.warning(" [Internal error] Unexpected call on package = " + value.show + " , meth = " + meth.show + Trace .show, Trace .position)
746
747
Bottom
747
748
748
- case BaseValue =>
749
- if reportUnknown then UnknownValue else BaseValue
749
+ case SafeValue =>
750
+ SafeValue // Check return type, if not safe, try to analyze body, 1.until(2).map(i => UninitializedObject)
750
751
751
752
case Bottom =>
752
753
Bottom
@@ -773,7 +774,7 @@ class Objects(using Context @constructorOnly):
773
774
Bottom
774
775
else
775
776
// Array.length is OK
776
- BaseValue
777
+ SafeValue
777
778
778
779
case ref : Ref =>
779
780
val isLocal = ! meth.owner.isClass
@@ -794,10 +795,10 @@ class Objects(using Context @constructorOnly):
794
795
arr
795
796
else if target.equals(defn.Predef_classOf ) then
796
797
// Predef.classOf is a stub method in tasty and is replaced in backend
797
- BaseValue
798
+ SafeValue
798
799
else if target.equals(defn.ClassTagModule_apply ) then
799
800
// ClassTag and other reflection related values are considered safe
800
- BaseValue
801
+ SafeValue
801
802
else if target.hasSource then
802
803
val cls = target.owner.enclosingClass.asClass
803
804
val ddef = target.defTree.asInstanceOf [DefDef ]
@@ -911,8 +912,8 @@ class Objects(using Context @constructorOnly):
911
912
else
912
913
UnknownValue
913
914
914
- case BaseValue =>
915
- if reportUnknown then UnknownValue else BaseValue
915
+ case SafeValue =>
916
+ SafeValue
916
917
917
918
case Package (packageSym) =>
918
919
if field.isStaticObject then
@@ -996,7 +997,7 @@ class Objects(using Context @constructorOnly):
996
997
case arr : OfArray =>
997
998
report.warning(" [Internal error] unexpected tree in assignment, array = " + arr.show + " field = " + field + Trace .show, Trace .position)
998
999
999
- case BaseValue | UnknownValue =>
1000
+ case SafeValue | UnknownValue =>
1000
1001
report.warning(" Assigning to base or unknown value is forbidden. " + Trace .show, Trace .position)
1001
1002
1002
1003
case ValueSet (values) =>
@@ -1028,7 +1029,7 @@ class Objects(using Context @constructorOnly):
1028
1029
*/
1029
1030
def instantiate (outer : Value , klass : ClassSymbol , ctor : Symbol , args : List [ArgInfo ]): Contextual [Value ] = log(" instantiating " + klass.show + " , outer = " + outer + " , args = " + args.map(_.value.show), printer, (_ : Value ).show) {
1030
1031
outer.filterClass(klass.owner) match
1031
- case _ : Fun | _ : OfArray | BaseValue =>
1032
+ case _ : Fun | _ : OfArray | SafeValue =>
1032
1033
report.warning(" [Internal error] unexpected outer in instantiating a class, outer = " + outer.show + " , class = " + klass.show + " , " + Trace .show, Trace .position)
1033
1034
Bottom
1034
1035
@@ -1125,7 +1126,7 @@ class Objects(using Context @constructorOnly):
1125
1126
case UnknownValue =>
1126
1127
report.warning(" Calling on unknown value. " + Trace .show, Trace .position)
1127
1128
Bottom
1128
- case _ : ValueSet | _ : Ref | _ : OfArray | _ : Package | BaseValue =>
1129
+ case _ : ValueSet | _ : Ref | _ : OfArray | _ : Package | SafeValue =>
1129
1130
report.warning(" [Internal error] Unexpected by-name value " + value.show + " . " + Trace .show, Trace .position)
1130
1131
Bottom
1131
1132
else
@@ -1314,7 +1315,7 @@ class Objects(using Context @constructorOnly):
1314
1315
evalType(expr.tpe, thisV, klass)
1315
1316
1316
1317
case Literal (_) =>
1317
- BaseValue
1318
+ SafeValue
1318
1319
1319
1320
case Typed (expr, tpt) =>
1320
1321
if tpt.tpe.hasAnnotation(defn.UncheckedAnnot ) then
@@ -1600,7 +1601,7 @@ class Objects(using Context @constructorOnly):
1600
1601
1601
1602
// call .apply
1602
1603
val applyDenot = getMemberMethod(scrutineeType, nme.apply, applyType(elemType))
1603
- val applyRes = call(scrutinee, applyDenot.symbol, ArgInfo (BaseValue , summon[Trace ], EmptyTree ) :: Nil , scrutineeType, superType = NoType , needResolve = true )
1604
+ val applyRes = call(scrutinee, applyDenot.symbol, ArgInfo (SafeValue , summon[Trace ], EmptyTree ) :: Nil , scrutineeType, superType = NoType , needResolve = true )
1604
1605
1605
1606
if isWildcardStarArgList(pats) then
1606
1607
if pats.size == 1 then
@@ -1611,7 +1612,7 @@ class Objects(using Context @constructorOnly):
1611
1612
else
1612
1613
// call .drop
1613
1614
val dropDenot = getMemberMethod(scrutineeType, nme.drop, dropType(elemType))
1614
- val dropRes = call(scrutinee, dropDenot.symbol, ArgInfo (BaseValue , summon[Trace ], EmptyTree ) :: Nil , scrutineeType, superType = NoType , needResolve = true )
1615
+ val dropRes = call(scrutinee, dropDenot.symbol, ArgInfo (SafeValue , summon[Trace ], EmptyTree ) :: Nil , scrutineeType, superType = NoType , needResolve = true )
1615
1616
for pat <- pats.init do evalPattern(applyRes, pat)
1616
1617
evalPattern(dropRes, pats.last)
1617
1618
end if
@@ -1653,7 +1654,7 @@ class Objects(using Context @constructorOnly):
1653
1654
def evalType (tp : Type , thisV : ThisValue , klass : ClassSymbol , elideObjectAccess : Boolean = false ): Contextual [Value ] = log(" evaluating " + tp.show, printer, (_ : Value ).show) {
1654
1655
tp match
1655
1656
case _ : ConstantType =>
1656
- BaseValue
1657
+ SafeValue
1657
1658
1658
1659
case tmref : TermRef if tmref.prefix == NoPrefix =>
1659
1660
val sym = tmref.symbol
@@ -1903,7 +1904,7 @@ class Objects(using Context @constructorOnly):
1903
1904
resolveThis(target, ref.outerValue(klass), outerCls)
1904
1905
case ValueSet (values) =>
1905
1906
values.map(ref => resolveThis(target, ref, klass)).join
1906
- case _ : Fun | _ : OfArray | _ : Package | BaseValue =>
1907
+ case _ : Fun | _ : OfArray | _ : Package | SafeValue =>
1907
1908
report.warning(" [Internal error] unexpected thisV = " + thisV + " , target = " + target.show + " , klass = " + klass.show + Trace .show, Trace .position)
1908
1909
Bottom
1909
1910
}
0 commit comments