CSE411

CSE411: Introduction to Compilers

Type Checking

Jooyong Yi (UNIST)

CSE411

Interface of a Type Checker

      |--------------|           
AST → | Type Checker | → ok / error
      |--------------|         
CSE411

Example

void foo() {
    int x;
    int y;
    y = x;
}
  • Is the above program type-safe?
CSE411

Example

void foo() {
    int i;
    char *s;
    i = s;
}
  • Is the above program type-safe?
CSE411

Proof

void foo() {
    int x;
    int y;
    y = x;
}
  • How do we prove that the above program is type-safe?
CSE411

Proof Tree

------------------------   ------------------------
 [x:int][y:int] ⊢ y:int     [x:int][y:int] ⊢ x:int
-------------------------------------------------------
                 [x:int][y:int] ⊢ (y = x;): unit
               ----------------------------------
                 [x:int] ⊢ (int y; y = x;): unit
               -----------------------------------
                   ⊢ (int x; int y; y = x;): unit
CSE411

Judgement

  • An assertion about the typing of programs
  • Syntax: Γ ⊢ J (we read this as "Γ entails J")
    • Γ: A typing environment
    • J: An assertion
[x:int][y:int] ⊢ x:int
               ⊢ (int x; int y; y = x;): unit
CSE411

Building a Proof Tree

------------------------   ------------------------
 [x:int][y:int] ⊢ y:int     [x:int][y:int] ⊢ x:int
-------------------------------------------------------
                 [x:int][y:int] ⊢ (y = x;): unit
               ----------------------------------
                 [x:int] ⊢ (int y; y = x;): unit
               -----------------------------------
                   ⊢ (int x; int y; y = x;): unit         # Goal
  • Inference rule
      Γ[I:int] ⊢ (S): unit        # premises
---------------------------
      Γ ⊢ (int I; S): unit        # conclusion  
CSE411

Building a Proof Tree

------------------------   ------------------------
 [x:int][y:int] ⊢ y:int     [x:int][y:int] ⊢ x:int
-------------------------------------------------------
                 [x:int][y:int] ⊢ (y = x;): unit        # Goal
               ----------------------------------
                 [x:int] ⊢ (int y; y = x;): unit
               -----------------------------------
                   ⊢ (int x; int y; y = x;): unit         
  • Inference rule
   Γ ⊢ I:τ  Γ ⊢ E:τ            # premises
-------------------------
      Γ ⊢ (I = E;): unit       # conclusion  
CSE411

Building a Proof Tree

------------------------   ------------------------
 [x:int][y:int] ⊢ y:int     [x:int][y:int] ⊢ x:int     # Goal
-------------------------------------------------------
                 [x:int][y:int] ⊢ (y = x;): unit        
               ----------------------------------
                 [x:int] ⊢ (int y; y = x;): unit
               -----------------------------------
                   ⊢ (int x; int y; y = x;): unit         
  • Axiom: a fact that is accepted as true without requiring any further justification.
--------------
 Γ[x:τ] ⊢ x:τ
CSE411

Failure to Build a Proof Tree

--------------------------      ----------------------------
 [i:int][s:char*] ⊢ i:int       [i:int][s:char*] ⊢ s:char*     
------------------------------------------------------------
                 [i:int][s:char*] ⊢ (i = s;): unit              # Goal
               -------------------------------------
                 [i:int] ⊢ (char *s; i = s;): unit
               ------------------------------------------------
                   ⊢ (int i; char *s; i = s;): unit 
  • Inference rule
   Γ ⊢ I:τ  Γ ⊢ E:τ            # premises
-------------------------
      Γ ⊢ (I = E;): unit       # conclusion  
CSE411

If Statements

 Γ ⊢ E: boolean   Γ ⊢ S
--------------------------
  Γ ⊢ (if (E) S): unit

CSE411

While Statements

 Γ ⊢ E: boolean   Γ ⊢ S
--------------------------
  Γ ⊢ (while (E) S): unit

CSE411

Arithmetic Expressions

   Γ ⊢ E1: int   Γ ⊢ E2: int
------------------------------
      Γ ⊢ E1 + E2: int
CSE411

Equality

    Γ ⊢ E1: τ   Γ ⊢ E2: τ
------------------------------
      Γ ⊢ E1 == E2: boolean
CSE411

Procedure Invocation

   Γ ⊢ P: τ_1 × τ_2 × ... × τ_n → τ   Γ ⊢ E_k: τ_k (for k = 1, ..., n)
 -----------------------------------------------------------------------
           Γ ⊢ P(E1, E2, ..., En): τ
CSE411

Integer Constant

