type checking compiler

Upload: abckits

Post on 04-Apr-2018

232 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/30/2019 type checking compiler

    1/215

    Type-Checking II

  • 7/30/2019 type checking compiler

    2/215

    Announcements

    Written Assignment 2 Due Monday at 5:00PM.

    Office hours today, Sunday, and Monday.

    Ask questions on Piazzza!

    Email the staff list with questions!

    Midterm next Wednesday in class, 11:00 1:00.

    Midterm review session next Monday in class.

    We'll post practice midterms online.

    Midterm covers all of scanning and parsing, but not semantic

    analysis.

    Open-book, open-notes, open-computer, closed-network.

    OH switch next week: Monday office hours in Gates B24A,Friday office hours in Gates 160 at the scheduled times.

  • 7/30/2019 type checking compiler

    3/215

    Where We Are

    Lexical Analysis

    Semantic Analysis

    Syntax Analysis

    IR Generation

    IR Optimization

    Code Generation

    Optimization

    SourceCode

    Machine

    Code

  • 7/30/2019 type checking compiler

    4/215

    Review from Last Time

    Static type checking in Decaf consists of twoseparate processes:

    Inferring the type of each expression from the types

    of its components. Confirming that the types of expressions in certain

    contexts matches what is expected.

    Logically two steps, but you will probably

    combine into one pass.

  • 7/30/2019 type checking compiler

    5/215

    Review from Last Time

    while (numBitsSet(x + 5)

  • 7/30/2019 type checking compiler

    6/215

    Review from Last Time

    while (numBitsSet(x + 5)

  • 7/30/2019 type checking compiler

    7/215

    Review from Last Time

    while (numBitsSet(x + 5)

  • 7/30/2019 type checking compiler

    8/215

    Review from Last Time

    while (numBitsSet(x + 5)

  • 7/30/2019 type checking compiler

    9/215

    Review from Last Time

    while (numBitsSet(x + 5)

  • 7/30/2019 type checking compiler

    10/215

    Review from Last Time

    while (numBitsSet(x + 5)

  • 7/30/2019 type checking compiler

    11/215

    Review from Last Time

    We write

    S e : T

    ifin scope S, the expression e has type T.

  • 7/30/2019 type checking compiler

    12/215

    Review from Last Time

    S f(e1, ..., e

    n) : U

    fis an identifier.fis a non-member function in scope S.

    fhas type (T1, , T

    n) U

    S ei: T

    ifor 1 i n

    Read rules

    like this

  • 7/30/2019 type checking compiler

    13/215

    Review from Last Time

    S f(e1, ..., e

    n) : U

    fis an identifier.fis a non-member function in scope S.

    fhas type (T1, , T

    n) U

    S ei: T

    ifor 1 i n

  • 7/30/2019 type checking compiler

    14/215

    Review from Last Time

    We say that A B if A is convertible to B.

    The least upper bound of A and B is the class C where

    A C

    B C

    C C' for all other upper bounds.

    The least upper bound is denoted A B when it exists.

    A minimal upper bound of A and B is

    an upper bound of A and B that is not larger than any other upper bound.

  • 7/30/2019 type checking compiler

    15/215

    Review from Last Time

    S f(e1, ..., e

    n) : U

    fis an identifier.fis a non-member function in scope S.

    fhas type (T1, , T

    n) U

    S ei

    : Ri

    for 1 i n

    Ri T

    ifor 1 i n

  • 7/30/2019 type checking compiler

    16/215

    Review from Last Time

    S null : null type

  • 7/30/2019 type checking compiler

    17/215

    Overview for Today

    Type-checking statements.

    Practical type-checking considerations.

    Type-checking practical language constructs:

    Function overloading.

    Specializing overrides.

  • 7/30/2019 type checking compiler

    18/215

    Using our Type Proofs

    We can now prove the types of variousexpressions.

    How do we check...

    that ifstatements have well-formed conditionalexpressions?

    that return statements actually return the right

    type of value?

    Use another proof system!

  • 7/30/2019 type checking compiler

    19/215

    Proofs of Structural Soundness

    Idea: extend our proof system to statements toconfirm that they are well-formed.

    We say that

    S WF( stmt)if the statement stmtis well-formed in scope S.

    The type system is satisfied if for every functionfwith body B in scope S, we can showS WF(B).

  • 7/30/2019 type checking compiler

    20/215

    A Simple Well-Formedness Rule

    S WF( expr;)

    S expr: T

  • 7/30/2019 type checking compiler

    21/215

    A Simple Well-Formedness Rule

    S WF( expr;)

    S expr: T

    If we canassign a valid

    type to an

    expression in

    scope S

  • 7/30/2019 type checking compiler

    22/215

    A Simple Well-Formedness Rule

    S WF( expr;)

    S expr: T

    If we canassign a valid

    type to an

    expression in

    scope SS expr: T

    then it is a

    valid statement

    in scope S.

  • 7/30/2019 type checking compiler

    23/215

    A More Complex Rule

  • 7/30/2019 type checking compiler

    24/215

    A More Complex Rule

    S WF( stmt1stmt

    2)

    S WF( stmt1)

    S WF( stmt2)

  • 7/30/2019 type checking compiler

    25/215

    Rules forbreak

  • 7/30/2019 type checking compiler

    26/215

    Rules forbreak

    S WF( break;)

    S is in a for orwhile loop.

  • 7/30/2019 type checking compiler

    27/215

    A Rule for Loops

  • 7/30/2019 type checking compiler

    28/215

    A Rule for Loops

    S WF( while (expr)stmt)

    S expr:bool

    S' is the scope inside the loop.

    S' WF( stmt)

  • 7/30/2019 type checking compiler

    29/215

    Rules for Block Statements

  • 7/30/2019 type checking compiler

    30/215

    Rules for Block Statements

    S WF( { declsstmt})

    S' is the scope formed by adding decls to S

    S' WF( stmt)

  • 7/30/2019 type checking compiler

    31/215

    Rules forreturn

  • 7/30/2019 type checking compiler

    32/215

    Rules forreturn

    S WF( returnexpr;)

    S is in a function returning TS expr: T'

    T' T

    S WF( return;)

    S is in a function returning void

  • 7/30/2019 type checking compiler

    33/215

    Checking Well-Formedness

    Recursively walk the AST.

    For each statement:

    Typecheck any subexpressions it contains.

    Report errors if no type can be assigned.

    Report errors if the wrong type is assigned.

    Typecheck child statements.

    Check the overall correctness.

  • 7/30/2019 type checking compiler

    34/215

    PracticalConcerns

  • 7/30/2019 type checking compiler

    35/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

  • 7/30/2019 type checking compiler

    36/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

  • 7/30/2019 type checking compiler

    37/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

  • 7/30/2019 type checking compiler

    38/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

  • 7/30/2019 type checking compiler

    39/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S hi i V W H

  • 7/30/2019 type checking compiler

    40/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x: T

    xis an identifier.xis a variable in scope S with type T.

    S thi i V W H

  • 7/30/2019 type checking compiler

    41/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x: T

    xis an identifier.xis a variable in scope S with type T.

    S x : int

    S thi i V W H

  • 7/30/2019 type checking compiler

    42/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x: T

    xis an identifier.xis a variable in scope S with type T.

    S x : int

    S thi i V W H

  • 7/30/2019 type checking compiler

    43/215

    Something is Very Wrong Here

    int x, y, z;if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x: T

    xis an identifier.xis a variable in scope S with type T.

    S x : int

    S y : int

    S z : int

    S thi i V W H

  • 7/30/2019 type checking compiler

    44/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x: T

    xis an identifier.xis a variable in scope S with type T.

    S x : int

    S y : int

    S z : int

    S thi i V W H

  • 7/30/2019 type checking compiler

    45/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S e1== e2 :bool

    S e1

    : T1

    S e2

    : T2

    T1 T

    2or T

    2 T

    1

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    46/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S e1== e2 :bool

    S e1

    : T1

    S e2

    : T2

    T1 T

    2or T

    2 T

    1

    S x == y :bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    47/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S e1== e2 :bool

    S e1

    : T1

    S e2

    : T2

    T1 T

    2or T

    2 T

    1

    S x == y :bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    48/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S i: int

    iis an integer constant

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    49/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S

    i: int

    iis an integer constant

    S 5 : int

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    50/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S i

    :int

    iis an integer constant

    S 5 : int

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    51/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : intS e1 + e2 : int

    S e1

    : int

    S e2

    : int

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    52/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : intS e1 + e2 : int

    S e1

    : int

    S e2

    : int

    S x + y : int

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    53/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : intS e1 + e2 : int

    S e1

    : int

    S e2

    : int

    S x + y : int

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    54/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : intS e1< e2 :bool

    S e1

    : int

    S e2

    : int

    S x + y : int

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    55/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : intS e1< e2 :bool

    S e1

    : int

    S e2

    : int

    S x + y : int

    S x + y < z :bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    56/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : intS e1< e2 :bool

    S e1

    : int

    S e2

    : int

    S x + y : int

    S x + y < z :bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    57/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S e1== e2 :bool

    S e1

    : T1

    S e2

    : T2

    T1 T

    2or T

    2 T

    1

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    58/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S e1== e2 :bool

    S e1

    : T1

    S e2

    : T2

    T1 T

    2or T

    2 T

    1

    S x == z :bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    59/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1== e2 :bool

    S e1

    : T1

    S e2

    : T2

    T1 T

    2or T

    2 T

    1

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    60/215

    Something is Very Wrong Here

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1>e

    2:bool

    S e1

    : int

    S e2

    : int

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    61/215

    So e g s e y o g e e

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1>e

    2:bool

    S e1

    : int

    S e2

    : int

    >

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    62/215

    g y g

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1>e

    2:bool

    S e1

    : int

    S e2

    : int

    > Error: Cannot compare int and bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    63/215

    g y g

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1>e

    2:bool

    S e1

    : int

    S e2

    : int

    > Error: Cannot compare int and bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    64/215

    g y g

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {

    /* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1&& e

    2:bool

    S e1

    :bool

    S e2

    :bool

    > Error: Cannot compare int and bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    65/215

    g y g

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {/* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1&& e

    2:bool

    S e1

    :bool

    S e2

    :bool

    > Error: Cannot compare int and bool

    Error: Cannot compare ??? and bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    66/215

    g y g

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {/* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1&& e

    2:bool

    S e1

    :bool

    S e2

    :bool

    > Error: Cannot compare int and bool

    Error: Cannot compare ??? and bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    67/215

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {/* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1|| e

    2:bool

    S e1

    :bool

    S e2

    :bool

    > Error: Cannot compare int and bool

    Error: Cannot compare ??? and bool

    Something is Very Wrong Here

  • 7/30/2019 type checking compiler

    68/215

    int x, y, z;

    if (((x == y) > 5 && x + y < z) || x == z) {/* */

    }

    Facts

    S x : int

    S y : int

    S z : int

    S x == y :bool

    S 5 : int

    S x + y : int

    S x + y < z :bool

    S x == z :bool

    S e1|| e

    2:bool

    S e1

    :bool

    S e2

    :bool

    > Error: Cannot compare int and bool

    Error: Cannot compare ??? and bool

    Error: Cannot compare ??? and bool

    Cascading Errors

  • 7/30/2019 type checking compiler

    69/215

    A type erroroccurs when we cannot prove thatan expression has a given type.

    Type errors can easily cascade:

    Can't prove a type for e1, so can't prove a type fore

    1+e

    2, so can't prove a type for (e

    1+e

    2)+e

    3, etc.

    How do we resolve this?

    The Shape of Types

  • 7/30/2019 type checking compiler

    70/215

    Vegetable

    ArtichokeCarrot

    The Shape of Types

  • 7/30/2019 type checking compiler

    71/215

    Vegetable

    ArtichokeCarrot bool string doubleintArrayTypes

    The Shape of Types

  • 7/30/2019 type checking compiler

    72/215

    Vegetable

    ArtichokeCarrot bool string doubleintArrayTypes

    null Type

    The Shape of Types

  • 7/30/2019 type checking compiler

    73/215

    Vegetable

    ArtichokeCarrot bool string doubleintArrayTypes

    null Type

    Error Type

    The Shape of Types

  • 7/30/2019 type checking compiler

    74/215

    Vegetable

    ArtichokeCarrot bool string doubleintArrayTypes

    null Type

    Error Type

    The Error Type

  • 7/30/2019 type checking compiler

    75/215

    Introduce a new type representing an error intothe type system.

    The error type is less than all other types and isdenoted .

    It is sometimes called the bottom type.

    By definition, A for any type A.

    On discovery of a type error, pretend that wecan prove the expression has type .

    Update our inference rules to support .

    Updated Rules for Addition

  • 7/30/2019 type checking compiler

    76/215

    S e1

    + e2: double

    S e1

    : double1

    S e2

    : double2

    T1

    double

    T2 double

    Updated Rules for Addition

  • 7/30/2019 type checking compiler

    77/215

    S e1

    + e2: double

    S e1

    : T1

    S e2

    : T2

    T1

    double

    T2 double

    Updated Rules for Addition

  • 7/30/2019 type checking compiler

    78/215

    S e1

    + e2: double

    S e1

    : T1

    S e2

    : T2

    T1

    double

    T2 double

    Updated Rules for Addition

  • 7/30/2019 type checking compiler

    79/215

    S e1

    + e2: double

    S e1

    : T1

    S e2

    : T2

    T1

    double

    T2 double

    What does

    this mean?

    Updated Rules for Addition

  • 7/30/2019 type checking compiler

    80/215

    S e1

    + e2: intS e

    1+ e

    2: double

    S e1

    : T1

    S e2

    : T2

    T1

    double

    T2 double

    S e1

    : T1

    S e2

    : T2

    T1

    int

    T2 int

    Updated Rules for Addition

  • 7/30/2019 type checking compiler

    81/215

    S e1

    + e2: intS e

    1+ e

    2: double

    S e1

    : T1

    S e2

    : T2

    T1

    double

    T2 double

    S e1

    : T1

    S e2

    : T2

    T1

    int

    T2 int

    Prevents errorsfrom propagating.

    Updated Rules for Addition

  • 7/30/2019 type checking compiler

    82/215

    S e1

    + e2: intS e

    1+ e

    2: double

    S e1

    : T1

    S e2

    : T2

    T1

    double

    T2 double

    S e1

    : T1

    S e2

    : T2

    T1

    int

    T2 int

    Updated Rules for Addition

  • 7/30/2019 type checking compiler

    83/215

    S e1

    + e2: intS e

    1+ e

    2: double

    S e1

    : T1

    S e2

    : T2

    T1

    double

    T2 double

    S e1

    : T1

    S e2

    : T2

    T1

    int

    T2 int

    What happens ifboth operands have

    error type?

    Error-Recovery in Practice

  • 7/30/2019 type checking compiler

    84/215

    In your semantic analyzer, you will need to dosome sort of error recovery.

    We provide an error type Type::errorType.

    But what about other cases? Calling a nonexistent function.

    Declaring a variable of a bad type.

    Treating a non-array as an array.

    There are no right answers to these questions;just better and worse choices.

    Implementing Convertibility

  • 7/30/2019 type checking compiler

    85/215

    How do we implement the operator we'vedescribed so far?

    Lots of cases:

    Class Type

    PrimitiveType

    Array Type

    Null Type

    Error Type

    Class Type PrimitiveType Array Type Null Type Error Type

    If same orinherits from

    No No No No

    NoIf same

    typeNo No No

    No NoIf underlyingtypes match No No

    Yes No No Yes No

    Yes Yes Yes Yes Yes

    FromTo

    A Hierarchy for Types

  • 7/30/2019 type checking compiler

    86/215

    Type

    Class TypePrimitive

    TypeArray Type Null Type Error Type

    Methods You Might Want...

  • 7/30/2019 type checking compiler

    87/215

    virtual bool Type::IsIdenticalTo(Type* other);

    Returns whether two types represent the same actualtype.

    virtual bool Type::IsConvertibleTo(Type* other);

    Returns whether one type is convertible to someother type.

  • 7/30/2019 type checking compiler

    88/215

    Type-Checking in

    the Real World

  • 7/30/2019 type checking compiler

    89/215

    Function Overloading

    Function Overloading

  • 7/30/2019 type checking compiler

    90/215

    Two functions are said to be overloads of oneanother if they have the same name but adifferent set of arguments.

    At compile-time, determine which function is

    meant by inspecting the types of thearguments.

    Report an error if no one function is the best

    function.

    Overloading Example

  • 7/30/2019 type checking compiler

    91/215

    void Function();void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    Function();

    Function(137);

    Function(42.0);

    Function(new Base);

    Function(new Derived);

    Overloading Example

  • 7/30/2019 type checking compiler

    92/215

    void Function();void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    Function();

    Function(137);

    Function(42.0);

    Function(new Base);

    Function(new Derived);

    Implementing Overloadingvoid Function();

  • 7/30/2019 type checking compiler

    93/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    Implementing Overloadingvoid Function();

  • 7/30/2019 type checking compiler

    94/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    Function(137);

    Implementing Overloadingvoid Function();

  • 7/30/2019 type checking compiler

    95/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    () (int x) (double x) (Base b) (Derived d)

    Function(137);

    Implementing Overloadingvoid Function();

  • 7/30/2019 type checking compiler

    96/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    () (int x) (double x) (Base b) (Derived d)

    Function(137);

    Implementing Overloadingvoid Function();

  • 7/30/2019 type checking compiler

    97/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    () (int x) (double x) (Base b) (Derived d)

    Function(137);

    Implementing Overloadingvoid Function();

  • 7/30/2019 type checking compiler

    98/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    () (int x) (double x) (Base b) (Derived d)

    Function(137);

    Implementing Overloadingvoid Function();

  • 7/30/2019 type checking compiler

    99/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    () (int x) (double x) (Base b) (Derived d)

    Function(137);

    Implementing Overloadingvoid Function();

    id i (i )

  • 7/30/2019 type checking compiler

    100/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    () (int x) (double x) (Base b) (Derived d)

    Function(137);

    Implementing Overloadingvoid Function();

    id F ti (i t )

  • 7/30/2019 type checking compiler

    101/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    () (int x) (double x) (Base b) (Derived d)

    Function(137);

    Simple Overloading

  • 7/30/2019 type checking compiler

    102/215

    We begin with a set of overloaded functions. After filtering out functions that cannot match,

    we have a candidate set (C++ terminology) orset ofpotentially applicable methods (Java-

    speak). If no functions are left, report an error.

    If exactly one function left, choose it.

    (We'll deal with two or more in a second)

  • 7/30/2019 type checking compiler

    103/215

    Overloading with Inheritancevoid Function();

    void Function(int x);

  • 7/30/2019 type checking compiler

    104/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    Function(new Derived);

    Overloading with Inheritancevoid Function();

    void Function(int x);

  • 7/30/2019 type checking compiler

    105/215

    void Function(int x);

    void Function(double x);

    void Function(Base b);

    void Function(Derived d);

    Function(new Derived);

    () (int x) (double x) (Base b) (Derived d)

    Overloading with Inheritancevoid Function();

    void Function(int x);

  • 7/30/2019 type checking compiler

    106/215

    void Function(int x);

    void Function(double x);void Function(Base b);

    void Function(Derived d);

    Function(new Derived);

    () (int x) (double x) (Base b) (Derived d)

    Overloading with Inheritancevoid Function();

    void Function(int x);How do we

  • 7/30/2019 type checking compiler

    107/215

    void Function(int x);

    void Function(double x);void Function(Base b);

    void Function(Derived d);

    Function(new Derived);

    () (int x) (double x) (Base b) (Derived d)

    comparethese?

    Finding the Best Match

    Choose one function over another if it's strictly more

  • 7/30/2019 type checking compiler

    108/215

    Choose one function over another if it s strictly more

    specific.

    Given two candidate functions A and B with argumenttypes A

    1, A

    2, , A

    nand B

    1, B

    2, , B

    n, we say that A

  • 7/30/2019 type checking compiler

    109/215

    void Function(int x);

    void Function(double x);void Function(Base b);

    void Function(Derived d);

    Function(new Derived);

    () (int x) (double x) (Base b) (Derived d)

    Overloading with Inheritancevoid Function();

    void Function(int x);

  • 7/30/2019 type checking compiler

    110/215

    o d u ct o ( t );

    void Function(double x);void Function(Base b);

    void Function(Derived d);

    Function(new Derived);

    () (int x) (double x) (Base b) (Derived d)

    Overloading with Inheritancevoid Function();

    void Function(int x);

  • 7/30/2019 type checking compiler

    111/215

    ( );

    void Function(double x);void Function(Base b);

    void Function(Derived d);

    Function(new Derived);

    () (int x) (double x) (Base b) (Derived d)

    Ambiguous Calls

    void Function(Base b1, Base b2);

  • 7/30/2019 type checking compiler

    112/215

    void Function(Derived d1, Base b2);void Function(Base b1, Derived d2);

    Ambiguous Calls

    void Function(Base b1, Base b2);

  • 7/30/2019 type checking compiler

    113/215

    void Function(Derived d1, Base b2);void Function(Base b1, Derived d2);

    Function(new Derived, new Derived);

    Ambiguous Calls

    void Function(Base b1, Base b2);

  • 7/30/2019 type checking compiler

    114/215

    void Function(Derived d1, Base b2);void Function(Base b1, Derived d2);

    Function(new Derived, new Derived);

    Base, Base Base, Derived Derived, Base

    Ambiguous Calls

    void Function(Base b1, Base b2);

  • 7/30/2019 type checking compiler

    115/215

    void Function(Derived d1, Base b2);void Function(Base b1, Derived d2);

    Function(new Derived, new Derived);

    Base, Base Base, Derived Derived, Base

  • 7/30/2019 type checking compiler

    116/215

    In the Real World

    Often much more complex than this.

  • 7/30/2019 type checking compiler

    117/215

    p

    Example: variadic functions

    Functions that can take multiple arguments.

    Supported by C, C++, and Java.

    Overloading with Variadic Functions

    void Function(Base b1, Base b2);

  • 7/30/2019 type checking compiler

    118/215

    void Function(Derived d1, Base b2);void Function(Derived d1, ...);

    Overloading with Variadic Functions

    void Function(Base b1, Base b2);

  • 7/30/2019 type checking compiler

    119/215

    void Function(Derived d1, Base b2);void Function(Derived d1, ...);

    Function(new Derived, new Derived);

    Overloading with Variadic Functions

    void Function(Base b1, Base b2);

  • 7/30/2019 type checking compiler

    120/215

    void Function(Derived d1, Base b2);void Function(Derived d1, ...);

    Base, Base Derived, Base Derived,

    Function(new Derived, new Derived);

    Overloading with Variadic Functions

    void Function(Base b1, Base b2);

  • 7/30/2019 type checking compiler

    121/215

    void Function(Derived d1, Base b2);void Function(Derived d1, ...);

    Base, Base Derived, Base Derived,

    Function(new Derived, new Derived);

    Overloading with Variadic Functions

    Option one: Consider the call ambiguous.

  • 7/30/2019 type checking compiler

    122/215

    There are indeed multiple valid function calls, andthat's that!

    Option two: Prefer the non-variadic function.

    A function specifically designed to handle a set ofarguments is probably a better match than onedesigned to handle arbitrarily many parameters.

    Used in both C++ and (with minor modifications)

    Java.

    Hierarchical Function Overloads

    Idea: Have a hierarchy of candidate functions.

  • 7/30/2019 type checking compiler

    123/215

    Conceptually similar to a scope chain:

    Start with the lowest hierarchy level and look for anoverload.

    If a match is found, choose it. If multiple functions match, report an ambiguous call.

    If no match is found, go to the next level in the chain.

    Can you think of another example where we would

    use a hierarchy like this?

    Overloading with Variadic Functionsvoid Function(Base b1, Base b2);

    void Function(Derived d1, Base b2);

    i i i

  • 7/30/2019 type checking compiler

    124/215

    Base, Base Derived, Base Derived,

    Function(new Derived, new Derived);

    void Function(Derived d1, ...);

    Overloading with Variadic Functionsvoid Function(Base b1, Base b2);

    void Function(Derived d1, Base b2);

    id i ( i d d1 )

  • 7/30/2019 type checking compiler

    125/215

    void Function(Derived d1, ...);

    Base, Base Derived, Base

    Derived,

    Function(new Derived, new Derived);

    Overloading with Variadic Functionsvoid Function(Base b1, Base b2);

    void Function(Derived d1, Base b2);

    id F ti (D i d d1 )

  • 7/30/2019 type checking compiler

    126/215

    void Function(Derived d1, ...);

    Base, Base Derived, Base

    Derived,

    Function(new Derived, new Derived);

    Overloading with Variadic Functionsvoid Function(Base b1, Base b2);

    void Function(Derived d1, Base b2);

    id F ti (D i d d1 )

  • 7/30/2019 type checking compiler

    127/215

    void Function(Derived d1, ...);

    Base, Base Derived, Base

    Derived,

    Function(new Derived, new Derived);

    Overloading with Variadic Functionsvoid Function(Base b1, Base b2);

    void Function(Derived d1, Base b2);

    id F ti (D i d d1 )

  • 7/30/2019 type checking compiler

    128/215

    void Function(Derived d1, ...);

    Base, Base Derived, Base

    Derived,

    Function(new Derived, new Derived);

    Overloading with Variadic Functionsvoid Function(Base b1, Base b2);

    void Function(Derived d1, Base b2);

    void Function(Derived d1 );

  • 7/30/2019 type checking compiler

    129/215

    void Function(Derived d1, ...);

    Base, Base Derived, Base

    Derived,

    Function(new Derived, new Derived);

  • 7/30/2019 type checking compiler

    130/215

    Covariance and

    Contravariance

    A Rule for Member Functions

    f is an identifier

  • 7/30/2019 type checking compiler

    131/215

    S e0.f(e

    1, ..., e

    n) : ?

    fis an identifier.S e

    0: M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri T

    ifor 1 i n

    A Rule for Member Functions

    f is an identifier

  • 7/30/2019 type checking compiler

    132/215

    S e0.f(e

    1, ..., e

    n) : ?

    fis an identifier.S e

    0: M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri T

    ifor 1 i n

    A Rule for Member Functions

    f is an identifier

  • 7/30/2019 type checking compiler

    133/215

    S e0.f(e

    1, ..., e

    n) : ?

    fis an identifier.S e

    0: M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri T

    ifor 1 i n

    A Rule for Member Functions

    f is an identifier

  • 7/30/2019 type checking compiler

    134/215

    S e0.f(e

    1, ..., e

    n) : ?

    fis an identifier.S e

    0: M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri T

    ifor 1 i n

    A Rule for Member Functions

    f is an identifierS M

  • 7/30/2019 type checking compiler

    135/215

    S e0.f(e

    1, ..., e

    n) : ?

    fis an identifier.S e

    0: M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    A Rule for Member Functions

    f is an identifier.S M

  • 7/30/2019 type checking compiler

    136/215

    S e0.f(e

    1, ..., e

    n) : ?

    fis an identifier.S e

    0: M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    A Rule for Member Functions

    f is an identifier.S M

  • 7/30/2019 type checking compiler

    137/215

    S e0.f(e

    1, ..., e

    n) : U

    fis an identifier.S e

    0: M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Legal Code?class Id {

    Id me() {

    return this;}

  • 7/30/2019 type checking compiler

    138/215

    }

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    Legal Code?class Id {

    Id me() {

    return this;}

  • 7/30/2019 type checking compiler

    139/215

    }

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    Legal Code?class Id {

    Id me() {

    return this;}

  • 7/30/2019 type checking compiler

    140/215

    }

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    Ego

    Legal Code?class Id {

    Id me() {

    return this;

    }

  • 7/30/2019 type checking compiler

    141/215

    }

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    Ego

    Legal Code?class Id {

    Id me() {

    return this;

    } fis an identifier.S e : M

  • 7/30/2019 type checking compiler

    142/215

    }

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    S e0.f(e

    1, ..., e

    n) : U

    S e0

    : M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Ego

    Legal Code?class Id {

    Idme() {

    return this;

    } fis an identifier.S e : M

  • 7/30/2019 type checking compiler

    143/215

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    S e0.f(e

    1, ..., e

    n) : U

    S e0

    : M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Ego

    Legal Code?class Id {

    Idme() {

    return this;

    } fis an identifier.S e : M

  • 7/30/2019 type checking compiler

    144/215

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    S e0.f(e

    1, ..., e

    n) : U

    S e0

    : M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    IdEgo

    Legal Code?class Id {

    Idme() {

    return this;

    } fis an identifier.S e : M

  • 7/30/2019 type checking compiler

    145/215

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    S e0.f(e

    1, ..., e

    n) : U

    S e0

    : M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    IdEgo

    Legal Code?class Id {

    Idme() {

    return this;

    } fis an identifier.S e0

    : M

  • 7/30/2019 type checking compiler

    146/215

    void beSelfish() {

    /* */

    }

    }

    class Ego extends Id {

    void bePractical() {

    /* */

    }

    }

    int main() {

    (new Ego).me().bePractical();

    }

    S e0.f(e

    1, ..., e

    n) : U

    S e0

    : M

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    bePracticalis not in

    Id!Id

    Ego

    Limitations of Static Type Systems

    Static type systems are often incomplete.

    There are valid programs that are rejected.

  • 7/30/2019 type checking compiler

    147/215

    p g j

    Tension between the static and dynamic typesof objects.

    Static type is the type declared in the programsource.

    Dynamic type is the actual type of the object atruntime.

    Soundness and Completeness

    Static type systems sometimes reject valid

    programs because they cannot prove theb f t

  • 7/30/2019 type checking compiler

    148/215

    p g y pabsence of a type error.

    A type system like this is called incomplete.

    Instead, try to prove for every expression thatDynamicType(E) StaticType(E)

    A type system like this is called sound.

    Building a Good Static Checker

    It is difficult to build a good static type checker.

    Easy to have unsound rules.

  • 7/30/2019 type checking compiler

    149/215

    Impossible to accept all valid programs.

    Goal: make the language as expressive as

    possible while still making the type-checkersound.

    Relaxing our Restrictions

    class Base {

    Base clone() {

  • 7/30/2019 type checking compiler

    150/215

    return new Base;

    }

    }

    class Derived extends Base {

    Base clone() {

    return new Derived;

    }}

    Relaxing our Restrictions

    class Base {

    Base clone() {

  • 7/30/2019 type checking compiler

    151/215

    return new Base;

    }

    }

    class Derived extends Base {

    Base clone() {

    return new Derived;

    }}

    Relaxing our Restrictions

    class Base {

    Base clone() {

  • 7/30/2019 type checking compiler

    152/215

    return new Base;

    }

    }

    class Derived extends Base {

    Derivedclone() {

    return new Derived;

    }}

    Relaxing our Restrictions

    class Base {

    Base clone() {

  • 7/30/2019 type checking compiler

    153/215

    return new Base;

    }

    }

    class Derived extends Base {

    Derivedclone() {

    return new Derived;

    }}

    Is this safe?

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    154/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    155/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    156/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    157/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    158/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    159/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    160/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    161/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    162/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    The Intuition

    Base b = new Base;

    Derived d = new Derived;

  • 7/30/2019 type checking compiler

    163/215

    Base b2 = b.clone();

    Base b3 = d.clone();

    Derived d2 = b.clone();

    Derived d3 = d.clone();

    Base reallyD = new Derived;

    Base b4 = reallyD.clone();

    Derived d4 = reallyD.clone();

    Is this Safe?

    fis an identifier.S e

    0: M

    f is a member function in class M

  • 7/30/2019 type checking compiler

    164/215

    S e0.f(e

    1, ..., e

    n) : U

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Is this Safe?

    fis an identifier.S e

    0: M

    f is a member function in class M

    This refers to the

    static type of the

    function.

  • 7/30/2019 type checking compiler

    165/215

    S e0.f(e

    1, ..., e

    n) : U

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Is this Safe?

    fis an identifier.S e

    0: M

    f is a member function in class M

    This refers to the

    static type of the

    function.

  • 7/30/2019 type checking compiler

    166/215

    S e0.f(e

    1, ..., e

    n) : U

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    f has dynamic type

    (T1, T

    2, , T

    n) V

    and we know that

    V U

    Is this Safe?

    fis an identifier.S e

    0: M

    f is a member function in class M.

    This refers to the

    static type of the

    function.

  • 7/30/2019 type checking compiler

    167/215

    S e0.f(e

    1, ..., e

    n) : U

    fis a member function in class M.fhas type (T

    1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    f has dynamic type

    (T1, T

    2, , T

    n) V

    and we know that

    V U

    So the rule is sound!

    Covariant Return Types

    Two functions A and B are covariant in their

    return types if the return type of A is convertibleto the return type of B.

  • 7/30/2019 type checking compiler

    168/215

    Many programming language support covariantreturn types.

    C++ and Java, for example.

    Not supported in Decaf.

    But easy extra credit!

    Relaxing our Restrictions (Again)

    class Base {

    bool equalTo(Base B) {/* */

  • 7/30/2019 type checking compiler

    169/215

    }

    }

    class Derived extends Base {

    bool equalTo(Base B) {

    /* */

    }}

    Relaxing our Restrictions (Again)

    class Base {

    bool equalTo(Base B) {/* */

  • 7/30/2019 type checking compiler

    170/215

    }

    }

    class Derived extends Base {

    bool equalTo(Base B) {

    /* */

    }}

    Relaxing our Restrictions (Again)

    class Base {

    bool equalTo(Base B) {/* */

  • 7/30/2019 type checking compiler

    171/215

    }

    }

    class Derived extends Base {

    bool equalTo(DerivedB) {

    /* */

    }}

    Relaxing our Restrictions (Again)

    class Base {

    bool equalTo(Base B) {/* */

  • 7/30/2019 type checking compiler

    172/215

    }

    }

    class Derived extends Base {

    bool equalTo(Derived D) {

    /* */

    }}

    Relaxing our Restrictions (Again)

    class Base {

    bool equalTo(Base B) {/* */

  • 7/30/2019 type checking compiler

    173/215

    Is this safe?

    }

    }

    class Derived extends Base {

    bool equalTo(Derived D) {

    /* */

    }}

    Is this Safe?

    fis an identifier.S e

    0: M

    fis a member function in class M.

  • 7/30/2019 type checking compiler

    174/215

    S e0.f(e

    1, ..., e

    n) : U

    fhas type (T1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Is this Safe?

    fis an identifier.S e

    0: M

    fis a member function in class M.f h t (T T ) U

    This refers to the

    static type of the

    function.

  • 7/30/2019 type checking compiler

    175/215

    S e0.f(e

    1, ..., e

    n) : U

    fhas type (T1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Is this Safe?

    fis an identifier.S e

    0: M

    fis a member function in class M.f h t (T T ) U

    This refers to the

    static type of the

    function.

  • 7/30/2019 type checking compiler

    176/215

    S e0.f(e

    1, ..., e

    n) : U

    fhas type (T1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    f has dynamic type

    (V1, V2, , Vn) U

    and we know that

    Vi T

    ifor 1 i n

    Is this Safe?

    fis an identifier.S e

    0: M

    fis a member function in class M.f h t (T T ) U

    This refers to the

    static type of the

    function.

  • 7/30/2019 type checking compiler

    177/215

    S e0.f(e

    1, ..., e

    n) : U

    fhas type (T1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    f has dynamic type

    (V1, V2, , Vn) U

    and we know that

    Vi T

    ifor 1 i nRi Ti for 1 i n

    Vi Ti for 1 i n

    Is this Safe?

    fis an identifier.S e 0 : M

    fis a member function in class M.f has type (T T ) U

    This refers to the

    static type of the

    function.

  • 7/30/2019 type checking compiler

    178/215

    S e0.f(e

    1, ..., e

    n) : U

    fhas type (T1, , T

    n) U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    f has dynamic type

    (V1, V2, , Vn) U

    and we know that

    Vi T

    ifor 1 i nRi Ti for 1 i n

    Vi Ti for 1 i n

    This doesn't mean thatR

    i V

    ifor 1 i n

    A Concrete Example

  • 7/30/2019 type checking compiler

    179/215

    A Concrete Exampleclass Fine {

    void nothingFancy(Fine f) {

    /* do nothing */

    }}

    class Borken extends Fine {

  • 7/30/2019 type checking compiler

    180/215

    class Borken extends Fine {

    int missingFn() {

    return 137;

    }void nothingFancy(Borken b) {

    Print(b.missingFn());

    }

    }

    int main() {Fine f = new Borken;

    f.nothingFancy(f);

    }

    A Concrete Exampleclass Fine {

    void nothingFancy(Fine f) {

    /* do nothing */

    }}

    class Borken extends Fine {

  • 7/30/2019 type checking compiler

    181/215

    class Borken extends Fine {

    int missingFn() {

    return 137;

    }void nothingFancy(Borken b) {

    Print(b.missingFn());

    }

    }

    int main() {Fine f = new Borken;

    f.nothingFancy(f);

    }

    A Concrete Exampleclass Fine {

    void nothingFancy(Fine f) {

    /* do nothing */

    }}

    class Borken extends Fine {

  • 7/30/2019 type checking compiler

    182/215

    class Borken extends Fine {

    int missingFn() {

    return 137;

    }void nothingFancy(Borken b) {

    Print(b.missingFn());

    }

    }

    int main() {Fine f = new Borken;

    f.nothingFancy(new Fine);

    }

    A Concrete Exampleclass Fine {

    void nothingFancy(Fine f) {

    /* do nothing */

    }}

    class Borken extends Fine {

  • 7/30/2019 type checking compiler

    183/215

    {

    int missingFn() {

    return 137;

    }void nothingFancy(Borken b) {

    Print(b.missingFn());

    }

    }

    int main() {Fine f = new Borken;

    f.nothingFancy(new Fine);

    }

    A Concrete Exampleclass Fine {

    void nothingFancy(Fine f) {

    /* do nothing */

    }}

    class Borken extends Fine {

  • 7/30/2019 type checking compiler

    184/215

    {

    int missingFn() {

    return 137;

    }void nothingFancy(Borken b) {

    Print(b.missingFn());

    }

    }

    int main() {Fine f = new Borken;

    f.nothingFancy(new Fine);

    }

    (That calls this

    one)

    A Concrete Exampleclass Fine {

    void nothingFancy(Fine f) {

    /* do nothing */

    }}

    class Borken extends Fine {

  • 7/30/2019 type checking compiler

    185/215

    int missingFn() {

    return 137;

    }void nothingFancy(Borken b) {

    Print(b.missingFn());

    }

    }

    int main() {Fine f = new Borken;

    f.nothingFancy(new Fine);

    }

    (That calls this

    one)

    A Concrete Exampleclass Fine {

    void nothingFancy(Fine f) {

    /* do nothing */

    }}

    class Borken extends Fine {

    Problem?

  • 7/30/2019 type checking compiler

    186/215

    int missingFn() {

    return 137;

    }void nothingFancy(Borken b) {

    Print(b.missingFn());

    }

    }

    int main() {Fine f = new Borken;

    f.nothingFancy(new Fine);

    }

    (That calls this

    one)

    Covariant Arguments are Unsafe

    Allowing subclasses to restrict their parameter

    types is fundamentally unsafe. Calls through base class can send objects of

    the wrong type down to base classes

  • 7/30/2019 type checking compiler

    187/215

    the wrong type down to base classes.

    This is why Java's Object.equals takesanotherObject.

    Some languages got this wrong.

    Eiffel allows functions to be covariant in theirarguments; can cause runtime errors.

    Contravariant Arguments

    class Super {}

    class Base extends Super {

    bool equalTo(Base B) {/* */

    }

  • 7/30/2019 type checking compiler

    188/215

    }

    }

    class Derived extends Base {

    bool equalTo(Base B) {

    /* */

    }}

    Contravariant Argumentsclass Super {}

    class Base extends Super {

    bool equalTo(Base B) {/* */

    }

  • 7/30/2019 type checking compiler

    189/215

    }

    }

    class Derived extends Base {

    bool equalTo(Base B) {

    /* */

    }}

    Contravariant Argumentsclass Super {}

    class Base extends Super {

    bool equalTo(Base B) {/* */

    }

  • 7/30/2019 type checking compiler

    190/215

    }

    }

    class Derived extends Base {

    bool equalTo(Super B) {

    /* */

    }}

    Contravariant Argumentsclass Super {}

    class Base extends Super {

    bool equalTo(Base B) {/* */

    }

  • 7/30/2019 type checking compiler

    191/215

    }

    }

    class Derived extends Base {

    bool equalTo(Super B) {

    /* */

    }}

    Contravariant Argumentsclass Super {}

    class Base extends Super {

    bool equalTo(Base B) {/* */

    }

  • 7/30/2019 type checking compiler

    192/215

    }

    }

    class Derived extends Base {

    bool equalTo(Super B) {

    /* */

    }} Is this safe?

    Is this Safe?

    fis an identifier.

    S e 0 : Mfis a member function in class M.

    fhas type (T1, , T

    n) U

  • 7/30/2019 type checking compiler

    193/215

    S e0.f(e

    1, ..., e

    n) : U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Is this Safe?

    fis an identifier.

    S e 0 : Mfis a member function in class M.

    fhas type (T1, , T

    n) U

    This refers to the

    static type of the

    function.

  • 7/30/2019 type checking compiler

    194/215

    S e0.f(e

    1, ..., e

    n) : U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    Is this Safe?

    fis an identifier.

    S e 0 : Mfis a member function in class M.

    fhas type (T1, , T

    n) U

    This refers to the

    static type of the

    function.

    f has dynamic type

  • 7/30/2019 type checking compiler

    195/215

    S e0.f(e

    1, ..., e

    n) : U

    S ei: R

    ifor 1 i n

    Ri Ti for 1 i n

    f has dynamic type

    (V1, V2, , Vn) U

    and we know that

    Ti V

    ifor 1 i n

    Is this Safe?

    fis an identifier.

    S e 0 : Mfis a member function in class M.

    fhas type (T1, , T

    n) U

    S R f 1 i

    This refers to the

    static type of the

    function.

    f has dynamic type

  • 7/30/2019 type checking compiler

    196/215

    S e0.f(e

    1, ..., e

    n) : U

    S ei: R

    ifor 1 i n

    Ri T

    ifor 1 i n

    f has dynamic type

    (V1, V2, , Vn) U

    and we know that

    Ti V

    ifor 1 i nRi Ti for 1 i n

    Ti Vi for 1 i n

    Is this Safe?

    fis an identifier.

    S e 0 : Mfis a member function in class M.

    fhas type (T1, , T

    n) U

    S R f 1 i

    This refers to the

    static type of the

    function.

    f has dynamic type

  • 7/30/2019 type checking compiler

    197/215

    S e0.f(e

    1, ..., e

    n) : U

    S ei: R

    ifor 1 i n

    Ri T

    ifor 1 i n

    f has dynamic type

    (V1, V2, , Vn) U

    and we know that

    Ti V

    ifor 1 i nRi Ti for 1 i n

    Ti Vi for 1 i nso

    Ri V

    ifor 1 i n

    Contravariant Arguments are Safe

    Intuition: When called through base class, will

    accept anything the base class already would. Most languages do not support contravariant

    arguments.

  • 7/30/2019 type checking compiler

    198/215

    Why?

    Increases the complexity of the compiler and thelanguage specification.

    Increases the complexity of checking methodoverrides.

    Contravariant Overridesclass Super {}

    class Duper extends Super {}

    class Base extends Super {

    bool equalTo(Base B) {

    /* */

    }

    }

  • 7/30/2019 type checking compiler

    199/215

    }

    class Derived extends Base {bool equalTo(Super B) {

    /* */

    }

    bool equalTo(Duper B) {

    /* */}

    }

    Contravariant Overridesclass Super {}

    class Duper extends Super {}

    class Base extends Super {

    bool equalTo(Base B) {/* */

    }

    }

  • 7/30/2019 type checking compiler

    200/215

    }

    class Derived extends Base {bool equalTo(Super B) {

    /* */

    }

    bool equalTo(Duper B) {

    /* */}

    }

    Two overrides?Or an overload

    and an override?

    So What?

    Need to be very careful when introducing

    language features into a statically-typedlanguage.

    Easy to design language features; hard to

  • 7/30/2019 type checking compiler

    201/215

    design language features that are type-safe.

    Type proof system can sometimes help detectthese errors in the abstract.

    Array Polymorphism

    In some languages like C++ and Java, it is

    possible to treat arrays of objectspolymorphically.

    class A { };

    l B bli A { }

    class A { };

    l B t d A { }

  • 7/30/2019 type checking compiler

    202/215

    Is this safe?

    class B: public A { };

    B* bArray = new B[137];A* aArray = bArray;

    class B extends A { };

    B[] bArray = new B[137];A[] aArray = bArray;

    A Different Approach to Arrays

    Think of arrays as classes:

    class ArrayOfA {public A getElement(int index);

    }

  • 7/30/2019 type checking compiler

    203/215

    class ArrayOfB extends ArrayOfA {

    public B getElement(int index);

    }

    A Different Approach to Arrays

    Think of arrays as classes:

    class ArrayOfA {publicA getElement(int index);

    }

  • 7/30/2019 type checking compiler

    204/215

    class ArrayOfB extends ArrayOfA {

    public B getElement(int index);

    }

    A Different Approach to Arrays

    Think of arrays as classes:

    class ArrayOfA {publicA getElement(int index);

    }

  • 7/30/2019 type checking compiler

    205/215

    class ArrayOfB extends ArrayOfA {

    public B getElement(int index);

    }

    Is this safe?

    A Different Approach to Arrays

    Think of arrays as classes:

    class ArrayOfA {publicA getElement(int index);

    }

  • 7/30/2019 type checking compiler

    206/215

    class ArrayOfB extends ArrayOfA {

    public B getElement(int index);

    }

    Is this safe?

    Yes!

    A Different Approach to Arrays

    Think of arrays as classes:

    class ArrayOfA {public A getElement(int index);

    public void setElement(int index, A value);

    }

  • 7/30/2019 type checking compiler

    207/215

    class ArrayOfB extends ArrayOfA {

    public B getElement(int index);

    public void setElement(int index, B value);

    }

    A Different Approach to Arrays

    Think of arrays as classes:

    class ArrayOfA {public A getElement(int index);

    public void setElement(int index, A value);

    }

  • 7/30/2019 type checking compiler

    208/215

    class ArrayOfB extends ArrayOfA {

    public B getElement(int index);

    public void setElement(int index, B value);

    }

    A Different Approach to Arrays

    Think of arrays as classes:

    class ArrayOfA {public A getElement(int index);

    public void setElement(int index, A value);

    }

  • 7/30/2019 type checking compiler

    209/215

    class ArrayOfB extends ArrayOfA {

    public B getElement(int index);

    public void setElement(int index, B value);

    }

    Is this safe?

    A Different Approach to Arrays

    Think of arrays as classes:

    class ArrayOfA {public A getElement(int index);

    public void setElement(int index, A value);

    }

  • 7/30/2019 type checking compiler

    210/215

    class ArrayOfB extends ArrayOfA {

    public B getElement(int index);

    public void setElement(int index, B value);

    }

    Is this safe?

    No!

    Problematic Java Code

    class A {

    }

    class B extends A {

    public static void main(String[] args) {

    A[] arr new B[137];

  • 7/30/2019 type checking compiler

    211/215

    A[] arr = new B[137];

    arr[0] = new A();}

    }

    Problematic Java Code

    class A {

    }

    class B extends A {

    public static void main(String[] args) {

    A[] arr = new B[137];

  • 7/30/2019 type checking compiler

    212/215

    A[] arr = new B[137];

    arr[0] = new A();}

    }

    Java's Solution

    All array writes checked at runtime.

    ThrowsArrayStoreException if the elementstored in an array has the wrong type.

    Pay at runtime for something that could be

  • 7/30/2019 type checking compiler

    213/215

    detected at compile-time.

    Almost no benefits in practice; arraypolymorphism is rarely used.

    Java's Solution

    All array writes checked at runtime.

    ThrowsArrayStoreException if the elementstored in an array has the wrong type.

    Pay at runtime for something that could be

  • 7/30/2019 type checking compiler

    214/215

    detected at compile-time.

    Almost no benefits in practice; arraypolymorphism is rarely used.

    Please don't add this as an extension to Decaf.

    Summary

    We can extend our type proofs to handle well-formedness proofs.

    The error type is convertible to all other types and helpsprevent cascading errors.

    Overloading is resolved at compile-time and determineshi h f f ti t ll

  • 7/30/2019 type checking compiler

    215/215

    which of many functions to call.

    Overloading ranks functions against one another todetermine the best match.

    Functions can safely be covariant in their return typesand contravariant in their argument types.

    Don't treat arrays polymorphically!