49
Compilation 2011 Compilation 2011 Static Type Checking Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

Embed Size (px)

Citation preview

Page 1: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

Compilation 2011Compilation 2011

Static Type CheckingStatic Type Checking

Ian ZernyMichael I. Schwartzbach

Aarhus University

Page 2: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

2Static Type Checking

The Type CheckerThe Type Checker

The type checker has several tasks:• determine the types of all expressions• check that values and variables are used correctly• resolve certain ambiguities by transformations

Some languages have no type checker• no compile-time guarantees• runtime tagging and checking become necessary

Page 3: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

3Static Type Checking

Types Describe Possible ValuesTypes Describe Possible Values

The Joos types are:• void (the empty set of values)• byte• short • int • char• boolean• C (objects of class C or any subclass)• null (the polymorphic null constant)• σ[] (for any type σ)

Page 4: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

4Static Type Checking

Type AnnotationsType Annotations

Type annotations:

int x;

Foo y;

specify invariants about the runtime behavior:• x will always contain an integer value• y will always contain null or an object of class Foo or

any subclass thereof

Java-like Type annotations are (arguably) not very expressive viewed as invariants• Other type systems are more expressive

Page 5: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

5Static Type Checking

A program is type correct if the type annotations are valid invariants

Type correctness is trivially undecidable:

int x = 0;

TM(j);

x = false;

The program is type correct iff the j'th Turing machine does not halt on empty input

Type CorrectnessType Correctness

Page 6: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

6Static Type Checking

Static Type CorrectnessStatic Type Correctness

A program is statically type correct if it satisfies some type rules

The rules are chosen to be:• simple to understand• efficient to decide• conservative with respect to type correctness

Type systems are not canonical They are designed like the rest of the language

Page 7: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

7Static Type Checking

SlackSlack

Static type systems are necessarily flawed:

There is always slack: programs that are unfairly rejected by the type checker

statically type correcttype correct

slack

Page 8: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

8Static Type Checking

Examples of SlackExamples of Slack

Trivial example:

x = 87;

if (false) x = true;

Useful example:

Map m = new Hashmap();

m.put("bar","foo");

String x = m.get("bar");

Java 1.5 was designed to pick up some slack

Page 9: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

9Static Type Checking

Specifying Type RulesSpecifying Type Rules

Prose:

"The argument of the sqrt function must be of type int, the result is of type double"

Logical rules:

C |- x: int

C |- sqrt(x): double

Page 10: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

10Static Type Checking

The Shortcomings of ProseThe Shortcomings of Prose

The first expression must be of type boolean, or a compile-time error occurs. The conditional operator

may be used to choose between second and third operands of numeric type, or second and third

operands of type boolean, or second and third operands that are each of either reference type or the null

type. All other cases result in a compile-time error. Note that it is not permitted for either the second or

the third operand expression to be an invocation of a void method. In fact, it is not permitted for a

conditional expression to appear in any context where an invocation of a void method could appear. The

type of a conditional expression is determined as follows: If the second and third operands have the

same type (which may be the null type), then that is the type of the conditional expression. Otherwise, if

the second and third operands have numeric type, then there are several cases:If one of the operands is

of type byte and the other is of type short, then the type of the conditional expression is short. If one of

the operands is of type T where T is byte, short, or char, and the other operand is a constant expression

of type int whose value is representable in type T, then the type of the conditional expression is T.

Otherwise, binary numeric promotion is applied to the operand types, and the type of the conditional

expression is the promoted type of the second and third operands. Note that binary numeric promotion

performs value set conversion. If one of the second and third operands is of the null type and the type of

the other is a reference type, then the type of the conditional expression is that reference type. If the

second and third operands are of different reference types, then it must be possible to convert one of the

types to the other type (call this latter type T) by assignment conversion; the type of the conditional

expression is T. It is a compile-time error if neither type is assignment compatible with the other type.

Page 11: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

11Static Type Checking

Three Kinds of Type RulesThree Kinds of Type Rules

Declarations:

this variable is declared to have this type Propagations:

if the argument is of this type, then the result is of that type

Restrictions:

the argument must be of this type or that type

The logical notation handles all three uniformly

Page 12: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

12Static Type Checking

Judging ExpressionsJudging Expressions

The judgment:

C, L, X, σ |- E: τ

means that the expression E is statically type correct and has type τ in a context where:• C is the current class• L is the current local environment• X is the current set of exceptions• σ is the return type of the current method

Page 13: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

13Static Type Checking

Judging StatementsJudging Statements

The judgment:

C, L, X, σ |- S

