  A key challenge when statically typing so-called dynamic languages is the
ubiquity of value-based overloading, where a given function can dynamically
reflect upon and behave according to the types of its arguments. Thus, to
establish basic types, the analysis must reason precisely about values, but in
the presence of higher-order functions and polymorphism, this reasoning itself
can require basic types. In this paper we address this chicken-and-egg problem
by introducing the framework of two-phased typing. The first "trust" phase
performs classical, i.e. flow-, path- and value-insensitive type checking to
assign basic types to various program expressions. When the check inevitably
runs into "errors" due to value-insensitivity, it wraps problematic expressions
with DEAD-casts, which explicate the trust obligations that must be discharged
by the second phase. The second phase uses refinement typing, a flow- and
path-sensitive analysis, that decorates the first phase's types with logical
predicates to track value relationships and thereby verify the casts and
establish other correctness properties for dynamically typed languages.
