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.
-
The design is based on the concept of "cold aliasing" --- a cold alias may not be actively used during initialization, i.e., it's forbidden to call methods or access fields of a cold alias. Method arguments are cold aliases by default unless specified to be sensitive. Method parameters captured in lambdas or inner classes are always cold aliases.
-
It is inter-procedural and flow-sensitive.
-
It is object-sensitive by default and parameter-sensitive on-demand.
-
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
- Self type
-
Objects.type
Members list
Type members
Classlikes
A cold alias which should not be used during initialization.
A cold alias which should not be used during initialization.
Cold is not ValueElement since RefSet containing Cold is equivalent to Cold
Attributes
- Supertypes
- Self type
-
Cold.type
Represents a lambda expression
Represents a lambda expression
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass ValueElementclass Valueclass Objecttrait Matchableclass AnyShow all
A reference to a static object
A reference to a static object
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Refclass ValueElementclass Valueclass 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
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass ValueElementclass Valueclass 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 Refclass ValueElementclass Valueclass Objecttrait Matchableclass AnyShow all
A reference caches the values for outers and immutable fields.
A reference caches the values for outers and immutable fields.
Attributes
- Supertypes
- Known subtypes
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, vs[outer], ctor, args, env) // instance of a class | OfArray(object[owner], regions) | Fun(..., env) // value elements that can be contained in ValueSet vs ::= ValueSet(ve) // set of abstract values Bottom ::= ValueSet(Empty) val ::= ve | Cold | vs // all possible abstract values in domain Ref ::= ObjectRef | OfClass // values that represent a reference to some (global or instance) object ThisValue ::= Ref | Cold // possible values for 'this'
refMap = Ref -> ( valsMap, varsMap, outersMap ) // refMap stores field informations of an object or instance valsMap = valsym -> val // maps immutable fields to their values varsMap = valsym -> addr // each mutable field has an abstract address outersMap = class -> val // maps outer objects to their values
arrayMap = OfArray -> addr // an array has one address that stores the join value of every element
heap = addr -> val // heap is mutable
env = (valsMap, Option[env]) // stores local variables in the residing method, and possibly outer environments
addr ::= localVarAddr(regions, valsym, owner) | fieldVarAddr(regions, valsym, owner) // independent of OfClass/ObjectRef | arrayAddr(regions, owner) // independent of array element type
regions ::= List(sourcePosition)
Attributes
- Supertypes
- Known subtypes
Represents a set of values
Represents a set of values
It comes from if
expressions.
Attributes
- Supertypes
-
trait Serializabletrait Producttrait Equalsclass Valueclass Objecttrait Matchableclass AnyShow all
Types
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)
.
Handle new expression new p.C(args)
.
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 klass
Resolve C.this that appear in klass
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. - klass
-
The enclosing class where the type
C.this
is located. - target
-
The class symbol for
C
for whichC.this
is to be resolved. - thisV
-
The value for
D.this
whereD
is represented by the parameterklass
.
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.