means that the statement S is statically type correct in a context where:• C is the current class• L is the current local environment• X is the current set of exceptions• σ is the return type of the current method

Page 14: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

14Static Type Checking

The class environment is implicitly available The notation D≤C means that D is a subclass of C We can query a class C:

• C |- extends D (super class)• C |- σ f (fields)• C |- static σ f (static fields)

• C |- (σ1,..., σk) X (constructors)

• C |- σ m (σ1,..., σk) X (methods)

• C |- static σ m (σ1,..., σk) X (static methods)

Class EnvironmentsClass Environments

return type

name argument typesthrown exceptions

Page 15: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

15Static Type Checking

Assignment CompatibilityAssignment Compatibility

The relation σ := τ means that values of type τ may be assigned to variables of type σ:σ := σ short := byte σ :- σ

int := byte int := short σ[] :- τ[], if σ :- τ

int := char C := null java.lang.Cloneable :- σ[]

σ[] := null Object := σ[] java.io.Serializable :- σ[]

java.lang.Cloneable := σ[] Object :- σ[]

java.io.Serializable := σ[] C :- D, if D ≤ C

σ[] := τ[], if σ :- τ

C := D, if D ≤ C

It is reflexive, transitive, and anti-symmetric

Page 16: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

16Static Type Checking

StatementsStatements

C,L,X,σ |- S1 C,L,X,σ |- S2

C, L, X, σ |- S1 S2

C, L[n→ τ], X, σ |- S

C, L, X, σ |- { τ n; S }

C, L, X, σ |- E: τ

C, L, X, σ |- E;

Page 17: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

17Static Type Checking

Control StatementsControl Statements

C,L,X,σ |- E: boolean C,L,X,σ |- S

C, L, X, σ |- if (E) S

C,L,X,σ |- E: boolean C,L,X,σ |- Si

C, L, X, σ |- if (E) S1 else S2

C,L,X,σ |- E: boolean C,L,X,σ |- S

C, L, X, σ |- while (E) S

Page 18: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

18Static Type Checking

Return StatementsReturn Statements

σ = void

C, L, X, σ |- return

C, L, X, σ |- E: τ σ := τ

C, L, X, σ |- return E

Page 19: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

19Static Type Checking

Throw StatementThrow Statement

C,L,X, σ |- E: τ throwok({τ},X)

C, L, X, σ |- throw E

throwok(A,B) ≡ αA: Error:= α

RuntimeException:= α βB: β:=α

Page 20: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

20Static Type Checking

LocalsLocals

L(n) = τ

C, L, X, σ |- n: τ

Page 21: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

21Static Type Checking

FieldsFields

C,L,X,σ |- this: C

D |- static τ f

C,L,X,σ |- D.f: τ

C,L,X,σ |- E: D D |- τ f

C, L, X, σ |- E.f: τ

Page 22: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

22Static Type Checking

AssignmentsAssignments

C,L,X,σ |- E: τ2 L(n)=τ1 τ1:=τ2

C, L, X, σ |- n = E: τ1

C,L,X,σ |- E: τ2 D |- static τ1 f τ1:=τ2

C, L, X, σ |- D.f = E: τ1

C,L,X,σ |- E2: τ2 C,L,X,σ |- E1: D D |- τ1 f τ1:=τ2

C, L, X, σ |- E1.f = E2: τ1

Page 23: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

23Static Type Checking

ArraysArrays

C,L,X,σ |- E1: τ1[] C,L,X,σ |- E2: τ2 num(τ2)

C, L, X, σ |- E1[E2]: τ1

C, L, X, σ |- E1: τ1[] C, L, X, σ |- E2: τ2

C, L, X, σ |- E3: τ3 num(τ2) τ1:= τ3

C, L, X, σ |- E1[E2]= E3: τ1

num(σ) ≡ σ{ byte, short, int, char }

Page 24: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

24Static Type Checking

Array OperationsArray Operations

C,L,X,σ |- E: τ[]

C,L,X,σ |- E.length: int

C,L,X,σ |- E: τ[]

C,L,X,σ |- E.clone(): Object

C,L,X,σ |- E: τ2 num(τ2)

C,L,X,σ |- new τ1[E]: τ1[]

Page 25: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

25Static Type Checking

OperatorsOperators

C,L,X,σ |- E: boolean

C,L,X,σ |- !E: boolean

C,L,X,σ |- E1: τ1 C,L,X,σ |- E2: τ2 num(τ1) num(τ2)

C, L, X, σ |- E1*E2: int

Page 26: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

26Static Type Checking

LiteralsLiterals

C,L,X,σ |- true: boolean

