Objects
Check initialization safety of static objects
The problem is illustrated by the example below:
class Foo(val opposite: Foo)
case object A extends Foo(B) // A -> B
case object B extends Foo(A) // B -> A
In the code above, the initialization of object A
depends on B
and vice versa. There is no correct way to initialize the code above. The current checker issues a warning for the code above.
At the high-level, the analysis has the following characteristics:
-
The check enforces the principle of "initialization-time irrelevance", which means that the time when an object is initialized should not change program semantics. For that purpose, it enforces the following rule:
The initialization of a static object should not directly or indirectly read or write mutable state of another static object.
This principle not only put initialization of static objects on a solid foundation, but also avoids whole-program analysis.
-
It is inter-procedural and flow-sensitive.
-
The check is modular in the sense that each object is checked separately and there is no whole-program analysis. However, the check is not modular in terms of project boundaries.
Attributes
- Graph
-
- Supertypes
Members list
Type members
Classlikes
Attributes
- Supertypes
Represents a lambda expression
Represents a lambda expression
Value parameters
- klass
-
The enclosing class of the anonymous function's creation site
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalstrait ValueElementtrait Valueclass Objecttrait Matchableclass AnyShow all
Attributes
- Supertypes
- Known subtypes
-
object given_Join_ScopeSetobject given_Join_Value
A reference to a static object
A reference to a static object
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Reftrait ValueElementtrait Valueclass Scopeclass Objecttrait Matchableclass AnyShow all
Represents arrays.
Represents arrays.
Note that the 2nd parameter block does not take part in the definition of equality.
Different arrays are distinguished by the context. Currently the default context is the static object whose initialization triggers the creation of the array.
In the future, it is possible that we introduce a mechanism for end-users to mark the context.
Value parameters
- owner
-
The static object whose initialization creates the array.
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Reftrait ValueElementtrait Valueclass Scopeclass Objecttrait Matchableclass AnyShow all
Represents values that are instances of the specified class.
Represents values that are instances of the specified class.
Note that the 2nd parameter block does not take part in the definition of equality.
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Reftrait ValueElementtrait Valueclass Scopeclass Objecttrait Matchableclass AnyShow all
Represents common base values like Int, String, etc. Assumption: all methods calls on such values should not trigger initialization of global objects or read/write mutable fields
Represents common base values like Int, String, etc. Assumption: all methods calls on such values should not trigger initialization of global objects or read/write mutable fields
Attributes
- Companion
- object
- Supertypes
-
trait Serializabletrait Producttrait Equalstrait ValueElementtrait Valueclass Objecttrait Matchableclass AnyShow all
Attributes
- Supertypes
Represents values unknown to the checker, such as values loaded without source
Represents values unknown to the checker, such as values loaded without source
Attributes
- Supertypes
-
trait Singletontrait Producttrait Mirrortrait Serializabletrait Producttrait Equalstrait ValueElementtrait Valueclass Objecttrait Matchableclass AnyShow all
- Self type
-
UnknownValue.type
Syntax for the data structure abstraction used in abstract domain:
Syntax for the data structure abstraction used in abstract domain:
ve ::= ObjectRef(class) // global object | OfClass(class, ownerObject, ctor, regions) // instance of a class | OfArray(ownerObject, regions) // represents values of native array class in Array.scala | Fun(code, LocalEnv) // value elements that can be contained in ValueSet | SafeValue // values on which method calls and field accesses won't cause warnings. Int, String, etc. | UnknownValue // values whose source are unknown at compile time vs ::= ValueSet(ve) // set of abstract values Bottom ::= ValueSet(Empty) // unreachable code val ::= ve | vs | Package Ref ::= ObjectRef | OfClass | OfArray // values that represent a reference to some (global or instance) object ThisValue ::= Ref | Set(Ref) // possible values for 'this' LocalEnv(meth, ownerObject) // represents environments for methods or functions Scope ::= Ref | LocalEnv ScopeSet ::= Set(Scope)
valsMap = sym -> val // maps variables to their values outersMap = sym -> ScopeSet // maps the possible outer scopes for a corresponding (parent) class heap.MutableData = Scope -> (valsMap, outersMap) // heap is mutable
regions ::= List(sourcePosition)
Attributes
- Supertypes
- Known subtypes
-
class Packagetrait ValueElementclass Funclass Refclass ObjectRefclass OfArrayclass OfClassclass SafeValueobject UnknownValueclass ValueSetShow all
ValueElement are elements that can be contained in a ValueSet
Represents a set of values
Represents a set of values
It comes from if
expressions.
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalstrait Valueclass Objecttrait Matchableclass AnyShow all
Attributes
- Supertypes
- Self type
-
given_Join_ScopeSet.type
Attributes
- Supertypes
- Self type
-
given_Join_Value.type
Value members
Concrete methods
Handle assignment lhs.f = rhs
.
Handle assignment lhs.f = rhs
.
Value parameters
- field
-
The symbol of the target field.
- lhs
-
The value of the object to be mutated.
- rhs
-
The value to be assigned.
- rhsTyp
-
The type of the right-hand side.
Attributes
Handle method calls e.m(args)
.
Handle method calls e.m(args)
.
Value parameters
- args
-
Arguments of the method call (all parameter blocks flatten to a list).
- meth
-
The symbol of the target method (could be virtual or abstract method).
- needResolve
-
Whether the target of the call needs resolution?
- receiver
-
The type of the receiver.
- superType
-
The type of the super in a super call. NoType for non-super calls.
- value
-
The value for the receiver.
Attributes
Handle constructor calls <init>(args)
.
Handle constructor calls <init>(args)
.
Value parameters
- args
-
Arguments of the constructor call (all parameter blocks flatten to a list).
- ctor
-
The symbol of the target method.
- value
-
The value for the receiver.
Attributes
Handles the evaluation of different expressions
Handles the evaluation of different expressions
Note: Recursive call should go to eval
instead of cases
.
Value parameters
- expr
-
The expression to be evaluated.
- klass
-
The enclosing class where the expression
expr
is located. - thisV
-
The value for
C.this
whereC
is represented by the parameterklass
.
Attributes
Evaluate an expression with the given value for this
in a given class klass
Evaluate an expression with the given value for this
in a given class klass
Note that klass
might be a super class of the object referred by thisV
. The parameter klass
is needed for this
resolution. Consider the following code:
class A { A.this class B extends A { A.this } }
As can be seen above, the meaning of the expression A.this
depends on where it is located.
This method only handles cache logic and delegates the work to cases
.
Value parameters
- cacheResult
-
It is used to reduce the size of the cache.
- expr
-
The expression to be evaluated.
- klass
-
The enclosing class where the expression is located.
- thisV
-
The value for
C.this
whereC
is represented by the parameterklass
.
Attributes
Evaluate arguments of methods and constructors
Evaluate arguments of methods and constructors
Attributes
Evaluate a list of expressions
Evaluate a list of expressions
Attributes
Handle semantics of leaf nodes
Handle semantics of leaf nodes
For leaf nodes, their semantics is determined by their types.
Value parameters
- elideObjectAccess
-
Whether object access should be omitted. Object access elission happens when the object access is used as a prefix in
new o.C
andC
does not need an outer. - klass
-
The enclosing class where the type
tp
is located. - thisV
-
The value for
C.this
whereC
is represented byklass
. - tp
-
The type to be evaluated.
Attributes
Initialize part of an abstract object in klass
of the inheritance chain
Initialize part of an abstract object in klass
of the inheritance chain
Value parameters
- klass
-
The class to which the template belongs.
- thisV
-
The value of the current object to be initialized.
- tpl
-
The class body to be evaluated.
Attributes
Handle local variable definition, val x = e
or var x = e
.
Handle local variable definition, val x = e
or var x = e
.
Value parameters
- sym
-
The symbol of the variable.
- value
-
The value of the initializer.
Attributes
Handle new expression new p.C(args)
. The actual instance might be cached without running the constructor. See tests/init-global/pos/cache-constructor.scala
Handle new expression new p.C(args)
. The actual instance might be cached without running the constructor. See tests/init-global/pos/cache-constructor.scala
Value parameters
- args
-
The arguments passsed to the constructor.
- ctor
-
The symbol of the target constructor.
- klass
-
The symbol of the class
C
. - outer
-
The value for
p
.
Attributes
Compute the outer value that corresponds to tref.prefix
Compute the outer value that corresponds to tref.prefix
Value parameters
- klass
-
The enclosing class where the type
tref
is located. - thisV
-
The value for
C.this
whereC
is represented by the parameterklass
. - tref
-
The type whose prefix is to be evaluated.
Attributes
Evaluate the cases against the scrutinee value.
Evaluate the cases against the scrutinee value.
It returns the scrutinee in most cases. The main effect of the function is for its side effects of adding bindings to the environment.
See https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html
Value parameters
- cases
-
The cases to match.
- klass
-
The enclosing class where the type
tp
is located. - scrutinee
-
The abstract value of the scrutinee.
- thisV
-
The value for
C.this
whereC
is represented byklass
.
Attributes
Read local variable x
.
Read local variable x
.
Value parameters
- sym
-
The symbol of the variable.
- thisV
-
The value for
this
where the variable is used.
Attributes
Resolve C.this that appear in D.this
Resolve C.this that appear in D.this
Value parameters
- elideObjectAccess
-
Whether object access should be omitted. Object access elision happens when the object access is used as a prefix in
new o.C
andC
does not need an outer. - target
-
The class symbol for
C
for whichC.this
is to be resolved. - thisV
-
The value for
D.this
.
Attributes
Resolve C.this by recursively searching through the outer chain
Resolve C.this by recursively searching through the outer chain
Value parameters
- scopeSet
-
The scopes as the starting point.
- target
-
The class symbol for
C
for whichC.this
is to be resolved.
Attributes
Handle selection e.f
.
Handle selection e.f
.
Value parameters
- field
-
The symbol of the target field (could be virtual or abstract).
- needResolve
-
Whether the target of the selection needs resolution?
- receiver
-
The type of the receiver.
- value
-
The value for the receiver.
Attributes
Handle local variable assignmenbt, x = e
.
Handle local variable assignmenbt, x = e
.
Value parameters
- sym
-
The symbol of the variable.
- thisV
-
The value for
this
where the assignment locates. - value
-
The value of the rhs of the assignment.
Attributes
Concrete fields
Check if the checker option reports warnings about unknown code
Check if the checker option reports warnings about unknown code