-----------------
  Γ ⊢ n: int        # n is an integer constant
CSE411

I do not want to manually write a proof tree...

CSE411

Automatic Proof

  • Imagine you traverse the AST
------------------------   ------------------------
 [x:int][y:int] ⊢ y:int     [x:int][y:int] ⊢ x:int    
-------------------------------------------------------
                 [x:int][y:int] ⊢ (y = x;): unit        
               ----------------------------------
                 [x:int] ⊢ (int y; y = x;): unit
               -----------------------------------
                   ⊢ (int x; int y; y = x;): unit         
CSE411
------------------------   ------------------------
 [x:int][y:int] ⊢ y:int     [x:int][y:int] ⊢ x:int    
-------------------------------------------------------
                 [x:int][y:int] ⊢ (y = x;): unit        
               ----------------------------------
                 [x:int] ⊢ (int y; y = x;): unit                                 Γ[I:int] ⊢ (S): unit        
               -----------------------------------                            ---------------------------
                   ⊢ (int x; int y; y = x;): unit         # Goal                 Γ ⊢ (int I; S): unit                             
// Visitor to construct a symbol table
class Visitor extends ASTVisitor {
  ...
  public boolean visit(final VariableDeclarationStatement node) { // e.g., node: int x;
    final VariableDeclarationFragment vdf = (VariableDeclarationFragment) node.fragments().get(0); // e.g., vdf: x
    final String name = vdf.getName().getIdentifier();
    if (this.nameMap.containsKey(name)) {
      // duplicate declaration
      throw new Error(...);
    }
    this.nameMap.put(name, node);
    return false;
  }
  ...
}  
CSE411
------------------------   ------------------------
 [x:int][y:int] ⊢ y:int     [x:int][y:int] ⊢ x:int    
-------------------------------------------------------
                 [x:int][y:int] ⊢ (y = x;): unit         # Goal
               ----------------------------------
                 [x:int] ⊢ (int y; y = x;): unit                                Γ ⊢ I:τ  Γ ⊢ E:τ            
               -----------------------------------                          -------------------------
                   ⊢ (int x; int y; y = x;): unit                               Γ ⊢ (I = E;): unit                           
class Visitor extends ASTVisitor {
  ...
  public boolean visit(final Assignment node) {
    node.getLeftHandSide().accept(this);
    final Type lhsType = getResult();
    node.getRightHandSide().accept(this);
    final Type rhsType = getResult();
    if (lhsType != rhsType) {
      throw new Error(node, "Type mismatch in \"" + node + "\": " + lhsType + " = " + rhsType);
    }
    return false;
  }
  ...
}  
CSE411

Benefits of Using Inference Rules

CSE411

Benefits of Using Inference Rules

  • Modular and compositional reasoning
    • With a finite set of rules, we can prove the correctness of any program.
CSE411

Logical System

  • A type-checking system is an example of a logical system.
    • A logical system consists of axioms and inference rules.
CSE411

Two Fundamental Questions

  1. Soundness: P ⊢ Q ⇒ P ⊧ Q
  2. Completeness: P ⊧ Q ⇒ P ⊢ Q
CSE411

Soundness

  • ⊢ (int x; int y; y = x;): unit ⇒ ⊧ (int x; int y; y = x;): unit
  • The compiler says the given program is type-safe. Is the program really type-safe?
CSE411

Completeness

  • ⊧ (int x; int y; y = x;): unit ⇒ ⊢ (int x; int y; y = x;): unit
  • I know that the given program should be type-safe. Can the compiler prove that the program is type-safe?
CSE411

Completeness

import java.util.List;
import java.util.ArrayList;

public class Incomplete {
    static class C {}
    static class D extends C {}

    public static void main(String args[]) {
        List<C> lst = new ArrayList<>();
        if (args[0].equals("1")) {
            lst.add(new D());
        } else {
            lst.add(new D());
        }
        D d = lst.get(0);
    }
}                                                                                                                   
  • Is the above Java program type-safe?
CSE411

Completeness

import java.util.List;
import java.util.ArrayList;

public class Incomplete {
    static class C {}
    static class D extends C {}

    public static void main(String args[]) {
        List<C> lst = new ArrayList<>();
        if (args[0].equals("1")) {
            lst.add(new D());
        } else {
            lst.add(new D());
        }
        D d = lst.get(0);
    }
}                                                                                                                   
Incomplete.java:15: error: incompatible types: C cannot be converted to D
        D d = lst.get(0);
                     ^
1 error                                                                                                          
CSE411

Sound Type System: Over-approximation

center

  • A sound type system may reject some programs that are type-safe.