C,L,X,σ |- "abc": String

C,L,X,σ |- null: null C,L,X,σ |- '@': char

C,L,X,σ |- 42: int

Page 27: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

27Static Type Checking

PlusPlus

C,L,X,σ |- E1: τ1 C,L,X,σ |- E2: τ2 num(τ1) num(τ2)

C, L, X, σ |- E1+E2: int

C,L,X,σ |- E1: String C,L,X,σ |- E2: τ2 τ2≠void

C, L, X, σ |- E1+E2: String

C,L,X,σ |- E1: τ1 C,L,X,σ |- E2: String τ1≠void

C, L, X, σ |- E1+E2: String

Page 28: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

28Static Type Checking

EqualityEquality

C,L,X,σ |- E1: τ1 C,L,X,σ |- E2: τ2

(num(τ1)num(τ2)) τ1:=τ2 τ2:=τ1

C, L, X, σ |- E1==E2: boolean

Page 29: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

29Static Type Checking

Casts and InstanceofCasts and Instanceof

C,L,X,σ |- E: τ1 (num(τ1)num(τ2)) τ1:=τ2 τ2:=τ1

C, L, X, σ |- (τ2)E: τ2

C,L,X,σ |- E: τ τ:=D D:=τ

C, L, X, σ |- E instanceof D: boolean

Page 30: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

30Static Type Checking

Why Restrict Casts?Why Restrict Casts?

τ1

τ2

τ2

τ1

τ1τ2

Alway succeeds, but upcasting is useful for selecting different methods

τ2 := τ1

Really useful, the object may or may not by a subclass of τ2

τ1 := τ2

Always fails, don't bother to execute

τ1 :≠ τ2 τ1 :≠ τ2

Page 31: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

31Static Type Checking

Method Invocation in Joos1Method Invocation in Joos1

C,L,X,σ |- E: D C,L,X,σ |- Ei: τi

D |- τ m(τ1,...,τk) Y

C, L, X, σ |- E.m(E1,...,Ek): τ

C,L,X,σ |- Ei: τi

D |- static τ m(τ1,...,τk) Y

C, L, X, σ |- D.m(E1,...,Ek): τ

(we add exception handling machinery later)

Page 32: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

32Static Type Checking

Constructor InvocationConstructor Invocation

C,L,X,σ |- Ei: τi

D |- (τ1,...,τk) Y throwok(Y,X)

C, L, X, σ |- new D(E1,...,Ek): D

C,L,X,σ |- Ei: τi C |- extends D

D |- (τ1,...,τk) Y throwok(Y,X)

C, L, X, σ |- super(E1,...,Ek)

Page 33: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

33Static Type Checking

Method Invocation in Joos2Method Invocation in Joos2

C,L,X,σ |- E: D C,L,X,σ |- Ei: σi

D |- τ m(τ1,...,τk) Y τi:= σi

D |- γ m(γ1,..., γk) Z : (i: γi:= σi) (i: γi:= τi)

C, L, X, σ |- E.m(E1,...,Ek): τ

• This rule does not describe access modifiers• supports overloading (closest match) and subtype polymorphim in the arguments

Page 34: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

34Static Type Checking

C,L,X,σ |- E: D C,L,X,σ |- Ei: τi

D |- τ m(τ1,...,τk) Y

throwok({Yi| D |- τ m(τ1,...,τk) Yi }, X)

C, L, X, σ |- E.m(E1,...,Ek): τ

Checking Exceptions in Joos1Checking Exceptions in Joos1

where

YZ = YZ Z Y

YZ = { yY | throwok({y},Z) }

Intuitively: check the intersection of all possible exceptions

Page 35: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

Exceptions - why so complicated?Exceptions - why so complicated?

35Static Type Checking

class X extends Throwable {}class Y extends Throwable {}

abstract class A { public abstract void m() throws X;}interface B { void m() throws Y;}class Test { void foo(C c) { // no throws clause required! c.m(); }}

Page 36: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

Exceptions - why so complicated?Exceptions - why so complicated?

36Static Type Checking

class X extends Throwable {}class Y extends X {}

abstract class A { public abstract void m() throws X;}interface B { void m() throws Y;}class Test { void foo(C c) throws Y { // no throws X clause required! c.m(); }}

Page 37: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

37Static Type Checking

Judging Methods and ConstructorsJudging Methods and Constructors

C, [ai→ σi], { Xi }, σ |- S Throwable := Xi

C |- σ m(σ1 a1,...,σk ak)throws X1,...,Xn { S }

C, [ai→ σi], { Xi }, void |- S Throwable := Xi

C |- C(σ1 a1,...,σk ak)throws X1,...,Xn { S }

Page 38: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

38Static Type Checking

Different Kinds of Type RulesDifferent Kinds of Type Rules

Axioms:

Predicates: τ1:=τ2 τ1:=τ2

Inferences:

C,L,X,σ |- this: C

C,L,X,σ |- E: D D |- τ f

C, L, X, σ |- E.f: τ

Page 39: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

39Static Type Checking

Type ProofsType Proofs

A type proof is a tree in which:• nodes are inferences• leaves are axioms or true predicates

A judgment is valid

it is the root of some type proof

Page 40: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

40Static Type Checking

A Type ProofA Type Proof

[x→A,y→B](x)=A

C,[x→A,y→B],X,σ |- x:A ABBA [x→A,y→B](y)=B C,[x→A,y→B],X,σ |- (B)x: B B:=B

C,[x→A,y→B],X, σ |- y=(B)x: B

C,[x→A,y→B],X, σ |- y=(B)x;

C,[x→A],X, σ |- {B y; y=(B)x;}

C,[],X,σ |- {A x; {B y; y=(B)x;}}

Equal to a trace of a successful run of the type checker

(Assuming that B is a subclass of A)

Page 41: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

41Static Type Checking

Static Type CorrectnessStatic Type Correctness

A program is statically type correct

all method and constructor judgments are valid

A type system is sound

static type correctness implies type correctness

Page 42: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

42Static Type Checking

Java's Type System is UnsoundJava's Type System is Unsound

The following is a valid judgement:

C, [b→B,x→A[],y→B[],c→C], X, σ |- x=y; x[0]=c; b=y[0];

where BA, CA, and B and C are incomparable Afterward, b contains an object of class C But its declared type only allows B objects

Page 43: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

43Static Type Checking

GreedGreed

Java's type system is too greedy:

Runtime type checks catch the unsound cases

statically type correcttype correct

unsound

Page 44: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

44Static Type Checking

Fixed Assignment CompatibilityFixed Assignment Compatibility

By design, the rule for assignment of arrays has been chosen to be convenient but unsound

It should have looked like:σ := σ short := byte σ :- σ

int := byte int := short σ[] :- τ[], if σ :- τ

int := char C := null java.lang.Cloneable :- σ[]

σ[] := null Object := σ[] java.io.Serializable :- σ[]

java.lang.Cloneable := σ[] C :- D, if D ≤ C

java.io.Serializable := σ[]

σ[] := τ[], if σ :- τ

C := D, if D ≤ C

But that would then introduce annoying slack...

Page 45: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

45Static Type Checking

Complexity of Inference SystemsComplexity of Inference Systems

Deciding valid judgments of an inference system depends on its rules and axioms and may be:• undecidable• (hyper)exponential time (backtracking)• linear time

The Java type system is designed to be simple A type checker performs a single traversal of the

parse tree in linear time

Page 46: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

46Static Type Checking

Type Checking in JavaType Checking in Java

Type checking is performed bottom-up The rule to apply is uniquely determined by the

types of subexpressions and the syntax

The type proof also specifies how to transform the program with respect to:• Autoboxing/unboxing• implicit string conversions• concat(...) code

Page 47: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

47Static Type Checking

Implicit CoercionsImplicit Coercions

Suppose we add a coercion type rule:

corresponding to the JVM bytecode i2f

Type proofs are now no longer unique!

C,L,X,σ |- E: int

C,L,X,σ |- E: float

Page 48: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

48Static Type Checking

Ambiguous Type ProofsAmbiguous Type Proofs

L(i)=int L(j)=int

C,L,X,σ |-i: int C,L,X,σ |- j: int

C,L,X,σ |-i: float C,L,X,σ |- j: float L(f)=float

C,L,X,σ |- i+j: float C,L,X,σ |- f: float

C,L,X,σ |- i+j==f: boolean

L(i)=int L(j)=int

C,L,X,σ |-i: int C,L,X,σ |- j: int

C,L,X,σ |-i+j: int L(f)=float

C,L,X,σ |- i+j: float C,L,X,σ |- f: float

C,L,X,σ |- i+j==f: boolean

Page 49: Compilation 2011 Static Type Checking Ian Zerny Michael I. Schwartzbach Aarhus University

49Static Type Checking

Semantic CoherenceSemantic Coherence

Different type proofs generate different transformed programs

The type system is semantically coherent if they always have the same semantics

The previous hypothetical type system is not:• i = 2147400000• j = 83647• f = 2.14748365E9

Java chooses the proof with coercions as near the root as possible