skip to main content
research-article
Free Access

Two Parametricities Versus Three Universal Types

Published:21 September 2022Publication History

Skip Abstract Section

Abstract

The formal calculus System F models the essence of polymorphism and abstract data types, features that exist in many programming languages. The calculus’ core property is parametricity: a theorem expressing the language’s abstractions and validating important principles like information hiding and modularity.

When System F is combined with features like recursive types, mutable state, continuations or exceptions, the formulation of parametricity needs to be adapted to follow suit, for example using techniques like step-indexing, Kripke world-indexing or biorthogonality. However, it is less clear how this formulation should change when System F is combined with untyped languages, gradual types, dynamic sealing and runtime type analysis (typecase) alongside type generation. Extensions of System F with these features have been proven to satisfy forms of parametricity (with Kripke worlds carrying semantic interpretations of types). However, the relative power of the modified formulations of parametricity with respect to others and the relative expressiveness of System F with and without these extensions are unknown.

In this paper, we explain that the aforementioned different settings have a common characteristic: they do not enforce or preserve the lexical scope of System F’s type variables. Formally, this results in the existence of a universal type (note: this is not the same as a universally-quantified type). We explain why standard parametricity is incompatible with such a type and how type worlds resolve this. Building on these insights, we answer two open conjectures from the literature, negatively, and we point out a deficiency in current proposals for combining System F with gradual types.

To make the distinction between languages visually apparent, we typeset elements of System F in a blue, bold font, elements of λσ in a red, sans-serif font, elements of G in an emerald, verbatim font and elements of the blame calculus in an orange, italic font. This kind of syntax highlighting has been proven effective for colourblind and black & white readers too [Patrignani 2020].

Skip 1INTRODUCTION Section

1 INTRODUCTION

System F is a widely influential type system, originally defined by Reynolds [1974] and Girard [1972], featuring parametric polymorphism and an impredicative universe. The core property of System F is parametricity. Parametricity guarantees that polymorphic functions in System F cannot behave differently when invoked at different types. Parametricity is formalised using a logical relation (LR): an (often relational) property about values and terms, derived from their type [Reynolds 1983]. A Fundamental Theorem of Logical Relations or Abstraction Theorem then states that the LR properties are automatically satisfied by any term, without the need to verify their code. For this reason, Wadler [1989] has described them as free theorems. A canonical example is the fact that any value of type \( {{\color {#0C80CF}{\mathbf {\forall X\ldotp X\mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}} \) must behave as the identity function.

It is well known that the formulation of parametricity must be adapted when language features are added to System F. For example, consider a value \( {{\color {#0C80CF}{\mathbf {f}}}} \) of type \( {{\color {#0C80CF}{\mathbf {\forall X\ldotp X\mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}} \). In vanilla System F, it must behave as the identity function, i.e., return its argument in every invocation. If we add general recursion, then there is another possibility: \( {{\color {#0C80CF}{\mathbf {f}}}} \) can also be the function that diverges on every invocation. Adding mutable state changes the situation again: it is now possible for \( {{\color {#0C80CF}{\mathbf {f}}}} \) to return its argument in some invocations and to diverge in others, even though the choice can still not depend on the argument. If we add continuations, then it may be possible for \( {{\color {#0C80CF}{\mathbf {f}}}} \) to return more than once, but still: on every return, the return value must be the one it received as an argument. These behavioural differences are reflected in the different definition of the logical relation used to formalize parametricity. Thus, formulations of parametricity using logical relations capture semantic guarantees about the language as a whole.1

In many cases (like the addition of state mentioned above), it is well understood that a particular change in the formulation of parametricity introduces changes both in the set of equivalences it implies as well as in the logical relation used to state it (see e.g., Dreyer et al. [2010]). However, there are also cases where a certain formulation of parametricity is motivated by technical considerations, but it is not clear what effects this change has on equivalence reasoning and whether the change could have been somehow avoided. Specifically, in this paper, we look at the work by Sumii and Pierce [2003] on logical relations for encryption, the work by Neis et al. [2009]; , 2011] on parametricity in the presence of a dynamic type inspection primitive and runtime type generation, and the work by Ahmed et al. [2017], Toro et al. [2019], and New et al. [2019a] on parametricity in gradually-typed variants of System F. Although they work in different contexts, these authors prove (a form of) parametricity with a logical relation indexed by System F types (or a superset of these types), with the exception of Sumii and Pierce who index with simple types for cryptographic primitives. Additionally, the logical relation used by all these parametricity results (including Sumii and Pierce’s) follow a particular pattern: they are indexed by a type world. For this reason, we refer to these LRs as type-world logical relations (TWLRs). TWLRs should not be regarded as a clearly delineated subclass of logical relations, but rather as a design pattern that can be applied and varied upon in the design of a logical relation.

The type worlds in TWLRs are a form of Kripke worlds: they capture a set of assumptions with respect to which the logical relation holds (or does not hold). There is also an order relation on worlds that expresses when one world (a “future world”) represents a stronger set of assumptions than another and whenever the logical relation holds with respect to a world, it automatically also holds for future worlds. While traditional logical relations (e.g., Reynolds [1983]; Dreyer et al. [2011b]) keep track of semantic interpretations for type variables in a type environment (as we discuss later in section 2.3), the logical relations used by Ahmed et al.; Neis et al.; New et al.; Sumii and Pierce; Toro et al. carry semantic interpretations for dynamically-allocated opaque type variables or seals in the Kripke world. Additionally, instantiating polymorphic functions (or allocating fresh seals in the case of Sumii and Pierce [2003]) results in terms that are only related in a world that stores the relation between the applied types as the type interpretation for the instantiated type (or seal).

So why is the same kind of TWLR used in these three different domains? In this paper, we suggest this is because they are used in settings where the lexical scope of type variables is not enforced. Thus, in types like \( {{\color {#0C80CF}{\mathbf {\forall X\ldotp X \rightarrow A}}}} \) (with \( {{\color {#0C80CF}{\mathbf {X}}}} \) not free in \( {{\color {#0C80CF}{\mathbf {A}}}} \)), it is possible for values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) to escape from their scope, be stored as values of a type that does not mention \( {{\color {#0C80CF}{\mathbf {X}}}} \) (such as \( {\color {#0C80CF}{\mathbf {A}}} \)) and somehow be recovered from there as a value of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) again.

Instead of TWLRs, other work that predates TWLRs used logical relations that enforced such lexical scoping, similar to Reynolds’ original formulation [Reynolds 1983]. Thus, we refer to these traditional logical relations as Reynolds-style logical relations (RLRs).

Although some of our insights might appear obvious, the importance of understanding the pattern of type-world logical relations can be seen in the literature, in two ways. First, if we look at the history of one of the aforementioned results [Ahmed et al. 2017], then we see that an RLR was actually used in a precursor of the work [Matthews and Ahmed 2008]. However, a flaw was later discovered in this proof [Ahmed et al. 2017]. Few details are available about this flaw, but our results make it clear that the RLR could not possibly have been compatible with the language’s non-lexically scoped type variables, i.e., the theorem was wrong, not just the proof. The flaw was resolved by the authors in an unpublished draft by moving to a TWLR [Ahmed et al. 2011] and the whole effort culminated in the mature TWLR of Ahmed et al. [2017].

A second consequence is that researchers had wrong expectations of how program equivalence changes when not enforcing lexical scope of type variables in extensions of System F. Concretely, our insights allow us to disprove two long-standing conjectures made by experts in published literature. These conjectures are respectively related to secure compilation of System F using dynamic sealing (read, idealised encryption) and to the enforcement of parametricity in the presence of dynamic type analysis and runtime type generation. Additionally, we also identify a concern in the interaction between gradually typed languages and polymorphic types. Let us take a closer look at these three topics.

Secure compilation. The field of secure compilation studies high-level programming languages that are compiled to low-level target languages where they may interact with untrusted target-level components. The goal of secure compilation is to ensure that those target-level components can only interact with the compiled code in ways that high-level components can interact with the original code. This constitutes a powerful security property, as it effectively excludes a wide variety of low-level attacks like improper stack manipulation, breaking control flow guarantees, reading from or writing to private memory of other components, inspecting or modifying the implementation of a function, etc.

Formally, secure compilation has been expressed as full abstraction: given two source-level contextually equivalent programs, their target-level compilation are also contextually equivalent (and vice versa) [Abadi 1998].2 Compiler full abstraction has been proven for compilers that rely on address-space layout randomisation [Abadi and Plotkin 2012; Jagadeesan et al. 2011], or secure enclaves [Agten et al. 2012; Patrignani et al. 2015; , 2016; Larmuseau et al. 2015; , 2016], tagged architectures [Juglaret et al. 2015, 2016], dynamic type checking in JavaScript [Fournet et al. 2013], typed closure conversion [Ahmed and Blume 2008], cryptographic primitives [Abadi et al. 1998, 1999, 2000; Bugliesi and Giunti 2007], etc. We refer the interested reader to the survey of Patrignani et al. [2019].

In a paper from the year 2000, Pierce and Sumii [2000] proposed a compiler from System F to a cryptographic lambda calculus, which enforces parametricity using a form of idealised encryption primitives (sealing) called lambda-seal (\( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \)). They conjectured that this compiler was fully abstract, owing part of the complexity of such a proof to the target language being more expressive than the source. Their conjecture has received further research attention, but remains open to this day [Siek and Wadler 2016; Sumii and Pierce 2004]. In other work, the same authors proposed a TWLR for the cryptographic lambda calculus [Sumii and Pierce 2003].

Non-parametric parametricity. Some programming languages include a way to perform intensional type analysis through a type cast operator [Abadi et al. 1995; Rossberg 2003]. This appears to be in direct conflict with parametric polymorphism, possibly violating parametricity and representation independence guarantees [Mitchell 1986]. Researchers have proposed runtime type generation as a way to regain parametricity for languages with a type cast operator. Ideally, when an abstract type is defined, a fresh type name should also be generated at runtime. Such a name should then be used as a runtime representative of the abstract type for type analysis purposes.

Runtime type generation has been proven to indeed provide parametricity guarantees for System F terms that interact with terms that can perform type casts [Neis et al. 2009]. This guarantee has been dubbed non-parametric parametricity.

Neis et al. [2009] also conjectured that their way of using runtime type generation preserves any System F abstraction in their type cast language. Although they do not explain the reasons behind this conjecture, we have an idea of the intuition behind it. Parametricity is the most powerful abstraction programmers think that System F has, so it seems logical to believe that once that has been preserved, all other abstractions will follow. These authors also use a TWLR for stating parametricity in their system, and our results let us conclude that their version is weaker than the parametricity one states with RLR.

Gradual typing. The final field where we contribute new insight is gradual typing. In order to allow programmers to incrementally migrate large, untyped code bases to a typed programming language, gradual programming languages allow for typed and untyped code to interact. Such languages generally strive to preserve the benefits of the statically-typed components of an application, even when interacting with untyped components. Such benefits include performance benefits, absence of runtime type errors but also benefits for reasoning [de Amorim et al. 2020; New et al. 2019b; Toro et al. 2018]. While the literature mentions several ways to formalise the former two properties, the latter has received less attention.

Based on a suggestion in the conference version of this paper [Devriese et al. 2018], Jacobs et al. [2021] have recently proposed to formally express that a gradual language preserves the reasoning principles of the typed language by reusing the same notion of fully abstract compilation that we mentioned above. Specifically, if the embedding of the typed language into the gradual language is fully abstract, then similarly to secure compilation, this expresses that untyped code can only interact with typed code in ways that are also possible using just typed code.3

Also in the field of gradual typing, System F’s parametric polymorphism presents a formidable challenge. The observation that sealing could be useful to combine parametric polymorphism with dynamic typing was already made by Pierce and Sumii [2000]. This idea was further developed with the definition of a gradually-typed language based on this idea [Ahmed et al. 2011; Matthews and Ahmed 2008], the addition of blame in the polymorphic blame calculus [Ahmed et al. 2011a], further developed by Igarashi et al. [2017], Ahmed et al. [2017], Toro et al. [2019] and New et al. [2019a]. The latter two papers also formulate parametricity using a TWLR in the polymorphic blame calculus. In these cases it is also unclear what the benefits are of relying on TWLRs has as opposed to relying on RLR.

Three questions, one answer. To answer these questions, we have to define non-lexical scoping of type variables. Our best formal characterisation is based on the existence of what we call a universal type.4 A universal type is a type which any other type can be embedded into and extracted from. Thus, by this definition, the term universal type is broader than Abadi et al. [1991] \( {\!} \)’s dynamic type or Siek and Taha [2006] \( {\!} \)’s gradual type: the former includes any type that arbitrary values can be embedded into and extracted from, while the latter are specific primitive types, specifically intended for representing untyped values in a typed language.5 We point out that enforcing the lexical scope of type variables forbids the existence of a universal type such as the following one: TODO: I think the following formulation is better (see email): We point out that enforcing the lexical scope of type variables forbids the existence of a universal type. Consider the following definition: \( \begin{*} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \mathrel {\overset{\text{def}}{=}}{{\color {#0C80CF}{\mathbf {\exists Y\ldotp \forall X \ldotp (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}} \end{align*} \)

Type \( {\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}} \) expresses the existence of a universal type \( {{\color {#0C80CF}{\mathbf {Y}}}} \) such that for any other type \( {{\color {#0C80CF}{\mathbf {X}}}} \), there is a mapping from \( {{\color {#0C80CF}{\mathbf {X}}}} \) into \( {{\color {#0C80CF}{\mathbf {Y}}}} \) and vice versa. In a non-terminating variant of System F, there exist inhabitants of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \), but we prove that they are all degenerate in the sense that mapping a value into the universal type and back must necessarily diverge. Our key finding is that this degeneracy can be proven using RLRs (and this illustrates the incompatibility of RLRs with universal types) but it cannot be proven using TWLRs.

Thus, by clarifying the subtleties of TWLRs and RLRs, we solve these aforementioned open problems and answer these questions negatively. Concretely, we prove that Sumii and Pierce’s compiler is not fully abstract, and that System F does not embed fully abstractly into either Neis et al.’s language with a type cast, or any of the published polymorphic blame calculi.

More in detail, Sumii and Pierce’s compiler fails to enforce this degeneracy of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \). In fact, their target language really does contain a universal type: since it is untyped we can think about it as being “uni-typed”, citing Dana Scott [Statman 1991]. As a consequence, their fully abstract compilation conjecture is false, as we will formally show by constructing two System F terms \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) whose contextual equivalence relies on the degeneracy of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \). We can then falsify Sumii and Pierce’s conjecture by showing that these two terms are mapped to non-equivalent terms by their proposed compiler.

In Neis et al.’s language with non-parametric parametricity, we show that type cast operators also break the degeneracy of \( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \), despite the presence of runtime type generation primitives. The type \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \), which is normally only inhabited by diverging terms, becomes a universal type in the presence of a dynamic type cast, as any value can be embedded in it and extracted from it. By relying on this type, System F does not embed fully abstractly into this language, contradicting Neis et al.’s conjecture.

Finally, in the field of gradual typing, we demonstrate that existing polymorphic blame calculi also break the degeneracy of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \).6 Like Sumii and Pierce’s target language, they also provide a universal type: the type of untyped values \( {\color {orange}{\mathit {\star }}} \), common to most gradual languages (also often indicated as \( {\color {orange}{\mathit {?}}} \)). Exploiting the existence of this type, we demonstrate that the polymorphic blame calculus does not embed System F in a fully abstract way and as a result, they do not preserve System F’s parametricity.

To close, we discuss a number of consequences and perspectives that follow from our results. First, we discuss some thoughts on how Sumii and Pierce’s compiler might be fixed (so that it does enforce full abstraction), and what could be modified in the polymorphic blame calculus to make it preserve all of System F’s contextual equivalences. However, in neither case there appears to be a panacea solution: potential fixes all seem to come with certain downsides. Because of this, we also discuss whether we should not instead adjust our expectations and find a way to formalise the guarantees that we do get from both Sumii and Pierce’s compiler, Neis et al.’s sealing wrappers and the polymorphic blame calculus.

Outline. We start our discussion by repeating the definition of System F and defining two logical relations for it (an RLR and a TWLR), which we will use in subsequent proofs (section 2). Then we present type \( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \) and two key terms: \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \), and we discuss their contextual equivalence (Section 3). We then prove that \( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \) is degenerate and that these terms are contextually equivalent using the previously-defined logical relations (section 4). Next, we present Sumii and Pierce’s compiler and disprove their conjecture by explaining how it treats \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and fails to preserve their equivalence (section 5). We then present \( {\color {#41A9A6}{\mathtt {G}}} \), an extension of System F with type casts and runtime type generation and demonstrate how embedding \( {\color {#0C80CF}{\mathbf {t_u }}} \) and \( {\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}} \) into \( {\color {#41A9A6}{\mathtt {G}}} \) breaks contextual equivalence (section 6). Next, we turn to gradual typing, introducing polymorphic blame calculi and demonstrating how the contextual equivalence of \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) is also lost in the presence of these calculi’s universal type (section 7). Finally, we discuss perspectives and consequences of our results (section 8), related work (section 9) and we conclude (section 10). We omit only few auxiliary lemmas, their proofs and tedious, long reductions used in the main proofs, all of this can be found in the supplementary material.

Relation with the Previous Version. This paper extends a paper by the same authors that was published at POPL 2018 [Devriese et al. 2018]. In this version, the main changes include

(1)

a more detailed analysis of the type \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) and how its degeneracy varies in the presence of effects and value polymorphism

(2)

a presentation of a Reynolds-style or lexically-scoped (Section 2.3), Kripke (Section 2.4) and type-world logical relation (Section 2.5),

(3)

a more elegant proof of the degeneracy of \( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \) ( Section 4),

(4)

a detailed analysis of the relation between the different logical relations, non-lexically-scoped type variables and degeneracy of the universal type (Section 4.2), and

(5)

the disproval of the conjecture by Neis et al. [2011] in Section 6.

Skip 2SYSTEM F Section

2 SYSTEM F

We now consider System F itself (Section 2.1), the standard formulation of parametricity for it (Section 2.2) and the different kinds of logical relations for it: Reynolds-style or lexically-scoped (Section 2.3) and type-world (Section 2.5). To introduce type-world logical relations, we first explain their more general variant: Kripke logical relations (Section 2.4).

Note on divergence and recursive types. Technically, the language we should be using is System F with recursive types since that is the language considered by the conjectures we examine [Pierce and Sumii 2000]. We choose against including recursive types in our technical development since their presence is not central to our argument for disproving existing conjectures. Recursive types are required only insofar as System F is allowed some way to diverge. Fortunately, there are simpler ways to allow a language to diverge, as for example the addition of a diverging term (a solution also proposed by Pierce and Sumii [2000] and that we also adopt). Moreover, well-founded logical relations for languages with recursive types require step indices, and the addition of steps makes the technical development noisy without adding particular insights. Thus, in this paper we remove recursive types from System F and instead add a diverging term \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\omega }}} }}} \).

2.1 The Source Language λF

Figure 1 presents the variant of System F that we will be using in this paper, which we indicate with \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \). In addition to standard polymorphic functions (\( {{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \)) and existential packages (\( {{\color {#0C80CF}{\mathbf {{\mathbf {{\color {#0C80CF}{\exists }}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \)), the variant includes \( {{\color {#0C80CF}{\mathbf {{Unit} }}}} \) and \( {{\color {#0C80CF}{\mathbf {{Bool} }}}} \) and product \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _1\mathbf {{\color {#0C80CF}{\times }}} \mathbf {{\color {#0C80CF}{\tau }}} _2}}}} \) types. In the figure, we present types \( \mathbf {{\color {#0C80CF}{\tau }}} \), values \( {{\color {#0C80CF}{\mathbf {v}}}} \) and terms \( {{\color {#0C80CF}{\mathbf {t}}}} \), here the most peculiar addition is \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\omega }}} _{\mathbf {{\color {#0C80CF}{\tau }}}}}}} \), which is a diverging term of type \( \mathbf {{\color {#0C80CF}{\tau }}} \) . We show the most important typing rules \( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \vdash {{\color {#0C80CF}{\mathbf {t}}}}: \mathbf {{\color {#0C80CF}{\tau }}} \) in terms of term and type variable contexts \( \mathbf {{\color {#0C80CF}{\Gamma }}} \) and \( \mathbf {{\color {#0C80CF}{\Delta }}} \) (but we omit context and type well-formedness judgements \( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \vdash \diamond \) and \( \mathbf {{\color {#0C80CF}{\Delta }}} \vdash \mathbf {{\color {#0C80CF}{\tau }}} \)). Finally, we define call-by-value evaluation rules in terms of evaluation contexts \( {{\color {#0C80CF}{\mathbf {{E}}}}} \). There, we indicate the usual capture-avoiding substitution of value \( {\color {#0C80CF}{\mathbf {v}}} \) (or type \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}} \)) for variable \( {\color {#0C80CF}{\mathbf {x}}} \) (or type variable \( {\color {#0C80CF}{\mathbf {X}}} \)) in term \( {\color {#0C80CF}{\mathbf {t}}} \) (or type \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}} \)) as \( {\color {#0C80CF}{\mathbf {t{{\color {black}{\left[{{\color {#0C80CF}{\mathbf {v}}}}{{\color {black}{/}}}{{\color {#0C80CF}{\mathbf {x}}}}\right]}}}}}} \) (as \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} {{\color {black}{\left[{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}}{{\color {black}{/}}}{{\color {#0C80CF}{\mathbf {X}}}}\right]}}}}}} \)). We indicate lists of such substitutions as \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\gamma }}} }}} \).

Fig. 1.

Fig. 1. System F syntax, typing rules and evaluation rules (excerpts). The semantics relation \( {{\color {#0C80CF}{\mathbf {\hookrightarrow }}}} \) relies on the primitive reductions indicated as \( {{\color {#0C80CF}{\mathbf {\hookrightarrow _0}}}} \) .

Program contexts \( {{\color {#0C80CF}{\mathbf {{C}}}}} \) are defined as terms with exactly one subterm replaced by a hole \( {{\color {#0C80CF}{\mathbf {\left[\cdot \right]}}}} \). An omitted well-typedness judgement for program contexts \( {{\color {#0C80CF}{\mathbf {{C}}}}}: \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}};\mathbf {{\color {#0C80CF}{\tau }}} \rightarrow {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Delta }}}^{\prime }}}}};{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Gamma }}}^{\prime }}}}};{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} ^{\prime }}}}} \) guarantees that plugging a well-typed term \( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \vdash {{\color {#0C80CF}{\mathbf {t}}}}: \mathbf {{\color {#0C80CF}{\tau }}} \) in the hole produces the well-typed resulting term \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Delta }}}^{\prime }}}}};{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Gamma }}}^{\prime }}}}}\vdash {{\color {#0C80CF}{\mathbf {{C}}}}}{{\color {#0C80CF}{\mathbf {\left[t\right]}}}}:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} ^{\prime }}}}} \).

Definition 2.1

(Contextual Equivalence)

For two terms \( {{\color {#0C80CF}{\mathbf {t_1,t_2}}}} \) that have the same type \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}} \) in the same contexts \( \mathbf {{\color {#0C80CF}{\Delta }}} \) and \( \mathbf {{\color {#0C80CF}{\Gamma }}} \), we define that they are contextually equivalent (\( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \vdash {{\color {#0C80CF}{\mathbf {t_1}}}} \mathrel {{{\color {#0C80CF}{\mathbf {\mathrel {\simeq }}}}}}{{\color {#0C80CF}{\mathbf {t_2}}}} : \mathbf {{\color {#0C80CF}{\tau }}} \)) iff for all \( {{\color {#0C80CF}{\mathbf {{C}}}}} \) such that \( \vdash {{\color {#0C80CF}{\mathbf {{C}}}}}: \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}},\mathbf {{\color {#0C80CF}{\tau }}} \rightarrow {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}},{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \), we have that \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {{C}}}}}{{\color {#0C80CF}{\mathbf {\left[t_1\right]}}}} \Uparrow }}}} \) iff \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {{C}}}}}{{\color {#0C80CF}{\mathbf {\left[t_2\right]}}}} \Uparrow }}}} \), where \( \Uparrow \) indicates divergence [Plotkin 1977].

Value polymorphism. An interesting aspect of this definition of System F is that the body of a polymorphic functions \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp t}}}} \) is a general term \( {{\color {#0C80CF}{\mathbf {t}}}} \). This means that it is possible for polymorphic functions to diverge or perform effects when instantiated. This means, for example, that the polymorphic type \( {{\color {#0C80CF}{\mathbf {{\forall }X\ldotp \bot }}}} \) (for an empty type \( \bot \)) is inhabited by the function \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp \mathbf {{\color {#0C80CF}{\omega }}} }}}} \). In effectful variants of System F, we could similarly write a function of type \( {{\color {#0C80CF}{\mathbf {{\forall }X\ldotp {{\color {#0C80CF}{\mathbf {Ref}}}}~({{\color {#0C80CF}{\mathbf {Maybe}}}}~X)}}}} \): \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp {{\color {#0C80CF}{\mathbf {ref}}}}~{{\color {#0C80CF}{\mathbf {nothing}}}}}}}} \). For this function, it is important that different applications of this function are evaluated separately and produce different mutable reference locations, as otherwise, we could use a single location to store a value of one type and read a value of another, leading to a type error. In particular, this means that polymorphic lambdas and type applications cannot be erased away in an untyped execution scheme.

Although the choice of allowing arbitrary terms in the body of a polymorphic function is standard in formal accounts of System F, imperative polymorphic languages like ML make a different choice. They use value polymorphism, originally proposed by Wright [1995], which restricts ML polymorphism to values. This choice can be modeled in System F by restricting the syntax of polymorphic functions from \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp t}}}} \) to \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp v}}}} \), i.e., the body of the polymorphic function must be a syntactic value [Pitts 1998]. Value polymorphism is not central to our technical development, but we will come back to this in Section 3.2 when discussing the aforementioned universal type in more general settings.

2.2 Parametricity

The main information hiding mechanism in \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) is parametric polymorphism: the representation type of an existentially quantified package is invisible outside the package, and hence clients of the package cannot depend on that representation type.

Example 2.2

(Zn Implementation in λF)

We could for instance represent the type \( \mathbb {Z}_n \) of integers modulo \( n \) as a tuple \( {{\color {#0C80CF}{\mathbf {\left\langle \left\langle zero,succ \right\rangle ,zero? \right\rangle }}}} \) of type \( {{\color {#0C80CF}{\mathbf {{\exists X\ldotp X \mathbf {{\color {#0C80CF}{\times }}} (X \mathbf {{\color {#0C80CF}{\rightarrow }}} X) \mathbf {{\color {#0C80CF}{\times }}} (X \mathbf {{\color {#0C80CF}{\rightarrow }}} {Bool})}}}}} \), and then implement this type as a \( k \)-tuple of booleans.

Example 2.3

(Example Polymorphic Function Type in λF)

Dually, the type system ensures that code cannot depend on parameters of universally quantified types, for instance the only thing a function of type \( {{\color {#0C80CF}{\mathbf {\forall X \ldotp X \mathbf {{\color {#0C80CF}{\times }}} X \mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}} \) can do is return one of its two arguments or diverge.

Reynolds formalised (relational) parametricity in the form of a theorem that all \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) terms of a certain type satisfy a property that can be derived from their type [Reynolds 1983]. For example, if we assume a value \( {{\color {#0C80CF}{\mathbf {f}}}} \) of type \( {{\color {#0C80CF}{\mathbf {\forall X\ldotp X\mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}} \), then parametricity states that for any closed types \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _1,\mathbf {{\color {#0C80CF}{\tau }}} _2}}}} \), any relation \( R \) between values of types \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _1}}}} \) and \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _2}}}} \), and any two closed values \( {{\color {#0C80CF}{\mathbf {v_1,v_2}}}} \) of type \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _1}}}} \) and \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _2}}}} \) respectively, if \( ({{\color {#0C80CF}{\mathbf {v_1}}}},{{\color {#0C80CF}{\mathbf {v_2}}}}) \) is in \( R \), then \( {{\color {#0C80CF}{\mathbf {f~\mathbf {{\color {#0C80CF}{\tau }}} _1~v_1}}}} \) and \( {{\color {#0C80CF}{\mathbf {f~\mathbf {{\color {#0C80CF}{\tau }}} _2~v_2}}}} \) will either both diverge or reduce to values \( ({{\color {#0C80CF}{\mathbf {v_1^{\prime }}}}},{{\color {#0C80CF}{\mathbf {v_2^{\prime }}}}}) \in R \). The relational property is derived from the type using what is known as a logical relation.

2.3 Reynolds-style Logical Relation

As we explained in the introduction, this logical relation can be defined in various ways. For our purposes, it is instructive to first consider Reynolds’ original definition. For simplicity and because it suffices for our purposes, we present a unary variant.7

The Reynolds-style or lexically-scoped Logical Relation (RLR) defines a relation on values \( {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {\cdot }}}}{]\!]} ^{}}}} \) and on terms \( {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {\cdot }}}}{]\!]} ^{}}}} \). Both are indexed with a type environment \( \mathbf {{\color {#0C80CF}{\rho }}} \), which maps type variables to a closed type \( \mathbf {{\color {#0C80CF}{\tau }}} \) and a relation \( {{\color {#0C80CF}{\mathbf {R}}}} \) on values of type \( \mathbf {{\color {#0C80CF}{\tau }}} \). The value relation \( {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {\cdot }}}}{]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}}{} \) for type variables \( {\color {#0C80CF}{\mathbf {X}}} \) defers to the appropriate entry in \( \mathbf {{\color {#0C80CF}{\rho }}} \) for type variables \( {{\color {#0C80CF}{\mathbf {X}}}} \). Otherwise, the value relation accepts boolean and unit values when they are of canonical form and pairs when both components are in the appropriate relation themselves. For function types, the value relation accepts appropriately typed lambdas that map related values to related terms. We apply the type environment to the type \( \mathbf {{\color {#0C80CF}{\tau }}} \) (denoted with \( \mathbf {{\color {#0C80CF}{\rho }}} (\mathbf {{\color {#0C80CF}{\tau }}}) \)) to indicate type \( \mathbf {{\color {#0C80CF}{\tau }}} \) with any type variable \( {\color {#0C80CF}{\mathbf {X}}} \) replaced with its binding in \( \mathbf {{\color {#0C80CF}{\rho }}} \), i.e., with \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\rho }}} (X).1}}}} \). Polymorphic functions are accepted when they can be applied to an arbitrary type \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \) and an arbitrary relation \( {{\color {#0C80CF}{\mathbf {R}}}} \) on \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \) to obtain a term in the appropriate term relation, with \( \mathbf {{\color {#0C80CF}{\rho }}} \) extended with \( {{\color {#0C80CF}{\mathbf {R}}}} \). Finally, existential packages must contain a type \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \) and a value related at the appropriate type, extending \( \mathbf {{\color {#0C80CF}{\rho }}} \) with some relation \( {{\color {#0C80CF}{\mathbf {R}}}} \) on \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \). Values in the value relation are also required to be syntactically well-typed, as denoted by function \( {{{\color {black}{\mathtt {oftype}\left({{\color {#0C80CF}{\mathbf {v}}}},\mathbf {{\color {#0C80CF}{\tau }}} \right)}}}} \), which simply checks \( {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {v}}}}:\mathbf {{\color {#0C80CF}{\tau }}} \). The term relation accepts terms that diverge or produce a suitable value.

We can then define relations on environments \( {{\color {black}{\mathcal {G}{[\![} {{\color {#0C80CF}{\mathbf {\cdot }}}}{]\!]} ^{}}}} \) and on type environments \( {{\color {black}{\mathcal {D}{[\![} {{\color {#0C80CF}{\mathbf {\cdot }}}}{]\!]} ^{}}}} \). The former accepts environments which map free variables to values in the appropriate value relation. The latter requires a type and a relation on that type for every free type variable. \( \begin{*} {{\color {black}{\mathcal {G}{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\emptyset }}}}}}}} {]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}} =&\ \lbrace {{\color {#0C80CF}{\mathbf {\emptyset }}}} \rbrace \\ {{\color {black}{\mathcal {G}{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Gamma }}},(x:\mathbf {{\color {#0C80CF}{\tau }}})}}}}}}}} {]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}} =&\ \left\lbrace \mathbf {{\color {#0C80CF}{\gamma }}};{{\color {black}{\left[{{\color {#0C80CF}{\mathbf {v}}}}{{\color {black}{/}}}{{\color {#0C80CF}{\mathbf {x}}}}\right]}}} ~\mathrel {}\middle |\mathrel {}~ \mathbf {{\color {#0C80CF}{\gamma }}} \in {{\color {black}{\mathcal {G}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Gamma }}} }}}} {]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}} \text{ and } {{\color {#0C80CF}{\mathbf {v}}}}\in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}} {]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}} \right\rbrace \\ {{\color {black}{\mathcal {D}{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\emptyset }}}}}}}} {]\!]} ^{}}}} =&\ \lbrace {{\color {#0C80CF}{\mathbf {\emptyset }}}} \rbrace \\ {{\color {black}{\mathcal {D}{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\alpha }}} }}}}}}}} {]\!]} ^{}}}} =&\ \left\lbrace \mathbf {{\color {#0C80CF}{\rho }}},\mathbf {{\color {#0C80CF}{\alpha }}} \mapsto (\mathbf {{\color {#0C80CF}{\tau }}},{{\color {#0C80CF}{\mathbf {R}}}}) ~\mathrel {}\middle |\mathrel {}~ \mathbf {{\color {#0C80CF}{\rho }}} \in {{\color {black}{\mathcal {D}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Delta }}} }}}} {]\!]} ^{}}}} \text{ and } {{\color {#0C80CF}{\mathbf {R}}}} = {{{\color {black}{\mathtt {Rel}\left(\mathbf {{\color {#0C80CF}{\tau }}}\right)}}}} \right\rbrace \end{align*} \)

With these ingredients, we can define the relation \( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \Vdash {{\color {#0C80CF}{\mathbf {t}}}}:\mathbf {{\color {#0C80CF}{\tau }}} \) on open terms. This relation accepts terms \( {{\color {#0C80CF}{\mathbf {t}}}} \) which are in the term relation after appropriately closing their free variables and type variables (Definition 2.4).

Definition 2.4

(Reynolds-style Logical Relation).

\( \begin{*} \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \Vdash {{\color {#0C80CF}{\mathbf {t}}}}:\mathbf {{\color {#0C80CF}{\tau }}} \mathrel {\overset{\text{def}}{=}}&\ \forall \mathbf {{\color {#0C80CF}{\rho }}} \in {{\color {black}{\mathcal {D}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Delta }}} }}}}{]\!]} ^{}}}}, \forall \mathbf {{\color {#0C80CF}{\gamma }}} \in {{\color {black}{\mathcal {G}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Gamma }}} }}}}{]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}}, {{\color {#0C80CF}{\mathbf {t\mathbf {{\color {#0C80CF}{\gamma }}} }}}}\in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}{]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}} \end{align*} \)

We rely on a few results for the RLR, which are listed below. The fundamental property (Theorem 2.5) states that syntactically well-typed terms are in the relation (i.e., they are semantically well-typed). We do not provide proofs of these lemmas as they are quite standard [Dreyer et al. 2011b].

Theorem 2.5 (Fundamental Property for RLR).

if \( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \vdash {{\color {#0C80CF}{\mathbf {t}}}}:\mathbf {{\color {#0C80CF}{\tau }}} \) then \( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \Vdash {{\color {#0C80CF}{\mathbf {t}}}}:\mathbf {{\color {#0C80CF}{\tau }}} \)

Proving the fundamental property relies on a number of standard lemmas. We only mention a few which we will need in the rest of this paper.

First, we have an antireduction lemma (Lemma 2.6) which states that a term \( {{\color {#0C80CF}{\mathbf {t}}}} \) is in the term relation if a term \( {{\color {#0C80CF}{\mathbf {t^{\prime }}}}} \) that it reduces to is.

Lemma 2.6 (Antireduction).

If \( {\color {#0C80CF}{\mathbf {t \mathrel {{{\color {#0C80CF}{\mathbf {\hookrightarrow ^*}}}}}t^{\prime }}}} \) and \( {{\color {#0C80CF}{\mathbf {t^{\prime }}}}}\in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}{]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}} \), then \( {{\color {#0C80CF}{\mathbf {t}}}}\in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}{]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}} \).

Next, we mention two compatibility lemmas: one for functions (Lemma 2.7) and one for applications (Lemma 2.8). Essentially, they state that lambdas and applications are in the logical relation if their subterms are (at appropriate types).

Lemma 2.7 (Compatibility for Functions).

\( \begin{*} \text{If }& \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}},{{\color {#0C80CF}{\mathbf {x:\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}}\Vdash {{\color {#0C80CF}{\mathbf {t}}}}:\mathbf {{\color {#0C80CF}{\tau }}} \text{ then } \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \Vdash {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x:\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }\ldotp t}}}}:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }\mathbf {{\color {#0C80CF}{\rightarrow }}} \mathbf {{\color {#0C80CF}{\tau }}} }}}} \end{align*} \)

Lemma 2.8 (Compatibility for Applications).

\( \begin{*} \text{If }& \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \Vdash {{\color {#0C80CF}{\mathbf {t}}}}:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }\mathbf {{\color {#0C80CF}{\rightarrow }}} \mathbf {{\color {#0C80CF}{\tau }}} }}}} \text{ and } \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \Vdash {{\color {#0C80CF}{\mathbf {t^{\prime }}}}}:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \text{ then } \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \Vdash {{\color {#0C80CF}{\mathbf {t~t^{\prime }}}}}:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}} \end{align*} \)

We also mention the Boring lemma (Lemma 2.9),8 which states that the semantic type relation \( \rho \) can be altered freely as long as the type variables mentioned in the type \( \tau \) are left untouched.

Lemma 2.9 (Boring Lemma).

If \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\rho }}} _1}}} \) and \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\rho }}} _2}}} \) agree on the free type variables of \( \mathbf {{\color {#0C80CF}{\tau }}} \), then \( \begin{*} {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}{]\!]} ^{{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\rho }}} _1}}}}}}}} = {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}{]\!]} ^{{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\rho }}} _2}}}}}}}} \end{align*} \)

Finally, it is worth mentioning that this logical relation can be easily adapted to the use of value polymorphism, discussed in section 2.1. This requires only a change to the case for polymorphic types \( {{\color {#0C80CF}{\mathbf {\forall X\ldotp \tau }}}} \), which then looks as follows: \( \begin{*} {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}}}}}}{]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}}}}}} =\ \left\lbrace {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp v}}}} ~\mathrel {}\middle |\mathrel {}~ \begin{array}{l} {{{\color {black}{\mathtt {oftype}\left({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp v}}}}, {{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}}\right)}}}} \text{ and } \\ \forall {{\color {#0C80CF}{\mathbf {R}}}}\in {{{\color {black}{\mathtt {Rel}\left(\mathbf {{\color {#0C80CF}{\tau ^{\prime }}}}\right)}}}} \ldotp {{\color {#0C80CF}{\mathbf {v}}}}{{\color {black}{\left[\mathbf {{\color {#0C80CF}{\tau ^{\prime }}}}{{\color {black}{/}}}{{\color {#0C80CF}{\mathbf {X}}}}\right]}}}\in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}{]\!]} ^{\mathbf {{\color {#0C80CF}{\rho }}},{{\color {#0C80CF}{\mathbf {X}}}}\mapsto (\mathbf {{\color {#0C80CF}{\tau ^{\prime }}}},{{\color {#0C80CF}{\mathbf {R}}}})}}}} \end{array} \right\rbrace \end{align*} \)

The change is limited: polymorphic function bodies are now restricted to values and the instantiated bodies are now required to be in the value relation rather than the term relation, as one might expect.

2.4 Kripke Logical Relations

For languages with additional features, particularly effects like higher-order state, we can replace the basic logical relation from the previous section with a Kripke logical relation. The idea is to index the logical relation with a form of possible worlds or Kripke worlds \( {{\color {#0C80CF}{\mathbf {W}}}} \) which represent a set of shared assumptions, often about shared state like the heap. Possible worlds are partially ordered by a relation \( \sqsubseteq \), where \( {{\color {#0C80CF}{\mathbf {W^{\prime }}}}} \sqsupseteq {{\color {#0C80CF}{\mathbf {W}}}} \) expresses that \( {{\color {#0C80CF}{\mathbf {W^{\prime }}}}} \) represents a stronger set of assumptions than \( {{\color {#0C80CF}{\mathbf {W}}}} \). A Kripke version of the logical relation from before looks like the one below (as a notation convention, we typeset elements of Kripke LRs with a grey background, to distinguish them from elements of the RLR, which have no background). Note that we do not give a concrete definition of worlds in this section, since the goal here is just to make the reader familiar with their treatment – the next section will provide more concrete details about worlds.

The differences with before are that all cases of the logical relation now mention the world \( {{{\color {#0C80CF}{\mathbf {W}}}}} \) with respect to which values are related. Additionally, the expression relation existentially quantifies over a future world in which resulting values will be related. This generally models the fact that operational steps may introduce fresh assumptions, for example about freshly allocated mutable variables, which the resulting values’ relation depends on. Finally, the value relation for function types \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} \rightarrow \mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \) and \( {{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \) is polymorphically quantified over an arbitrary world \( {{\color {#0C80CF}{\mathbf {W^{\prime } \sqsubseteq W}}}} \) that extends the assumptions of the current world \( {{\color {#0C80CF}{\mathbf {W}}}} \). This represents the fact that these values must be valid whenever they are invoked, including when additional assumptions may have been introduced.

Again, the logical relation is easy to adapt to a value-polymorphic variant of System F, by modifying only the case for polymorphic function types:

As before, the instantiated function body is now required to be in the value relation rather than the term relation.

TODO: i don’t see the benefit of section 2.4, i think 2.5 can be kept and it’s clear and well understandable. perhaps move 2.4 as an appendix for the interested reader?

2.5 Logical Relation with Type Worlds

In this paper, we are not so interested in general effects but we focus on non-lexically-scoped type variables. For this reason, we are interested in a pattern in logical relation definitions that we dub Type World Logical Relations (TWLRs) [Ahmed et al. 2017; Neis et al. 2009; New et al. 2019a; Sumii and Pierce 2003; Toro et al. 2019]. Note that the term is not intended to denote a clearly delineated subclass of logical relations but rather a design pattern that may be used and varied upon in the definition of logical relations. A TWLR is a form of Kripke logical relation which uses Kripke worlds to represent the interpretations of type variables instead of (or in addition to) the semantic type relations \( \mathbf {{\color {#0C80CF}{\rho }}} \). Additionally, when related polymorphic functions are instantiated with related types, the resulting terms are only related in a world that stores the relation between the applied types as the type interpretation for the instantiated type. This different treatment of type environments removes the requirement to enforce the lexical scope of type quantifiers and makes the logical relation compatible with universal types, as we will explain in Section 3.

In a TWLR, worlds are used to store the type \( \mathbf {{\color {#0C80CF}{\tau }}} \) and predicate \( {{\color {#0C80CF}{\mathbf {R}}}} \) on values of type \( \mathbf {{\color {#0C80CF}{\tau }}} \) that are bound to a type variable, i.e., the information that was stored in \( \mathbf {{\color {#0C80CF}{\rho }}} \) in the RLR (see Section 2.3). Here, we present a TWLR variant of the logical relation from section 2.3 which uses worlds that contain types and relations for instantiated type variables. The future world relation \( \sqsubseteq \) enforces that once a binding is added to a world, it can never be removed (this is true for Kripke LRs too, but in Section 2.4 we did not have to define what constitutes worlds).

The attentive reader may notice that our definition of worlds is actually cyclic: worlds map type variables to types and relations, and the relations are themselves world-indexed. As a result, the worlds presented here are not actually well-defined. Fortunately, this is a well-known problem and a standard solution exists: step-indexing [Ahmed 2004; Ahmed et al. 2009; Dreyer et al. 2011a].

Essentially, the idea is to solve the cyclicity by indexing worlds with a number of steps which indicates up to which level they are defined. By carefully (and often tediously) ensuring that all world-indexed definitions only depend on the world up to a suitable number of steps, cyclic reasoning can be ruled out without otherwise changing the argumentation. Because step-indexing tends to complicate the technicalities while otherwise contributing little insight to the reasoning, we choose not to use it here. Instead, we simply ignore the problem in this text and stick to our illegal but comprehensible definition. To readers who wish to understand how the cyclicity can be solved without breaking the basic rules of mathematics, we recommend consulting Ahmed et al. [2017].

Having defined worlds, we can present the TWLR, which follows the same intuition of the RLR save for replacing \( \mathbf {{\color {#0C80CF}{\rho }}} \) with worlds . As before, replacing all type variables \( {\color {#0C80CF}{\mathbf {X}}} \) with their bindings in \( {\color {#0C80CF}{\mathbf {W}}} \) in type \( \mathbf {{\color {#0C80CF}{\tau }}} \) is denoted as \( {\color {#0C80CF}{\mathbf {W(\mathbf {{\color {#0C80CF}{\tau }}})}}} \).

It is crucial to compare the case for against the one from Section 2.3. Contrary to there, the instantiated term \( {{\color {#0C80CF}{\mathbf {t}}}}{{\color {black}{\left[\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }{{\color {black}{/}}}{{\color {#0C80CF}{\mathbf {X}}}}\right]}}} \) is only required to be related in worlds \( {{\color {#0C80CF}{\mathbf {W^{\prime }}}}} + ({{\color {#0C80CF}{\mathbf {X}}}},\mathbf {{\color {#0C80CF}{\tau ^{\prime }}}},{{\color {#0C80CF}{\mathbf {R}}}}) \) that store the relation \( {{\color {#0C80CF}{\mathbf {R}}}} \) as the semantic interpretation for the instantiated type variable \( {{\color {#0C80CF}{\mathbf {X}}}} \).

The last piece we need to formalise is what it means for a world to agree with a type environment \( {\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Delta }}} }}} \), which we denote with . This intuitively replaces the type environment relation \( {{\color {black}{\mathcal {D}{[\![} {{\color {#0C80CF}{\mathbf {\cdot }}}}{]\!]} ^{}}}} \) present in RLR. A world agrees with a type environment when it maps all the type variables of the latter to valid relations, formally:

With these ingredients we can define our Type-World Logical Relation.

Definition 2.10

(Type-World Logical Relation).

The fundamental property of TWLRs is analogous to that for RLR. As in the previous section, we do not provide proofs of these lemmas, which can be derived from similar (binary) statements in the works of e.g., Neis et al. [2009]; Ahmed et al. [2017].

Theorem 2.11 (Fundamental Property for TWLR).

if \( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} \vdash {{\color {#0C80CF}{\mathbf {t}}}}:\mathbf {{\color {#0C80CF}{\tau }}} \) then \( \mathbf {{\color {#0C80CF}{\Delta }}};\mathbf {{\color {#0C80CF}{\Gamma }}} {{\color {black}{\vDash \!\!\vDash }}}{{\color {#0C80CF}{\mathbf {t}}}}:\mathbf {{\color {#0C80CF}{\tau }}} \)

The main result we need from this logical relation is an analogous to Lemma 2.9 (Boring lemma). If we try to naively state such a result for this TWLR too we obtain the wrong statement below (Lemma 2.12).

Lemma 2.12 (Wrong Boring Lemma for TWLR).

If and agree on the free type variables of \( \mathbf {{\color {#0C80CF}{\tau }}} \), then

Contrary to the RLR, this lemma does not hold for our TWLR. If we were to try and prove it, we would quickly get stuck in the cases for lambdas and big lambdas where we get a future world \( W^{\prime } \) of, for example, \( W_1 \) but we have no way to relate it to world \( W_2 \).

The correct statement of Lemma 2.9 (Boring lemma) applied to the TWLR is the following one, which respects world monotonicity.

Lemma 2.13 (Boring Lemma for TWLR).

If , then, \( \forall \mathbf {{\color {#0C80CF}{\tau }}},{{\color {#0C80CF}{\mathbf {v}}}} \)

The premise has changed in this lemma, in fact we are only allowed to extend a world, but not remove bindings from it.

The difference between the RLR of Section 2.3 and the TWLR of this section may appear technical. However, we will see in the next section that this technical change from RLR to TWLR renders a formulation of parametricity compatible with universal types. This fact is witnessed by several TWLR-based parametricity proofs for languages with such types [Ahmed et al. 2011, 2017; Neis et al. 2009, 2011; New et al. 2019a; Sumii and Pierce 2003; Toro et al. 2019]. However, none of those papers observed that using a TWLR reduced the set of equivalences that the LR implies and that this reduction was necessary in the presence of non-lexically-scoped type variables.

Before concluding, it is again interesting to consider what our TWLR would look like for a value-polymorphic language:

Observe that here, the instantiated body is still required to be related by the value relation and thus not able to allocate additional assumptions. This makes sense, since the body cannot allocate, for example, fresh mutable heap locations. However, one particular assumption is still added to the world in which the body is related: the instantiated of \( {{\color {#0C80CF}{\mathbf {X}}}} \) to type \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \) and relation \( {{\color {#0C80CF}{\mathbf {R}}}} \).

In the next sections, we provide further insight into how the use of a TWLR underlines a compatibility with the universal type in the language. We do this by demonstrating the degeneracy of the universal type with LRLS and explaining why such a proof fails using a TWLR. Before showing these technical proofs, we must define the universal type.

Skip 3THE TYPE Univ Section

3 THE TYPE Univ

As mentioned, in this paper we rely heavily on the type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \): \( \begin{*} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \mathrel {\overset{\text def}{=}}{{\color {#0C80CF}{\mathbf {\exists Y\ldotp \forall X \ldotp (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}} \end{align*} \) The type can be read as stating the existence of a universal type \( {{\color {#0C80CF}{\mathbf {Y}}}} \): a type that all other types can be embedded into and extracted from.

In our non-terminating variant of \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \), \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) is clearly inhabited, for example by this value (recall that \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\omega }}} _X}}}} \) is a diverging term of type \( {{\color {#0C80CF}{\mathbf {X}}}} \)): \( \begin{equation*} {{\color {#0C80CF}{\mathbf {{pack}~\left\langle {Unit},\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp \left\langle \mathbf {{\color {#0C80CF}{\lambda }}} \_:X\ldotp {unit},\mathbf {{\color {#0C80CF}{\lambda }}} \_:{Unit} \ldotp \mathbf {{\color {#0C80CF}{\omega }}} _X \right\rangle \right\rangle ~{as}~}}}}{{{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}} } \)

However, this value is degenerate in the sense that injecting a value into the packaged \( {{\color {#0C80CF}{\mathbf {Y}}}} \) and extracting it again diverges. Note that it is not necessarily the function of type \( {{\color {#0C80CF}{\mathbf {Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}} \) that diverges. For example, we can construct the following inhabitants: \( \begin{gather*} {{\color {#0C80CF}{\mathbf {{pack}~\left\langle (\forall Z\ldotp Z),\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp \left\langle \mathbf {{\color {#0C80CF}{\lambda }}} \_:X\ldotp \mathbf {{\color {#0C80CF}{\omega }}} _{\forall Z\ldotp Z},\mathbf {{\color {#0C80CF}{\lambda }}} y:(\forall Z\ldotp Z)\ldotp y ~ X \right\rangle \right\rangle ~{as}~}}}}{{{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}}\\ {{\color {#0C80CF}{\mathbf {{pack}~\left\langle (\forall Z\ldotp Z),\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp \left\langle \mathbf {{\color {#0C80CF}{\lambda }}} \_:X\ldotp \mathbf {{\color {#0C80CF}{\Lambda }}} Z\ldotp \mathbf {{\color {#0C80CF}{\omega }}} _{Z},\mathbf {{\color {#0C80CF}{\lambda }}} y:(\forall Z\ldotp Z)\ldotp y ~ X \right\rangle \right\rangle ~{as}~}}}}{{{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}} \end{gather*} \) These other inhabitants instantiate \( {{\color {#0C80CF}{\mathbf {Y}}}} \) to \( {{\color {#0C80CF}{\mathbf {{\forall }Z\ldotp Z}}}} \) and make the function of type \( {{\color {#0C80CF}{\mathbf {Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}} \) simply use the received value of type \( {{\color {#0C80CF}{\mathbf {{\forall }Z\ldotp Z}}}} \) to obtain the required value of type \( {{\color {#0C80CF}{\mathbf {X}}}} \). It is now the function of type \( {{\color {#0C80CF}{\mathbf {X\mathbf {{\color {#0C80CF}{\rightarrow }}} Y}}}} \) that diverges, either directly or after being applied to a type \( {{\color {#0C80CF}{\mathbf {Z}}}} \).

A crucial observation for this paper is that all System F values of type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) are degenerate in the above sense. Intuitively, this is because a single type \( {{\color {#0C80CF}{\mathbf {Y}}}} \) needs to be chosen, independently of the types \( {{\color {#0C80CF}{\mathbf {X}}}} \) that will be embedded into it. Because nothing is known upfront about these \( {{\color {#0C80CF}{\mathbf {X}}}} \)s and nothing can be learnt about them after invocation (because \( {{\color {#0C80CF}{\mathbf {X}}}} \) must be treated parametrically), no viable choice for \( {{\color {#0C80CF}{\mathbf {Y}}}} \) can be made.9

From another perspective, the degeneracy results from the lexical scope of type variable \( {{\color {#0C80CF}{\mathbf {X}}}} \) in the polymorphic function of type \( {{\color {#0C80CF}{\mathbf {\forall X \ldotp (X \rightarrow Y) \times (Y \rightarrow X)}}}} \). In \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) , implementations of this function are required to respect this lexical scope and importantly, the variable is not in scope at the point where a choice for existential variable \( {{\color {#0C80CF}{\mathbf {Y}}}} \) needs to be made. A non-degenerate implementation of \( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \) essentially must somehow pass a value of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) as the result of the function of type \( {{\color {#0C80CF}{\mathbf {X \rightarrow Y}}}} \) and recover it from the argument to the function of type \( {{\color {#0C80CF}{\mathbf {Y \rightarrow X}}}} \). This would require that value to survive exiting and reentering the lexical scope of type variable \( {{\color {#0C80CF}{\mathbf {X}}}} \), and degeneracy expresses exactly the impossibility of this, i.e., \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) ’s respect for the lexical scope of type variables like \( {{\color {#0C80CF}{\mathbf {X}}}} \).

Note that in this paper, lexical scoping of type variables in System F is regarded as an informal property. Our best attempt to characterize it uses the degeneracy of \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) and the existence of a universal type as a sufficient criterion.

3.1 Two Contextually Equivalent Terms

This degeneracy of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) implies the contextual equivalence of the following two terms of type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \mathbf {{\color {#0C80CF}{\rightarrow }}} {Unit} }}}} \). \( \begin{*} {{\color {#0C80CF}{\mathbf {t_u }}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf { \begin{aligned} &\mathbf {{\color {#0C80CF}{\lambda }}} {{\color {#0C80CF}{\mathbf {x : {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}\ldotp {{\color {#0C80CF}{\mathbf {unpack}}}}~{{\color {#0C80CF}{\mathbf {x}}}}~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle {{\color {#0C80CF}{\mathbf {Y,x^{\prime }}}}} \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ &{{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})}}}}={{\color {#0C80CF}{\mathbf { x^{\prime }~{Unit} }}}}~{{\color {#0C80CF}{\mathbf {in}}}}~{{\color {#0C80CF}{\mathbf { x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}} \end{aligned}}}}} \\ {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x : {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \ldotp \mathbf {{\color {#0C80CF}{\omega }}} _{Unit} }}}} \end{align*} \) The reason that \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) are contextually equivalent is that both will diverge when applied to any argument of type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \). For \( {{\color {#0C80CF}{\mathbf {t_u }}}} \), this follows from the degeneracy of the type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \), as we demonstrate below, while for \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \), the term \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\omega }}} _{Unit} }}}} \) in the body ensures divergence. Note that the degeneracy of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) is essential: if the context were able to produce a non-degenerate value of type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \), then \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) would not diverge when applied to it, so that the context could distinguish \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) from \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \).

Thus, we have the following theorem:

Theorem 3.1

(tuandtωare Contextually Equivalent in λF)

\( {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {t_u }}}} \mathrel {{{\color {#0C80CF}{\mathbf {\mathrel {\simeq }}}}}}{{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} : {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \rightarrow {Unit} }}}} \).

Note that we have chosen \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) because their equivalence is relatively easy to prove. However, we could have taken many other equivalences which follow from the degeneracy of \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) and particularly, we could have taken example terms which will both terminate with different results in the presence of a non-degenerate universal type: \( \begin{*} {{\color {#0C80CF}{\mathbf {t_1}}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf { \begin{aligned} &\mathbf {{\color {#0C80CF}{\lambda }}} {{\color {#0C80CF}{\mathbf {x : {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}\ldotp {{\color {#0C80CF}{\mathbf {unpack}}}}~{{\color {#0C80CF}{\mathbf {x}}}}~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle {{\color {#0C80CF}{\mathbf {Y,x^{\prime }}}}} \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ &{{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})}}}}={{\color {#0C80CF}{\mathbf { x^{\prime }~{Unit} }}}}~{{\color {#0C80CF}{\mathbf {in}}}}~{{\color {#0C80CF}{\mathbf { x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}); 1}}}} \end{aligned}}}}} \\ {{\color {#0C80CF}{\mathbf {t_2}}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf { \begin{aligned} &\mathbf {{\color {#0C80CF}{\lambda }}} {{\color {#0C80CF}{\mathbf {x : {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}\ldotp {{\color {#0C80CF}{\mathbf {unpack}}}}~{{\color {#0C80CF}{\mathbf {x}}}}~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle {{\color {#0C80CF}{\mathbf {Y,x^{\prime }}}}} \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ &{{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})}}}}={{\color {#0C80CF}{\mathbf { x^{\prime }~{Unit} }}}}~{{\color {#0C80CF}{\mathbf {in}}}}~{{\color {#0C80CF}{\mathbf { x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}); 2}}}} \end{aligned}}}}} \end{align*} \)

3.2 Univ in Other Settings

Before we look at proving 3.1, it is useful to build a better intuition of the meaning and the cause of the degeneracy of \( {\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}} \). To this end, it is useful to consider the type’s properties in variants of System F.

For example, if we imagine a variant of System F with errors or exceptions, converting a function of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) to \( {{\color {#0C80CF}{\mathbf {Y}}}} \) and back, must no longer necessarily diverge, but can now also result in an error or an exception. Intuitively, this is perhaps still a form of degeneracy, but formally, it is no longer true that \( {{\color {#0C80CF}{\mathbf {t_u \mathrel {{{\color {#0C80CF}{\mathbf {\mathrel {\simeq }}}}}}t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) and thus, the two terms no longer form a counterexample to full abstraction. However, while the concrete counterexample is broken, the more general observation remains: System F implies properties about the type \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) that are no longer true in the languages we discuss in the next sections, even when both languages are extended with errors or exceptions. Concretely, we can easily adapt the counterexample by making \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) not always diverge, but diverge after invoking the two functions of the \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) value. \( \begin{*} {{\color {#0C80CF}{\mathbf {t_u }}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf { \begin{aligned} &\mathbf {{\color {#0C80CF}{\lambda }}} {{\color {#0C80CF}{\mathbf {x : {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}\ldotp {{\color {#0C80CF}{\mathbf {unpack}}}}~{{\color {#0C80CF}{\mathbf {x}}}}~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle {{\color {#0C80CF}{\mathbf {Y,x^{\prime }}}}} \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ &{{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})}}}}={{\color {#0C80CF}{\mathbf { x^{\prime }~{Unit} }}}}~{{\color {#0C80CF}{\mathbf {in}}}}~{{\color {#0C80CF}{\mathbf { x^{\prime \prime }.2~(x^{\prime \prime }.1~{{\color {#0C80CF}{\mathbf {{unit} }}}}) }}}} \end{aligned}}}}} \\ {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}}^{\prime }}}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf { \begin{aligned} &\mathbf {{\color {#0C80CF}{\lambda }}} {{\color {#0C80CF}{\mathbf {x : {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}\ldotp {{\color {#0C80CF}{\mathbf {unpack}}}}~{{\color {#0C80CF}{\mathbf {x}}}}~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle {{\color {#0C80CF}{\mathbf {Y,x^{\prime }}}}} \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ &{{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})}}}}={{\color {#0C80CF}{\mathbf { x^{\prime }~{Unit} }}}}~{{\color {#0C80CF}{\mathbf {in}}}}~{{\color {#0C80CF}{\mathbf { x^{\prime \prime }.2~(x^{\prime \prime }.1~{{\color {#0C80CF}{\mathbf {{unit} }}}}); \mathbf {{\color {#0C80CF}{\omega }}} _{{{\color {#0C80CF}{\mathbf {{Unit} }}}}} }}}} \end{aligned}}}}} \end{align*} \)

Our results should not be interpreted as strictly related to the specific example terms \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) and not even to the type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \). It appears clear at least that \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) is not the only type for which an RLR implies properties that do not follow from a TWLR (see Section 4). For example, it appears clear that similar properties will hold for a variant of \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) with one component duplicated: \( \begin{equation*} {{\color {#0C80CF}{\mathbf {\exists Y\ldotp \forall X \ldotp (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}} \end{equation*} \) Our modified example shows that the phenomenon also manifests itself in the presence of effects like errors and exceptions.

It is hard to identify a root cause for the phenomenon: some of the settings we consider feature a form of type generativity, all feature a universal type, but it is hard to say whether these are symptom or disease. The use of TWLRs suggests (at least to us) that it is essentially the lexical scoping of type variables in System F which is not enforced in the different settings we consider. However, as mentioned before, we don’t know how to formalize this intuitive property or argue that it is the root cause.

Extending System F with ML-like references breaks the counterexample in a seemingly more severe way. Concretely, consider extending System F in a standard way with types \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {Ref}}}}~\mathbf {{\color {#0C80CF}{\tau }}} }}}} \) for heap references and constructs for allocating (\( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {ref}}}}_\tau ~v}}}} \)), assigning (\( {{\color {#0C80CF}{\mathbf {x := v}}}} \)) and dereferencing (\( {{\color {#0C80CF}{\mathbf {!x}}}} \)) heap variables), see, e.g., Pierce [2002]. In this case, the type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) gains inhabitants like the following: \( \begin{*} {{\color {#0C80CF}{\mathbf {{pack}~\left\langle {Unit},\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp \begin{array}{l} {{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {r : Ref~(Maybe~ X)}}}} = {{\color {#0C80CF}{\mathbf {ref_X}}}}~ {{\color {#0C80CF}{\mathbf {None}}}} ~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ \left\langle {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x:X\ldotp r \mathbin {:=} {{\color {#0C80CF}{\mathbf {Some}}}}~ x; {{\color {#0C80CF}{\mathbf {{unit} }}}} }}}},{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} \_:{Unit} \ldotp !r}}}} \right\rangle \end{array} \right\rangle ~{as}~{{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}}}}} \end{align*} \) Rather than attempting to store values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) in an appropriately chosen \( {{\color {#0C80CF}{\mathbf {Y}}}} \) in some way, this inhabitant instantiates \( {{\color {#0C80CF}{\mathbf {Y}}}} \) to the non-informative type \( {{\color {#0C80CF}{\mathbf {{Unit} }}}} \). Instead, it allocates a mutable variable of type \( {{\color {#0C80CF}{\mathbf {X}}}} \), shared between the two functions. The first function then stores its argument in the heap variable for the second function to retrieve.

The existence of this inhabitant shows that ML references break our results as well and in this case, it is not as obvious how to recover equivalences that rely on lexical scoping of type variables. One might interpret this to mean that the degeneracy of \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) is an artifact of the purity of System F, and that it only holds in the absence of effects like mutable state. Perhaps what we call non-lexically-scoped type variables should simply be interpreted as impurity of polymorphic function applications and as such, not different from other effects?

We think it is not so simple and one way to see this is to consider what happens with the above example in a value-polymorphic language. Interestingly, value polymorphism breaks the \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) inhabitant mentioned above: it is no longer possible to allocate a reference cell that is shared by the functions from \( {{\color {#0C80CF}{\mathbf {X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y}}}} \) and \( {{\color {#0C80CF}{\mathbf {Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}} \). In fact, we expect degeneracy of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) to hold in value-polymorphic variants of System F, even in the presence of ML references or other effects.

Nevertheless, it will be clear in 567 that value polymorphism does not similarly break the inhabitants of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) we discuss there. TODO: add some notes about this in those sections This demonstrates that even if one interprets the non-lexical scope of type variables in those languages as a form of effect, it is at least a form of effect that behaves rather differently than other effects, as it does not disappear from polymorphic functions with the introduction of value-polymorphism. From that point of view, we think our results remain relevant in the presence of effects, although value polymorphism appears essential when those effects can be used to create a communication channel for transmitting values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) between the two functions in \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) (as discussed for ML references).

Skip 4PROVING DEGENERACY OF Univ Section

4 PROVING DEGENERACY OF Univ

This section attempts to prove 3.1 (the contextual equivalence of \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) which we recap below) using both the RLR and the TWLR and in doing so, it focusses on the key result for this proof: showing that \( {\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}} \) is degenerate. This result is doable with the RLR (from section 2.3), highlighting why they are incompatible with non-lexically-scoped type variables but the same fact cannot be shown with the TWLR (from section 2.5). \( \begin{*} {{\color {#0C80CF}{\mathbf {t_u }}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf { \begin{aligned} &\mathbf {{\color {#0C80CF}{\lambda }}} {{\color {#0C80CF}{\mathbf {x : {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}\ldotp {{\color {#0C80CF}{\mathbf {unpack}}}}~{{\color {#0C80CF}{\mathbf {x}}}}~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle {{\color {#0C80CF}{\mathbf {Y,x^{\prime }}}}} \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ &{{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})}}}}={{\color {#0C80CF}{\mathbf { x^{\prime }~{Unit} }}}}~{{\color {#0C80CF}{\mathbf {in}}}}~{{\color {#0C80CF}{\mathbf { x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}} \end{aligned}}}}} \\ {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x : {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \ldotp \mathbf {{\color {#0C80CF}{\omega }}} _{Unit} }}}} \end{align*} \)

The first step of the proof of 3.1 is captured by Lemma 4.1 (Diverging functions are contextually equivalent to an omega function), which states that a function that diverges for every argument is equivalent to a function whose body is the omega term.

Lemma 4.1 (Diverging Functions are Contextually Equivalent to an Omega Function).

\( \begin{*} \text{If } & {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}}\ldotp t}}}}:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }\mathbf {{\color {#0C80CF}{\rightarrow }}} {Unit} }}}} \text{ and } (\text{for all }{{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {v}}}}:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}} \text{ we have that } {{\color {#0C80CF}{\mathbf {(\mathbf {{\color {#0C80CF}{\lambda }}} x:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}}\ldotp t)~v}}}}{{\color {#0C80CF}{\mathbf {\Uparrow }}}}) \\ \text{Then } & {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}}\ldotp t}}}}\mathbf {{\color {#0C80CF}{\mathrel {\simeq }}}}{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}}\ldotp \mathbf {{\color {#0C80CF}{\omega }}} _{Unit} }}}}:{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime } \mathbf {{\color {#0C80CF}{\rightarrow }}} {Unit} }}}} \end{align*} \)

We do not think this lemma is very hard to believe. It can be proven using standard techniques, either using an ad hoc simulation argument or by relying on existing binary logical relations for System F, like the one by Dreyer et al. [2011a]. To avoid distracting from the main point of our paper, we do not offer a proof here.

With Lemma 4.1, it suffices to prove that \( {\color {#0C80CF}{\mathbf {t_u }}} \) always diverges when supplied with a value of type \( {\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}} \) in order to conclude 3.1. This result we derive from the “degeneracy” of \( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \), i.e., from the fact that \( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \) is only inhabited by diverging terms. We show this can be proven with the aid of the RLR in 4.2 below (Section 4.1) and also show that this is not provable with the TWLR (Section 4.2). We then discuss how this proof is carried out with other kinds of LR (Section 4.3).

4.1 Univ Degeneracy Using an RLR

Lemma 4.2

Univis Degenerate)

For all \( {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {v}}}}:{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \), we have that \( {{\color {#0C80CF}{\mathbf {t_u ~v}}}}{{\color {#0C80CF}{\mathbf {\Uparrow }}}} \).

Proof.

The proof proceeds largely in a standard way: we unfold the definition of value relation for the value of universal type and we rely on antireduction and compatibility lemmas in order to reason about terms after they evaluate. The goal is to show divergence of term \( {\color {#0C80CF}{\mathbf {t_u ~v}}} \). This can be achieved by showing that that term belongs to the term relation for a type variable whose set of inhabitants is empty. Specifically, we will prove that it belongs to \( {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\cdots ,{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {\emptyset }}}})}}}} \). By definition this means that the term must diverge or reduce to a value in \( {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\cdots ,{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {\emptyset }}}})}}}} \). Since that value relation is empty, the latter is not possible, so \( {{\color {#0C80CF}{\mathbf {t_u ~v}}}} \) must diverge.

To prove that \( {{\color {#0C80CF}{\mathbf {t_u ~v}}}} \) is in \( {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\cdots ,{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {\emptyset }}}})}}}} \), the main trick we use relies on having two relations for \( {\color {#0C80CF}{\mathbf {X}}} \) to inhabit. We will then instantiate the quantification over \( {\color {#0C80CF}{\mathbf {X}}} \) with two different semantic interpretations.

(1)

the first one \( {{\color {#0C80CF}{\mathbf {RU}}}} = {{\color {#0C80CF}{\mathbf {\lbrace {{\color {#0C80CF}{\mathbf {{unit} }}}} \rbrace }}}} \);

(2)

the second one \( {{\color {#0C80CF}{\mathbf {RE}}}} = {{\color {#0C80CF}{\mathbf {\emptyset }}}} \).

Now take \( {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {v}}}}:{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \). By Theorem 2.5 (Fundamental property for RLR) with \( {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {v}}}}:{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \), we have (HLR)10 \( {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \Vdash {{\color {#0C80CF}{\mathbf {v}}}}:{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \). By Definition 2.4 (Reynolds-style Logical Relation) with HLR (taking \( \mathbf {{\color {#0C80CF}{\rho }}} = \emptyset \) and \( \mathbf {{\color {#0C80CF}{\gamma }}} =\emptyset \)), we have \( {{\color {#0C80CF}{\mathbf {v}}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}{]\!]} ^{\emptyset }}}} \). Because \( {{\color {#0C80CF}{\mathbf {v}}}} \) is a value, we have \( {{\color {#0C80CF}{\mathbf {v}}}} \in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}}{]\!]} ^{\emptyset }}}} \).

By unfolding the definition of \( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \) and the value relation of the related type(s), it follows for some \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}} \), \( {{\color {#0C80CF}{\mathbf {v^{\prime }}}}} \) and \( {{\color {#0C80CF}{\mathbf {R_Y}}}} \in {{{\color {black}{\mathtt {Rel}\left({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}}\right)}}}} \), that

  • \( {{\color {#0C80CF}{\mathbf {v}}}} = {{\color {#0C80CF}{\mathbf {{pack}~\left\langle {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},v^{\prime } \right\rangle ~{as}~{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \)

  • (HPVP) \( {{\color {#0C80CF}{\mathbf {v^{\prime }}}}} \in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\forall X \ldotp (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}}}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}})}}}} \).

Let us now consider the reductions of \( {{\color {#0C80CF}{\mathbf {t_u ~v}}}} \): \( \begin{*} &\ {{\color {#0C80CF}{\mathbf {t_u ~v}}}} \\ \equiv &\ {{\color {#0C80CF}{\mathbf { \left| \begin{array}{l} (\mathbf {{\color {#0C80CF}{\lambda }}} x:{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \ldotp {{\color {#0C80CF}{\mathbf {unpack}}}}~x~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle {{\color {#0C80CF}{\mathbf {Y,x^{\prime }}}}} \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ \ {{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})}}}}={{\color {#0C80CF}{\mathbf { x^{\prime }~{Unit} }}}}~{{\color {#0C80CF}{\mathbf {in}}}}~\\ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}})~ {{\color {#0C80CF}{\mathbf {v}}}} \end{array} \right. }}}} \\ {{\color {#0C80CF}{\mathbf {\hookrightarrow }}}}&\ {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {unpack}}}}~v~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle Y,x^{\prime } \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~ {{\color {#0C80CF}{\mathbf {let}}}}~ x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})= x^{\prime }~{Unit} ~{{\color {#0C80CF}{\mathbf {in}}}}~ x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}} \\ \equiv &\ {{\color {#0C80CF}{\mathbf { \left| \begin{array}{l} {{\color {#0C80CF}{\mathbf {unpack}}}}~{{\color {#0C80CF}{\mathbf {({pack}~\left\langle \mathbf {{\color {#0C80CF}{\tau }}} _Y,v^{\prime } \right\rangle ~{as}~{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}})}}}}~{{\color {#0C80CF}{\mathbf {as}}}}~\left\langle {{\color {#0C80CF}{\mathbf {Y,x^{\prime }}}}} \right\rangle ~{{\color {#0C80CF}{\mathbf {in}}}}~\\ {{\color {#0C80CF}{\mathbf {let}}}}~ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }:({Unit} \rightarrow Y)\times (Y\rightarrow {Unit})}}}}={{\color {#0C80CF}{\mathbf { x^{\prime }~{Unit} }}}}~{{\color {#0C80CF}{\mathbf {in}}}}~ \\ {{\color {#0C80CF}{\mathbf {x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}} \end{array} \right. }}}} \\ {{\color {#0C80CF}{\mathbf {\hookrightarrow }}}}&\ {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {let}}}}~ x^{\prime \prime }:({Unit} \rightarrow \mathbf {{\color {#0C80CF}{\tau }}} _Y)\times (\mathbf {{\color {#0C80CF}{\tau }}} _Y\rightarrow {Unit})= v^{\prime }~{Unit} ~{{\color {#0C80CF}{\mathbf {in}}}}~ x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}} \end{align*} \) By Lemma 2.6 (Antireduction) and Lemma 2.9 (Boring lemma), to conclude our thesis (\( {{\color {#0C80CF}{\mathbf {t_u ~v}}}}\in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\emptyset , {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \)) it is sufficient to show that: \( \begin{*} & {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {let}}}}~ x^{\prime \prime }:({Unit} \rightarrow \mathbf {{\color {#0C80CF}{\tau }}} _Y)\times (\mathbf {{\color {#0C80CF}{\tau }}} _Y\rightarrow {Unit})= v^{\prime }~{Unit} ~{{\color {#0C80CF}{\mathbf {in}}}}~ x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}), {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \end{align*} \)

Now assume that the term \( \begin{equation*} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {let}}}}~ x^{\prime \prime }:({Unit} \rightarrow \mathbf {{\color {#0C80CF}{\tau }}} _Y)\times (\mathbf {{\color {#0C80CF}{\tau }}} _Y\rightarrow {Unit})= v^{\prime }~{Unit} ~{{\color {#0C80CF}{\mathbf {in}}}}~ x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}} } \) terminates to a value \( {{\color {#0C80CF}{\mathbf {v_r}}}} \). By definition of the term relation, it suffices to prove that \( \begin{equation*} {{\color {#0C80CF}{\mathbf {v_r}}}} \in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}), {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} } \) It is easy to see that there must be an intermediate value \( {{\color {#0C80CF}{\mathbf {v_U}}}} \) such that \( {{\color {#0C80CF}{\mathbf {v^{\prime }~{Unit} }}}} \mathrel {{{\color {#0C80CF}{\mathbf {\hookrightarrow ^*}}}}}{{\color {#0C80CF}{\mathbf {v_U}}}} \) and \( \begin{*} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {let}}}}~ x^{\prime \prime }:({Unit} \rightarrow \mathbf {{\color {#0C80CF}{\tau }}} _Y)\times (\mathbf {{\color {#0C80CF}{\tau }}} _Y\rightarrow {Unit})= v_U~{{\color {#0C80CF}{\mathbf {in}}}}~ x^{\prime \prime }.2~(x^{\prime \prime }.1~{unit}) }}}} \mathrel {{{\color {#0C80CF}{\mathbf {\hookrightarrow ^*}}}}}{{\color {#0C80CF}{\mathbf {v_r}}}} \end{align*} \)

From HPVP, we know that \( \begin{*} {{\color {#0C80CF}{\mathbf { v^{\prime }~{{\color {#0C80CF}{\mathbf {{Unit} }}}} }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y \times Y\mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}), {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \end{align*} \) By definition of the term relation, we have that (HPVU) \( {{\color {#0C80CF}{\mathbf {v_U}}}} \in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y \times Y\mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}), {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \). It will be useful later that the same property holds if we replace \( {{\color {#0C80CF}{\mathbf {RE}}}} \) with \( {{\color {#0C80CF}{\mathbf {RU}}}} \) (HPVU2).

By definition of the term relation, it suffices to prove that \( \begin{*} {{\color {#0C80CF}{\mathbf { v_U.2~(v_U.1~{unit}) }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}), {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \end{align*} \) This is a top-level application, so by Lemma 2.8 (Compatibility for applications), it suffices to prove the following (recall that \( {{\color {#0C80CF}{\mathbf {RE}}}}={{\color {#0C80CF}{\mathbf {\emptyset }}}} \)):

(1)

\( {{\color {#0C80CF}{\mathbf { v_U.2 }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y\mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}), {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \)

(2)

\( {{\color {#0C80CF}{\mathbf { v_U.1~{unit} }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}), {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \)

The former follows easily from HPVU by unfolding the definition of the value relation for pairs.

To prove 2 we apply our main trick. By Lemma 2.9 (Boring lemma), we can replace the relation with an equivalent one. We first drop the first relation for \( {\color {#0C80CF}{\mathbf {X}}} \) in the term relation for \( {\color {#0C80CF}{\mathbf {Y}}} \) (since variable \( {\color {#0C80CF}{\mathbf {X}}} \) is not mentioned in type \( {\color {#0C80CF}{\mathbf {Y}}} \)), then add the second relation and all the term relations are equivalent: \( \begin{*} {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} = {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}})}}}} = {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RU}}}})}}}} \end{align*} \) So instead of proving: \( \begin{*} {{\color {#0C80CF}{\mathbf {v_U.1~{unit} }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \end{align*} \) we can just prove (notice the change in the semantic interpretation for \( {\color {#0C80CF}{\mathbf {X}}} \)): \( \begin{*} {{\color {#0C80CF}{\mathbf {v_U.1~{unit} }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RU}}}})}}}} \end{align*} \) This is necessary in order to reason about the function application within this term, as we explain below.

Again, we apply Lemma 2.8 (Compatibility for applications) and it suffices to prove the following:

(3)

\( {{\color {#0C80CF}{\mathbf {v_U.1}}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {X\mathbf {{\color {#0C80CF}{\rightarrow }}} Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RU}}}})}}}} \)

(4)

\( {{\color {#0C80CF}{\mathbf {{unit} }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RU}}}})}}}} \)

Similarly to how we derived HPVU from HPVP and the definition of the term relation, 3 follows from the fact that \( {{\color {#0C80CF}{\mathbf {v_U}}}} \in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y \times Y\mathbf {{\color {#0C80CF}{\rightarrow }}} X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}), {{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RU}}}})}}}} \) (HPVU2) and then unfolding the definition of the value relation for pairs.

Proving 4 is not hard either. The term relation includes the value relation, so it suffices to prove: \( \begin{*} & {{\color {#0C80CF}{\mathbf {{unit} }}}} \in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RU}}}})}}}} \end{align*} \) By definition of the value relation for type variables, this holds if \( {\color {#0C80CF}{\mathbf {{unit} }}} \) inhabits the semantic interpretation for \( {\color {#0C80CF}{\mathbf {X}}} \), i.e., \( {{\color {#0C80CF}{\mathbf {RU}}}} =\lbrace {{\color {#0C80CF}{\mathbf {{unit} }}}}\rbrace \).□

If we had not performed our main trick, all other proof obligations would hold, but proving 4 would not be possible. In fact, there we would have had to prove that: \( \begin{*} & {{\color {#0C80CF}{\mathbf {{unit} }}}} \in {{\color {black}{\mathcal {V}{[\![} {{\color {#0C80CF}{\mathbf {X}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \end{align*} \) i.e., (according to the value relation for type variables) that \( {\color {#0C80CF}{\mathbf {{unit} }}} \) is in the current semantic interpretation for \( {\color {#0C80CF}{\mathbf {X}}} \), i.e., \( {\color {#0C80CF}{\mathbf {\emptyset }}} \), which is not possible.□

4.2 Why Universal Types Require Type Worlds

The proof from Section 3.1 shows that Reynolds-style or lexically-scoped logical relations are incompatible with a universal type. But to thoroughly understand what is going on, it is useful to take a closer look at the counterexample.

Recall the definition of the type \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \). \( \begin{*} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf {\exists Y\ldotp \forall X \ldotp (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}} \end{align*} \) According to the RLR, any value of this type is of the form \( {{\color {#0C80CF}{\mathbf {{pack}~\left\langle \mathbf {{\color {#0C80CF}{\mathbf {{\color {#0C80CF}{\tau }}} _Y}}},v \right\rangle ~{as}~{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) and comes with a predicate \( {{\color {#0C80CF}{\mathbf {R_Y}}}} \in {{{\color {black}{\mathtt {Rel}\left({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}}\right)}}}} \), i.e., a predicate on values of type \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}} \). Importantly, this predicate needs to be chosen independently of choices that are made later, particularly the choice of the type \( {{\color {#0C80CF}{\mathbf {{Unit} }}}} \) for \( {{\color {#0C80CF}{\mathbf {X}}}} \) and the predicate \( {{\color {#0C80CF}{\mathbf {R_X}}}} \in {{{\color {black}{\mathtt {Rel}\left({{\color {#0C80CF}{\mathbf {{Unit} }}}}\right)}}}} \) which the universal quantification will be instantiated with.

It is this independence (of the choice of \( {{\color {#0C80CF}{\mathbf {R_Y}}}} \)) that is fundamentally incompatible with the existence of a universal type. Imagine there were a universal type \( {{\color {#0C80CF}{\mathbf {U}}}} \) in System F with total injection and extraction functions \( {{\color {#0C80CF}{\mathbf {{in}_Z}}}} : {{\color {#0C80CF}{\mathbf {Z \rightarrow U}}}} \) and \( {{\color {#0C80CF}{\mathbf {{out}_Z}}}} : {{\color {#0C80CF}{\mathbf {U \rightarrow Z}}}} \) for arbitrary types \( {{\color {#0C80CF}{\mathbf {Z}}}} \). Then we could define a value of type \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) by taking \( {{\color {#0C80CF}{\mathbf {Y = U}}}} \) and constructing a pair with \( {{\color {#0C80CF}{\mathbf {{in}_X}}}} \) and \( {{\color {#0C80CF}{\mathbf {{out}_X}}}} \): \( \begin{*} {{\color {#0C80CF}{\mathbf {{pack}~\left\langle U, \mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp \left\langle {in}_X, {out}_X \right\rangle \right\rangle ~{as}~{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \end{align*} \) Now, to make a choice for the predicate \( {{\color {#0C80CF}{\mathbf {R_U}}}} \), one thing to decide is whether or not the predicate should accept the result of \( {{\color {#0C80CF}{\mathbf {{in}_X~{unit} }}}} \) when \( {{\color {#0C80CF}{\mathbf {X}}}} \) is later instantiated to \( {{\color {#0C80CF}{\mathbf {{Unit} }}}} \) (as in the counterexample). However, whether or not this value can be legally embedded in \( {{\color {#0C80CF}{\mathbf {U}}}} \) fundamentally depends on the choice for \( {{\color {#0C80CF}{\mathbf {R_X}}}} \in {{{\color {black}{\mathtt {Rel}\left({{\color {#0C80CF}{\mathbf {{Unit} }}}}\right)}}}} \). Particularly, if \( {{\color {#0C80CF}{\mathbf {R_X}}}} = {{\color {#0C80CF}{\mathbf {\emptyset }}}} \), then it should be rejected, but if \( {{\color {#0C80CF}{\mathbf {R_X}}}} = \lbrace {{\color {#0C80CF}{\mathbf {{unit} }}}}\rbrace \) then it should be accepted. Clearly, this is impossible if we need to choose \( {{\color {#0C80CF}{\mathbf {R_Y}}}} \) before we know what \( {{\color {#0C80CF}{\mathbf {R_X}}}} \) will be instantiated with.

So how do type-worlds fit into this picture? In a TWLR like that of section 2.5, we still need to make a choice for before a choice is made for . However, the type of is different now: with

Another way to think of this set is as : the set of monotone functions from \( {{\color {#0C80CF}{\mathbf {World}}}} \) to sets of values. In other words, is now a family of relations, and can decide which values to accept based on the current type world . This world will contain choices of predicates for other type variables, particularly the choice for . In each of the TWLRs where a universal type is at play, the logical relation will accept different values depending on the world , thus solving the conundrum outlined above.

It is also interesting to consider what this means in practice, when proving theorems using a formulation of parametricity. Many proofs go through with TWLRs as they do with RLRs, as demonstrated, for example, by Ahmed et al. [2017]. However, this is not the case for all proofs and Lemma 4.2 (\( {\color {#0C80CF}{\mathbf {\underline{Univ}}}} \) is degenerate) from section 3.1 is a perfect example. To see this, let us try to adapt the proof to use the TWLR from section 2.5 instead of the RLR from section 2.3, and see where this fails. Interestingly, the place we get stuck is at the application of Lemma 2.9 (Boring lemma), suggesting the theorem is not as boring as the name suggests.

When we look at how Lemma 2.9 (Boring lemma) was applied in the proof of 4.2, we see that we were able to prove the following: \( \begin{*} {{\color {#0C80CF}{\mathbf {v_U.1~{unit} }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RU}}}})}}}} \end{align*} \) Then, we used Lemma 2.9 (Boring lemma) twice, the first time to forget a binding for \( {\color {#0C80CF}{\mathbf {X}}} \), and the second time to add a different binding for the same \( {\color {#0C80CF}{\mathbf {X}}} \): \( \begin{*} {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RU}}}})}}}} = {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}})}}}} = {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \end{align*} \) We could then conclude that \( \begin{*} {{\color {#0C80CF}{\mathbf {v_U.1~{unit} }}}} \in {{\color {black}{\mathcal {E}{[\![} {{\color {#0C80CF}{\mathbf {Y}}}}{]\!]} ^{\emptyset ,{{\color {#0C80CF}{\mathbf {Y}}}} \mapsto ({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} _Y}}}},{{\color {#0C80CF}{\mathbf {R_Y}}}}),{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({{\color {#0C80CF}{\mathbf {{Unit} }}}},{{\color {#0C80CF}{\mathbf {RE}}}})}}}} \end{align*} \)

With the TWLR, these applications of the lemma cannot be replicated. Consider the following worlds:

Clearly, (HPNF).

We can replicate the first steps of the proof until we have the following relation:

but the step to no longer holds:
We cannot use Lemma 2.13 (Boring lemma for TWLR) because of (HPNF).

In other words, the use of a TWLR means that different terms may be valid at type \( {{\color {#0C80CF}{\mathbf {Y}}}} \) in world than in . This dependence of the relation for \( {{\color {#0C80CF}{\mathbf {Y}}}} \) on the world is precisely what a TWLR purposefully allows. As a result, it is impossible to transfer the result about \( {{\color {#0C80CF}{\mathbf {v^{\prime }~\mathbf {{\color {#0C80CF}{\left[{{\color {#0C80CF}{\mathbf {{Unit} }}}} \right]}}}}}}} \) from the world (with the permissive predicate for \( {{\color {#0C80CF}{\mathbf {X}}}} \)) to the world (with the more restrictive predicate for \( {{\color {#0C80CF}{\mathbf {X}}}} \)).

4.3 Degeneracy and Other Variants of Logical Relations

If we consider the other variants of the logical relation discussed in section 2.4, our expectations are essentially confirmed. We have seen in section 3.2 that the degeneracy of \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \) does not hold in the presence of higher-order effects and indeed, the above proof fails if we use the Kripke logical relation from section 2.4, for a similar reason as for the TWLR.

For some , we would be able to obtain the following two facts:

Combined with \( {{\color {#0C80CF}{\mathbf {v^{\prime }~{Unit} }}}} \mathrel {{{\color {#0C80CF}{\mathbf {\hookrightarrow ^*}}}}}{{\color {#0C80CF}{\mathbf {v_U}}}} \), this gives us some , for which
From the second expression relation above, we also get a such that
However, these two worlds and are potentially distinct and one is not (necessarily) a future world of the other, which will later prevent us from combining both facts later in the proof.

In section 3.2, we have also seen that the value-polymorphic version of the same calculus with higher-order state should preserve degeneracy of \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \). And indeed, using the value-polymorphic KLR, we can proceed differently and deduce that \( {{\color {#0C80CF}{\mathbf {v^{\prime }}}}} = {{\color {#0C80CF}{\mathbf {\Lambda X\ldotp v^{\prime \prime }}}}} \) and

In other words, value polymorphism gives us these two facts immediately in the same world and as a result, contrary to above, we can combine them in the remainder of the proof.

Thus, the different logical relation variants that we have discussed in section 2 either prevent or allow the proof of degeneracy of \( {{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} \), as appropriate for the language variant they are intended for. In addition to confirming our analysis of the universal type in section 3, this also provides more insight into how the different logical relation variants influence the particular proof techniques used in the proof outlined here.

In addition to clarifying the relation between TWLRs and non-lexically-scoped type variables, this paper also discusses some consequences that follow from these insights. Particularly, the example from section 3.1 can be used to disprove two open conjectures and expose a previously unmentioned deficiency of polymorphic blame calculi. In the next three sections, we discuss these three topics in turn, starting with the secure compilation of System F in the cryptographic \( \lambda \)-calculus, a conjecture by Sumii and Pierce [2004]; Pierce and Sumii [2000].

Skip 5ENFORCING PARAMETRICITY IN AN UNTYPED TARGET LANGUAGE Section

5 ENFORCING PARAMETRICITY IN AN UNTYPED TARGET LANGUAGE

Sumii and Pierce’s conjecture is about a compiler from \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) to an untyped lambda calculus with sealing (idealised encryption) called \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \). In this section, we first introduce the target language \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) (Section 5.1) and the compiler from \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) to \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) (Section 5.2). We then prove that the compiler is not fully-abstract: there exist two terms that are contextually-equivalent in \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) but whose compilation is inequivalent in \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) (Section 5.3).

Remark. Sumii and Pierce have presented both a typed [Pierce and Sumii 2000] as well as an untyped [Sumii and Pierce 2004] version of \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \). We use the untyped version because it is quite a bit simpler.11 However, the typed version suffers from the same problem, as we show in detail in the technical report. Essentially, both settings break degeneracy of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) because they feature a universal type: the unitype of all values in the untyped target language and the type \( {\color {#EF257F}{\mathsf {bits}}} \) of ciphertexts produced by encryption (sealing) in the typed target language.

5.1 The Cryptographic Lambda Calculus λσ

\( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) (Figure 2) is an untyped \( \lambda \)-calculus, extended with sealing, which models a dynamic protection mechanism such as (idealized) symmetric encryption [Sumii and Pierce 2004].

Fig. 2.

Fig. 2. \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) syntax and evaluation rules (excerpts). A \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) program state is a pair \( {\color {#EF257F}{\mathsf {h;t}}} \) where \( {\color {#EF257F}{\mathsf {h}}} \) is the list of allocated seals. The semantics relation \( {\color {#EF257F}{\mathsf {\hookrightarrow }}} \) relies on the beta reductions indicated as \( {\color {#EF257F}{\mathsf {\hookrightarrow _0}}} \) , which do not require a list of allocated seals to reduce.

Most syntactic constructs are standard for an untyped \( \lambda \)-calculus. The term \( {\color {#EF257F}{\mathsf {wrong}}} \) models run-time errors and is a stuck term. Sealing introduces four new syntactic constructs in the calculus: \( {\color {#EF257F}{\mathsf {\nu x.t}}} \) creates a fresh seal (symmetric encryption key) and then evaluates \( {\color {#EF257F}{\mathsf {t}}} \) with \( {\color {#EF257F}{\mathsf {x}}} \) bound to the newly created seal. There is no surface syntax for seals, but the internal syntax \( {\color {#EF257F}{\mathsf {\sigma }}} \) represents run-time seal values created with \( {\color {#EF257F}{\mathsf {\nu x.t}}} \). The construct \( {\color {#EF257F}{\mathsf {\lbrace t_1\rbrace _{t_2}}}} \) first evaluates \( {\color {#EF257F}{\mathsf {t_1}}} \) and \( {\color {#EF257F}{\mathsf {t_2}}} \) to values \( {\color {#EF257F}{\mathsf {v_1}}} \) and \( {\color {#EF257F}{\mathsf {v_2}}} \) and then creates the sealed value \( {\color {#EF257F}{\mathsf {\lbrace v_1\rbrace _{v_2}}}} \) (or leads to a run-time error if \( {\color {#EF257F}{\mathsf {v_2}}} \) is not a seal). One can think of such a sealed value as \( {\color {#EF257F}{\mathsf {v_1}}} \) encrypted under \( {\color {#EF257F}{\mathsf {v_2}}} \). The final construct \( {\color {#EF257F}{\mathsf {\mathrm{let}~\lbrace x\rbrace _{t_1}~\mathrm{=}~t_2~\mathrm{in}~t_3~\mathrm{else}~t_4}}} \) is for unsealing or decrypting. It first evaluates \( {\color {#EF257F}{\mathsf {t_1}}} \) to a seal \( {\color {#EF257F}{\mathsf {\sigma _1}}} \) and \( {\color {#EF257F}{\mathsf {t_2}}} \) to \( {\color {#EF257F}{\mathsf {\lbrace v_2\rbrace _{\sigma _2}}}} \) (or produces a run-time error if either result is not of that form). If \( {\color {#EF257F}{\mathsf {\sigma _1}}} \) and \( {\color {#EF257F}{\mathsf {\sigma _2}}} \) are equal, \( {\color {#EF257F}{\mathsf {t_3}}} \) is evaluated with \( {\color {#EF257F}{\mathsf {x}}} \) bound to the decrypted value \( {\color {#EF257F}{\mathsf {v_2}}} \), otherwise \( {\color {#EF257F}{\mathsf {t_4}}} \) is evaluated.

Program contexts in \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) are defined as for \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) and are denoted with \( {\color {#EF257F}{\mathsf {{C}}}} \). Contextual equivalence in \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \), indicated with \( {\color {#EF257F}{\mathsf {\mathrel {\simeq }}}} \), is defined analogously to 2.1. Note that the quantified contexts are not allowed to contain literal seals (as they are internal syntax), but they are allowed to allocate and use fresh seals of their own.

Sealing is the main information hiding mechanism in \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \): by creating a new seal \( {\color {#EF257F}{\mathsf {\sigma }}} \) and making sure it does not leak to the context, a term can create values \( {\color {#EF257F}{\mathsf {\lbrace v\rbrace _{{\color {#EF257F}{\mathsf {\sigma }}}}}}} \) that are opaque to the context. Pierce and Sumii [2000] explain how one can use this information hiding mechanism to implement a protection similar to that offered by parametric polymorphism. For instance, the following implementation of \( \mathbb {Z}_3 \) from Example 2.2 in terms of pairs of Booleans, uses sealing to protect the abstraction.

Example 5.1

(Z3 in λσ)

First, we introduce two helper functions: \( \begin{*} {\color {#EF257F}{\mathsf {seal_\sigma }}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf {\lambda y\ldotp \lbrace y\rbrace _{\sigma }}}} & {\color {#EF257F}{\mathsf {unseal_\sigma }}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf {\lambda y\ldotp \mathrm{let}~\lbrace x\rbrace _{\sigma }~\mathrm{=}~y~\mathrm{in}~x~\mathrm{else}~ {\color {#EF257F}{\mathsf {wrong}}}}}} \end{align*} \) Then, we can define a \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) correspondent of \( {\color {#0C80CF}{\mathbf {z3}}} \) as: \( \begin{*} {\color {#EF257F}{\mathsf {z3}}} = &{\color {#EF257F}{\mathsf {\nu s. \left\langle \left\langle zero,succ \right\rangle ,zero? \right\rangle }}}\\ &\text{where} \left\lbrace \begin{aligned}{\color {#EF257F}{\mathsf {zero}}} &= {\color {#EF257F}{\mathsf {seal_s~ \left\langle {false},{false} \right\rangle }}} \\ {\color {#EF257F}{\mathsf {succ}}} &= {\color {#EF257F}{\mathsf { \lambda p\ldotp {if}~(unseal_s\ p).2~{then}~seal_s~ \left\langle {false},{false} \right\rangle ~{else}~ }}} \\ & \qquad \ \ \ {\color {#EF257F}{\mathsf {{if}~ (unseal_s\ p).1 ~{then}~ seal_s~ \left\langle {false},{true} \right\rangle ~{else}~ {\color {#EF257F}{\mathsf {seal_s~ \left\langle {true},{false} \right\rangle }}} }}} \\ {\color {#EF257F}{\mathsf {zero?}}} &= {\color {#EF257F}{\mathsf {\lambda p\ldotp {if}~ (unseal_s~ p).1 ~{then}~ {false} ~{else}~ {\color {#EF257F}{\mathsf {{if}~(unseal_s p).2~{then}~{false} ~{else}~{true} }}} }}} \end{aligned}\right. \end{align*} \)

Whenever values of the abstract type leave the scope of the abstract type definition, they are encrypted, and when they are passed back in they are decrypted before use. Intuitively, one can see that this protects against a context looking into or tampering with representation values, similarly to the protection offered by type checking of parametric polymorphism.

Also the protection required for the dual case, where a term calls a universally quantified function provided by the context, can be implemented in \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \). Consider for instance the \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) term: \( \begin{*} &{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} f: \forall X \ldotp X \mathbf {{\color {#0C80CF}{\times }}} X \rightarrow X\ldotp {{if}~f~Bool~\left\langle {true},{true} \right\rangle ~{then}~{true} ~{else}~{false}} }}}} \end{align*} \) The polymorphic function \( {{\color {#0C80CF}{\mathbf {f}}}} \) that will be passed in by the context, can only return one of its arguments (or diverge), and hence the invocation in the term above will necessarily return \( {{\color {#0C80CF}{\mathbf {{true} }}}} \) (or diverge).

We can implement a similar protection in \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \). To enforce parametric behaviour of a polymorphic function received from the context, we create a new seal for every invocation, and we encrypt all parameters of the quantified type with that seal. For instance, the term above could be implemented in \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) as follows: \( \begin{*} &{\color {#EF257F}{\mathsf {\lambda f\ldotp {if}~\nu s.unseal_s (f~\left\langle seal_s\ {true}, seal_s\ {true} \right\rangle)~{then}~{true} ~{else}~{false} }}} \end{align*} \) Before calling \( {\color {#EF257F}{\mathsf {f}}} \), its arguments are encrypted with a new seal, and the return value gets decrypted with that seal, hence all that \( {\color {#EF257F}{\mathsf {f}}} \) can do is either return one of its arguments or diverge (doing anything else would lead to a run-time error).

Again, this gives us a dynamic guarantee that a function has to treat its arguments opaquely, where parametric polymorphism gives us this guarantee statically by type checking. This technique of dynamically protecting values with appropriately scoped seals is the essence of the idea behind Sumii and Pierce’s compiler for \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \).

5.2 Sumii and Pierce’s Compiler

The compiler \( {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {\cdot }}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \) first performs standard type erasure (function \( {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {\cdot }}}}\right)}}}} \)) and then wraps it with a dynamic check (\( {\color {#EF257F}{\mathsf {protect}}}_{{{\color {black}{\eta }}};{{\color {#0C80CF}{\mathbf {\tau }}}}} \)) that will insert dynamic applications of sealing and unsealing: \( \begin{*} \mbox{if }{{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {t}}}}:\mathbf {{\color {#0C80CF}{\tau }}} , \mbox{ then } {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t}}}} }}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \mathrel {\overset{\text {def}}{=}}&\ {\color {#EF257F}{\mathsf {{let}~ x={{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {t}}}}\right)}}}} ~{in}~{\color {#EF257F}{\mathsf {protect}}}_{{{\color {black}{\emptyset }}};{{\color {#0C80CF}{\mathbf {\tau }}}}}~x }}} \end{align*} \) Note that we restrict the compiler to closed terms here. Lifting this limitation is quite straightforward, as presented by Devriese et al. [2017].

We now present these steps and discuss their meaning. These definitions are taken from Sumii and Pierce [2004], except that we make some notational changes and some minor technical changes.

Type erasure. This pass is mostly straightforward, the only non-trivial aspect is how to deal with the quantified types. Type abstraction and application are erased to a dummy lambda abstraction and an application to a \( {\color {#EF257F}{\mathsf {{unit} }}} \) parameter, and unpacking is erased to a \( {\color {#EF257F}{\mathsf {let}}} \)-binding.12 \( \begin{*} {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {x}}}}\right)}}}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf {x}}} & {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {t~\tau ^{\prime }}}}}\right)}}}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf { {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {t}}}}\right)}}}} ~{\color {#EF257F}{\mathsf {{unit} }}} }}} \\ {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp t}}}}\right)}}}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf {\lambda \_\ldotp {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {t}}}}\right)}}}} }}} & {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {{pack}~\left\langle {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}}^{\prime }}}}},{{\color {#0C80CF}{\mathbf {t}}}} \right\rangle ~{as}~{\mathbf {{\color {#0C80CF}{\exists }}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}}\right)}}}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf { {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {t}}}}\right)}}}} }}} \\ {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x:\mathbf {{\color {#0C80CF}{\tau }}} \ldotp t}}}}\right)}}}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf {\lambda x\ldotp {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {t}}}}\right)}}}} }}} & {{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {{unpack}~t~{as}~\left\langle X,x \right\rangle ~{in}~t^{\prime }}}}}\right)}}}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf {{let}~ x={{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {t}}}}\right)}}}} ~{in}~{{{\color {black}{\mathtt {erase}\left({{\color {#0C80CF}{\mathbf {t^{\prime }}}}}\right)}}}} }}} \end{align*} \)

Dynamic wrappers. The second phase of the compiler wraps compiled terms with dynamic wrappers. These are formalised as the function \( {\color {#EF257F}{\mathsf {protect}}}_{{{\color {black}{\eta }}};{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}} \), which is defined in Figure 3, together with its dual \( {\color {#EF257F}{\mathsf {confine}}}_{{{\color {black}{\eta }}};{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}} \) by mutual induction on \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}} \). We use the names \( {\color {#EF257F}{\mathsf {protect}}} \) and \( {\color {#EF257F}{\mathsf {confine}}} \) (following Devriese et al. [2016]) to refer to the wrappers that Sumii and Pierce call and , respectively [Sumii and Pierce 2004].

Fig. 3.

Fig. 3. The dynamic wrappers of Sumii and Pierce’s compiler.

Intuitively, applying \( {\color {#EF257F}{\mathsf {protect}}}_{{{\color {black}{\eta }}};{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}} \) to a value \( {\color {#EF257F}{\mathsf {v}}} \) ensures that \( {\color {#EF257F}{\mathsf {v}}} \) cannot be used in ways that are not allowed by type \( \mathbf {{\color {#0C80CF}{\tau }}} \). Dually, applying \( {\color {#EF257F}{\mathsf {confine}}}_{{{\color {black}{\eta }}};{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}} \) to a value \( {\color {#EF257F}{\mathsf {v}}} \) prevents \( {\color {#EF257F}{\mathsf {v}}} \) from behaving in a way that is not allowed by type \( \mathbf {{\color {#0C80CF}{\tau }}} \). For any free type variables \( {{\color {#0C80CF}{\mathbf {X}}}} \) in \( \mathbf {{\color {#0C80CF}{\tau }}} \), \( \eta \) tells us how to protect/confine values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \). Concretely, \( \eta ({{\color {#0C80CF}{\mathbf {X}}}}) = ({\color {#EF257F}{\mathsf {t_p}}},{\color {#EF257F}{\mathsf {t_c}}}) \) where \( {\color {#EF257F}{\mathsf {t_p}}} \) and \( {\color {#EF257F}{\mathsf {t_c}}} \) are untyped terms that should be applied to protect/confine (respectively) values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \). Formally, \( \eta \) has the following syntax: \( \eta ::=\emptyset \mid \eta ,{{\color {#0C80CF}{\mathbf {X}}}}\mapsto ({\color {#EF257F}{\mathsf {t}}},{\color {#EF257F}{\mathsf {t}}}) \).

For defining \( {\color {#EF257F}{\mathsf {protect}}}_{{{\color {black}{}}};{{\color {#0C80CF}{\mathbf {}}}}} \) and \( {\color {#EF257F}{\mathsf {confine}}}_{{{\color {black}{}}};{{\color {#0C80CF}{\mathbf {}}}}} \) we rely on the following \( {\color {#EF257F}{\mathsf {seal_\sigma }}} \) and \( {\color {#EF257F}{\mathsf {unseal_\sigma }}} \) functions, which seal and unseal values with a given seal \( {\color {#EF257F}{\mathsf {\sigma }}} \). \( \begin{*} {\color {#EF257F}{\mathsf {seal_\sigma }}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf {\lambda y\ldotp \lbrace y\rbrace _{\sigma }}}} & {\color {#EF257F}{\mathsf {unseal_\sigma }}} &\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf {\lambda y\ldotp \mathrm{let}~\lbrace x\rbrace _{\sigma }~\mathrm{=}~y~\mathrm{in}~x~\mathrm{else}~{\color {#EF257F}{\mathsf {wrong}}}}}} \end{align*} \)

Protecting at a function type confines the argument and protects the result with the same polarity, and similarly for confining at a function type. Confining at ground type inserts a dynamic check that the confined value is indeed of the expected type (\( {\color {#EF257F}{\mathsf {{unit} }}} \) or \( {\color {#EF257F}{\mathsf {{true} }}} \)/\( {\color {#EF257F}{\mathsf {{false} }}} \)). If any of these checks fail, the term reduces to \( {\color {#EF257F}{\mathsf {wrong}}} \). Protecting at a ground type does nothing, because there is no way for the context to use such values that is not allowed by the type.

Protecting at type \( {{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \) does nothing but forward the dummy \( {\color {#EF257F}{\mathsf {{unit} }}} \) application and recursively protect at type \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}} \). This is because there is nothing to protect: intuitively, the context cannot use a term of type \( {{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \) in a way that is not allowed by the type. Similarly, confining at an existential type \( {{\color {#0C80CF}{\mathbf {{\mathbf {{\color {#0C80CF}{\exists }}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \) just recurses over type \( \mathbf {{\color {#0C80CF}{\tau }}} \) without doing anything special for values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \), because there is intuitively no way for a value of type \( {{\color {#0C80CF}{\mathbf {{\mathbf {{\color {#0C80CF}{\exists }}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \) to behave that is not allowed by the type.

Finally, when protecting a term of type \( {\color {#0C80CF}{\mathbf {{\mathbf {{\color {#0C80CF}{\exists }}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}} \), we want to make sure that the context treats the type \( {{\color {#0C80CF}{\mathbf {X}}}} \) opaquely, so values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) are sealed (encrypted) with a fresh seal \( {\color {#EF257F}{\mathsf {\sigma }}} \). Similarly, confining at type \( {{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \) generates a fresh seal for every invocation to protect values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) with. This is the idea we have explained before in section 5.1.

Applying the compiler to \( {{\color {#0C80CF}{\mathbf {z3}}}} \) from 5.1 results in the \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) term \( {\color {#EF257F}{\mathsf {z3}}} \) from Example 2.2 (modulo some additional \( \beta \)-reductions).

5.3 Disproving the Sumii-Pierce Conjecture

Sumii and Pierce conjectured that their compiler \( {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {\cdot }}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \) is fully abstract. In other words, two \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) terms are contextually equivalent if and only if they are compiled to equivalent \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) terms.

Conjecture 5.2 (Sumii and Pierce).

\( {{\color {#0C80CF}{\mathbf {\emptyset }}}};{{\color {#0C80CF}{\mathbf {\emptyset }}}} \vdash {{\color {#0C80CF}{\mathbf {t_1}}}} \mathrel {{{\color {#0C80CF}{\mathbf {\mathrel {\simeq }}}}}}{{\color {#0C80CF}{\mathbf {t_2}}}} : \mathbf {{\color {#0C80CF}{\tau }}} \) if and only if \( {\color {#EF257F}{\mathsf {\emptyset }}} \vdash {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {t_1}}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} {\color {#EF257F}{\mathsf {\mathrel {\simeq }}}}{{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {t_2}}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \)

However, we can now prove that this conjecture is false. A counterexample is given by the terms \( {\color {#0C80CF}{\mathbf {t_u }}} \) and \( {\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}} \) which we proved contextually equivalent in 3.1. Compiling \( {\color {#0C80CF}{\mathbf {t_u }}} \) and \( {\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}} \) does not produce contextually equivalent \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) terms:

Theorem 5.3

(tuand tωare Not Equivalent after Compilation to λσ)

Proof Sketch. A full proof with all details can be found in the supplementary material.

The terms \( {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_u }}}}}}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \) and \( {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}}}}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \) can be discriminated by the following context: \( \begin{*} {\color {#EF257F}{\mathsf {{C}}}}&\mathrel {\overset{\text {def}}{=}}{\color {#EF257F}{\mathsf { [\cdot ]~(\lambda \_\ldotp \left\langle \lambda x\ldotp x,\lambda x\ldotp x \right\rangle) }}} \end{align*} \) To understand the role of this context, recall that the contextual equivalence of \( {{\color {#0C80CF}{\mathbf {t_u}}}} \) and \( {{\color {#0C80CF}{\mathbf {t_d}}}} \) relies on the degeneracy of type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \). The context \( {\color {#EF257F}{\mathsf {{C}}}} \) breaks this assumption by invoking the terms with a non-degenerate value of type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \), which is constructed by using the unitype of all untyped values as a universal type.

By unfolding definitions and executing the operational semantics, it is easy to check that we get the following behaviour. \( \begin{*} {\color {#EF257F}{\mathsf {{C}}}}{\color {#EF257F}{\mathsf {\left[ {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_u }}}}}}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \right]}}} &\mathrel {{\color {#EF257F}{\mathsf {\hookrightarrow ^*}}}}{\color {#EF257F}{\mathsf {{unit} }}} & {\color {#EF257F}{\mathsf {{C}}}}{\color {#EF257F}{\mathsf {\left[ {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}}}}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \right]}}} &\mathrel {{\color {#EF257F}{\mathsf {\hookrightarrow ^*}}}}{\color {#EF257F}{\mathsf {(\lambda r\ldotp r)~\omega }}} \mathrel {{\color {#EF257F}{\mathsf {\hookrightarrow ^*}}}}{\color {#EF257F}{\mathsf {(\lambda r\ldotp r)~\omega }}} \mathrel {{\color {#EF257F}{\mathsf {\hookrightarrow ^*}}}}{\color {#EF257F}{\mathsf {\cdots }}}\ {\color {#EF257F}{\mathsf {\Uparrow }}} \end{align*} \) We spell out the reductions in full detail in the supplementary material. From this behaviour, it follows immediately that the terms are not contextually equivalent.□

We can thus prove that Sumii and Pierce’s conjecture is false as follows.

Theorem 5.4

([*]λFλσis Not Fully Abstract)

It is not true that \( \begin{*} \forall {{\color {#0C80CF}{\mathbf {t_1}}}},{{\color {#0C80CF}{\mathbf {t_2}}}}. {{\color {#0C80CF}{\mathbf {t_1}}}}\mathrel {{{\color {#0C80CF}{\mathbf {\mathrel {\simeq }}}}}}{{\color {#0C80CF}{\mathbf {t_2}}}} \iff {{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_1}}}}}}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}}{\color {#EF257F}{\mathsf {\mathrel {\simeq }}}}{{\color {black}{{[\![} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_2}}}}}}}} {]\!]} }}}^{{{\color {black}{{{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}}}}}}_{{{\color {black}{{{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}}}}}} \end{align*} \)

Proof.

Follows easily from 3.1 and the counterexample in 5.3.□

The problem is in the easy case. It is worth noticing that most of the work in Sumii and Pierce’s compiler (see Figure 3) is in enforcing that existentially quantified types passed to the context are treated opaquely and, dually, that polymorphic functions received from the context are forced to treat their argument type opaquely. However, it is not in these cases that the counterexample highlights a problem.

Instead, it goes wrong in the cases where we receive an existential type from the context (and dually when we pass a polymorphic function to the context). For these seemingly simple cases, the dynamic wrappers from Figure 3 do not perform any specific kind of enforcement (except for recursing on their body type). However, it is there that our counterexample uncovers a problem: the value that it provides as a value of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} = {{\color {#0C80CF}{\mathbf {\exists Y\ldotp \forall X \ldotp (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}} \) does not correspond to any legal choice of \( {{\color {#0C80CF}{\mathbf {Y}}}} \), but the dynamic type wrappers have no way to detect this. In fact, an alternative way to understand what goes wrong is that the value \( {\color {#EF257F}{\mathsf {\lambda \_\ldotp \left\langle \lambda x\ldotp x,\lambda x\ldotp x \right\rangle }}} \) provided by the context, behaves as if it can choose \( {{\color {#0C80CF}{\mathbf {Y}}}} \) equal to \( {{\color {#0C80CF}{\mathbf {X}}}} \). However, this is not possible in \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) because \( {{\color {#0C80CF}{\mathbf {X}}}} \) is not in scope at the moment when \( {{\color {#0C80CF}{\mathbf {Y}}}} \) needs to be chosen.

In other words, what seems to be missing in Sumii and Pierce’s dynamic enforcement is an enforcement of the type variable scope of existentially quantified types. To see this, consider the following type \( {{\color {#0C80CF}{\mathbf {\underline{Triv}}}}} \), which is identical to \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \), except for the order of the quantifiers: \( \begin{*} {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf {\exists Y\ldotp \forall X \ldotp (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}} & {{\color {#0C80CF}{\mathbf {\underline{Triv}}}}} &\mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf {\forall X \ldotp \exists Y\ldotp (X \mathbf {{\color {#0C80CF}{\rightarrow }}} Y) \mathbf {{\color {#0C80CF}{\times }}} (Y \mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}} \end{align*} \) Even though the type \( {{\color {#0C80CF}{\mathbf {\underline{Triv}}}}} \) is more liberal, as it allows to instantiate \( {{\color {#0C80CF}{\mathbf {Y}}}} \) with \( {{\color {#0C80CF}{\mathbf {X}}}} \), the wrappers of Figure 3 treat the types essentially the same. From this perspective, it is no surprise that the value \( {\color {#EF257F}{\mathsf {\lambda \_\ldotp \left\langle \lambda x\ldotp x,\lambda x\ldotp x \right\rangle }}} \) is accepted as a value of type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \), because it does in fact correspond to a legal \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) value of type \( {{\color {#0C80CF}{\mathbf {\underline{Triv}}}}} \): \( \begin{*} {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp {pack}~\left\langle X,\left\langle \mathbf {{\color {#0C80CF}{\lambda }}} x:X\ldotp x,\mathbf {{\color {#0C80CF}{\lambda }}} x:X\ldotp x \right\rangle \right\rangle ~{as}~\exists Y\ldotp (X\mathbf {{\color {#0C80CF}{\rightarrow }}} Y)\mathbf {{\color {#0C80CF}{\times }}} (Y\mathbf {{\color {#0C80CF}{\rightarrow }}} X)}}}} \end{align*} \)

Skip 6ENFORCING PARAMETRICITY IN THE PRESENCE OF TYPE CASTS Section

6 ENFORCING PARAMETRICITY IN THE PRESENCE OF TYPE CASTS

The second conjecture we disprove is by Neis et al. [2009]; , 2011]. These authors study a form of runtime type generation to protect parametrically polymorphic functions when interacting with code that can use a type cast primitive. They prove a parametricity result that applies to appropriately wrapped System F values once embedded in \( {\color {#41A9A6}{\mathtt {G}}} \), a language with a type cast primitive. They conjecture [Neis et al. 2009, Section 10] that this wrapping is fully abstract, and while they prove equivalence reflection, they only conjecture equivalence preservation due to a lack of sophistication of the proof techniques available at the time. 13

It turns out that our results may be adapted to this setting, as in such a non-parametrically polymorphic setting, the type \( {\color {#41A9A6}{\mathtt {\forall X\ldotp X}}} \) can be used as a universal type (that every other type can be embedded into or out from). In other words, we disprove this conjecture too: embedding System F into \( {\color {#41A9A6}{\mathtt {G}}} \) à la Neis-Dreyer-Rossberg (NDR, in the sequel) is not fully abstract.

We first present \( {\color {#41A9A6}{\mathtt {G}}} \) (Section 6.1) and the wrapper for protecting polymorphic functions from interacting with \( {\color {#41A9A6}{\mathtt {G}}} \) terms (Section 6.2). Then we demonstrate how \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \) is a universal type in \( {\color {#41A9A6}{\mathtt {G}}} \) (Section 6.3) and prove that due to that type, the wrapper does not preserve contextual equivalence (Section 6.4).

6.1 The G Language

\( {\color {#41A9A6}{\mathtt {G}}} \) extends System F with two primitives (Figure 4). The first one casts values of type \( {\color {#41A9A6}{\mathtt {\tau _1}}} \) to values of type \( {\color {#41A9A6}{\mathtt {\tau _2}}} \). The second one generates a fresh type name \( {\color {#41A9A6}{\mathtt {X}}} \) that is registered to be an equivalent classifier to a type \( {\color {#41A9A6}{\mathtt {\tau }}} \) although data of the two types is not equivalent (so casting between \( {\color {#41A9A6}{\mathtt {X}}} \) and \( {\color {#41A9A6}{\mathtt {\tau }}} \) will not succeed).

Fig. 4.

Fig. 4. The \( {\color {#41A9A6}{\mathtt {G}}} \) language: syntax, typing rules and evaluation rules (excerpts). The semantics relation \( {\color {#41A9A6}{\mathtt {\hookrightarrow }}} \) relies on the primitive reductions indicated as \( {\color {#41A9A6}{\mathtt {\hookrightarrow _{\mathit {0}}}}} \) and it relates configurations of the form \( {\color {#41A9A6}{\mathtt {\sum \triangleright t}}} \) .

6.2 Enforcing Parametricity in G

To avoid much code repetition, we use the same notation for the wrapper as that used by Neis et al. [2009]. Instead of writing two recursive functions such as \( {\color {#EF257F}{\mathsf {protect}}}_{{{\color {black}{}}};{{\color {#0C80CF}{\mathbf {}}}}} \) and \( {\color {#EF257F}{\mathsf {confine}}}_{{{\color {black}{}}};{{\color {#0C80CF}{\mathbf {}}}}} \), we annotate the wrapper with a polarity: positive polarity (\( + \)) is analogous to \( {\color {#EF257F}{\mathsf {protect}}}_{{{\color {black}{}}};{{\color {#0C80CF}{\mathbf {}}}}} \), negative polarity (\( - \)) is analogous to \( {\color {#EF257F}{\mathsf {confine}}}_{{{\color {black}{}}};{{\color {#0C80CF}{\mathbf {}}}}} \). When the other function is invoked, the polarity is switched (i.e., from \( \pm \) to \( \mp \)).

The wrapper consists of three parts. The first one, \( {{\color {black}{\mathrm{W}^{\pm }_{{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}}\left({\color {#41A9A6}{\mathtt {t}}}\right)}}} \), is the term wrapper, it reduces a term \( {\color {#41A9A6}{\mathtt {t}}} \) of source type \( \mathbf {{\color {#0C80CF}{\tau }}} \) to a value and applies the value wrapper. The second one, \( {{\color {black}{\mathrm{Wrap}^{\pm }_{{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}}\left({\color {#41A9A6}{\mathtt {v}}}\right)}}} \), is the value wrapper, it is responsible for generating the fresh type variables for outgoing universal values and incoming existential packages. The third one, \( {{\color {black}{\mathrm{NewTy}^{\pm } {{\color {#41A9A6}{\mathtt {X}}}} ~\mathrm{in}}}}~ {{\color {#41A9A6}{\mathtt {{\color {#41A9A6}{\mathtt {t}}}}}}} \) is the code that effectively generates the fresh type variables, depending on the polarity of the invocation. As the authors themselves note, the wrapper functions in a way analogous to the dynamic checks inserted by the Sumii-Pierce compiler.

The compiler from \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) to \( {\color {#41A9A6}{\mathtt {G}}} \), denoted with \( ⟅{\color {#0C80CF}{\mathbf {\cdot }}}⟆ \), leaves the term untouched (which we indicate with \( \equiv \)) and wraps it with a wrapper of the appropriate type.

The NDR conjecture (Conjecture 6.1) states that this wrapper is fully abstract. Contextual equivalence in \( {\color {#41A9A6}{\mathtt {G}}} \), indicated with \( {\color {#41A9A6}{\mathtt {\mathrel {\simeq }}}} \), is defined analogously to 2.1.

Conjecture 6.1 (NDR Conjecture).

We will prove that this statement is not true (6.3).

6.3 G has an Instance of an Universal Type: ∀Z.Z

To explain how we disprove the NDR conjecture, we need to explain that \( {\color {#41A9A6}{\mathtt {G}}} \) indeed has a universal type (unlike System F). This type is \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \) and it functions as a universal type because we can take any other type \( {\color {#41A9A6}{\mathtt {X}}} \) and (i) embed a value \( {\color {#41A9A6}{\mathtt {v}}} \) of type \( {\color {#41A9A6}{\mathtt {X}}} \) into \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \), (ii) extract the same value \( {\color {#41A9A6}{\mathtt {v}}} \) from \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \) at type \( {\color {#41A9A6}{\mathtt {X}}} \). It is possible to do this while remaining parametric in the type \( {\color {#41A9A6}{\mathtt {X}}} \) that these functions work with, i.e., keeping type variable \( {\color {#41A9A6}{\mathtt {X}}} \) free in these terms and binding it in a larger term using both these functions.

These two functionalities will be key for building a distinguishing context for \( {\color {#41A9A6}{\mathtt {G}}} \) which is analogous to the distinguishing contexts of for \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \) and \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) (the latter will be presented later). A value \( {\color {#41A9A6}{\mathtt {v}}} \) of an arbitrary type \( {\color {#41A9A6}{\mathtt {\tau }}} \) is represented as a value of type \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \). The cast operator in \( {\color {#41A9A6}{\mathtt {G}}} \) allows us to make this function behave differently when it is applied to type \( {\color {#41A9A6}{\mathtt {\tau }}} \) than when it is applied to other types. In the former case, we will make the function return \( {\color {#41A9A6}{\mathtt {v}}} \) itself, while in the latter case, we simply make the function diverge.

Concretely, to extract a value from \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \) into \( {\color {#41A9A6}{\mathtt {X}}} \), we simply apply the polymorphic function to type \( {\color {#41A9A6}{\mathtt {X}}} \): \( \begin{*} {\color {#41A9A6}{\mathtt { \lambda {\color {#41A9A6}{\mathtt {z:({\forall }Z\ldotp Z)}}} \ldotp {\color {#41A9A6}{\mathtt {z~X}}} }}} \end{align*} \)

Injecting a value of type from \( {\color {#41A9A6}{\mathtt {X}}} \) into \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \) is a bit more complex. What we would like to write is the following:

This term uses the \( {\color {#41A9A6}{\mathtt {{\color {#41A9A6}{\mathtt {cast}}}~\cdot \ \cdot }}} \) primitive to cast a value of type \( {\color {#41A9A6}{\mathtt {X}}} \) into \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \). If everything goes well, the requested type \( {\color {#41A9A6}{\mathtt {Z}}} \) is the same as the type \( {\color {#41A9A6}{\mathtt {X}}} \) of the value contained, and the constructed function returns \( {\color {#41A9A6}{\mathtt {x}}} \). Otherwise, it diverges by calling \( {\color {#41A9A6}{\mathtt {\omega _Z}}} \).

Unfortunately, the above does not work as intended because we are in a call-by-value setting, so \( {\color {#41A9A6}{\mathtt {\omega _Z}}} \) is evaluated before checking the type equality and the whole term always diverges. Fortunately, this can be resolved by the standard trick of “thunking” the term and the expected value \( {\color {#41A9A6}{\mathtt {x}}} \) into lambdas that expect a \( {\color {#41A9A6}{\mathtt {{Unit} }}} \) value, and pass \( {\color {#41A9A6}{\mathtt {{unit} }}} \) to them after the cast:

To see how these functions work in practice in our counterexample, we build a term that uses them in order to inject \( {\color {#41A9A6}{\mathtt {{true} }}} \) of type \( {\color {#41A9A6}{\mathtt {{Bool} }}} \) into \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \) and extract \( {\color {#41A9A6}{\mathtt {{true} }}} \) back. The term and its reductions are in Figure 5.

Fig. 5.

Fig. 5. Reductions of the combination of the two functionalities.

6.4 Disproving the NDR Conjecture

We now have all the technical machinery to disprove the NDR conjecture.

Compiling \( {\color {#0C80CF}{\mathbf {t_u }}} \) to \( {\color {#41A9A6}{\mathtt {G}}} \) results in a complex term that is equivalent to the following one, where, for simplicity, we have elided some redundant sub-terms that do not alter the semantics of the overall-term. As a convention we name variables and type variables from the wrapper with \( {\color {#41A9A6}{\mathtt {y}}} \). The first line is the \( {\color {#0C80CF}{\mathbf {t_u }}} \) term ported to \( {\color {#41A9A6}{\mathtt {G}}} \), the second and third lines (as well as the wrapping lambda) are wrapper-generated code. This code will take the parameter that needs to be passed to \( {\color {#0C80CF}{\mathbf {t_u }}} \) and perform a series of unpacking and type renaming which are intended to preserve parametricity.

The distinguishing context for \( {\color {#41A9A6}{\mathtt {G}}} \) passes a parameter of type \( {\color {#41A9A6}{\mathtt {\underline{Univ}}}} \) to the term in the hole (which will be either or ). The goal of this parameter is to make terminate and diverge. Let us discuss the passed parameter. Since \( {\color {#41A9A6}{\mathtt {\underline{Univ}}}} \) is an existential type at the top level, the parameter is a \( {\color {#41A9A6}{\mathtt {{\color {#41A9A6}{\mathtt {pack}}}~\left\langle \cdot \right\rangle ~{\color {#41A9A6}{\mathtt {as}}}~\cdot }}} \). The packed type is the universal type that exists in \( {\color {#41A9A6}{\mathtt {G}}} \): \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \). After the existential, \( {\color {#41A9A6}{\mathtt {\underline{Univ}}}} \) has a universal quantification, and thus the body of the existential package contains a \( {\color {#41A9A6}{\mathtt {{\Lambda }Z\ldotp \cdot }}} \). Then comes the pair of functions for projecting into and extracting from the universal type \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \), as explained in Section 6.3. As a convention, we name variables and type variables from the context with \( {\color {#41A9A6}{\mathtt {z}}} \):

Theorem 6.2

( and are Not Equivalent in \( {\color {#41A9A6}{\mathtt {G}}} \))

Proof.

We have that while .□

Theorem 6.3

(Embedding λFintoGis Not Fully Abstract)

It is not true that

Proof.

Follows directly from Theorems 3.1 and 6.2.□

Additional instances of universal types in \( {\color {#41A9A6}{\mathtt {G}}} \). \( {\color {#41A9A6}{\mathtt {{\forall }Z\ldotp Z}}} \) is not the only universal type in \( {\color {#41A9A6}{\mathtt {G}}} \). The type \( {\color {#41A9A6}{\mathtt {\exists X.X}}} \) works just as well and might be more intuitive to some readers. The context below is analogous to the one above and can also differentiate between the compilation of \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and of \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \).

Skip 7SYSTEM F EQUIVALENCES VS. GRADUAL TYPES Section

7 SYSTEM F EQUIVALENCES VS. GRADUAL TYPES

After discussing these conjectures, we turn our attention to polymorphic gradual calculi: gradually typed languages featuring parametric polymorphism. As explained in the introduction, gradually-typed languages provide a path for migrating codebases of untyped code to typed code. From this high-level idea, a number of natural design goals follow and the literature contains a number of correctness properties that formally express these objectives.

First, gradual languages are intended to preserve the semantics of existing typed and untyped code. Additionally, turning untyped programs into typed ones by adding correct (!) type signatures should not modify the semantics of programs. Without going into detail (because it is not relevant for our discussion), Siek et al. [2015] formalise these objectives as a number of formal criteria for gradually-typed languages, which include the gradual guarantee.

Another high-level design goal of gradually-typed languages is that the typed components continue to enjoy the benefits of well-typedness in the presence of untyped other components. Wadler and Findler [2009] have proposed the Blame Theorem that expresses this property when it comes to one such benefit: the absence of type errors at runtime. Gradual languages rely on dynamic casts (which can fail at runtime) to coerce untyped values into typed ones. Wadler and Findler add a notion of blame, which is essentially a way to identify the type cast that caused a runtime type error. The Blame Theorem then expresses that well-typed components are never to blame for such failures, i.e., the property that well-typed components never cause runtime type errors remains valid in the gradual language.

Jacobs et al. [2021] have recently argued the importance of on another benefit of well-typedness that has received less attention so far: the benefits that well-typedness provides in terms of reasoning. Many type systems allow us to deduce properties of components from their types, for example, the function \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x: {Unit} \ldotp x}}}} \) is easily seen to be equivalent to \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\lambda }}} x: {Unit} \ldotp {unit} }}}} \), based on the terms’ types. Formulations of System F parametricity similarly allows us to deduce properties from programs’ types.

Jacobs et al. propose a criterion that requires gradual type systems to preserve the validity of such reasoning in the original typed language. Specifically, the criterion requires that contextual equivalences between typed terms continue to hold when these terms are considered in the gradual language. Formally, there is an embedding of \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) terms \( {{\color {#0C80CF}{\mathbf {t}}}} \) into \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) terms that we will denote as \( {\color {orange}{\mathit {{{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t}}}}{\rfloor }}}}}}} \). The criterion then becomes: if \( {{\color {#0C80CF}{\mathbf {t_1}}}} \mathrel {{{\color {#0C80CF}{\mathbf {\mathrel {\simeq }}}}}}{{\color {#0C80CF}{\mathbf {t_2}}}} \), do we have that \( {{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_1}}}}}}}}{\rfloor }}}} {\color {orange}{\mathit {\mathrel {\simeq }}}}{{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_2}}}}}}}}{\rfloor }}}} \), or, in other words, is the embedding of the typed language into the gradual language fully abstract? Based on this view, Jacobs et al. refer to their criterion as the Fully Abstract Embedding (FAE) criterion.

In this section, we show that the criterion fails for the polymorphic blame calculus, which extends System F into a gradually typed language. We first present Ahmed et al.’s\( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \), a gradually-typed, polymorphic lambda-calculus (Section 7.1). Next, we reconsider \( {\color {#0C80CF}{\mathbf {t_u }}} \) and \( {\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}} \) from 3.1 in \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) and present a \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) context that differentiates them (Section 7.2). This shows that the embedding of \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) into \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) is not fully abstract.14

7.1 The λF Calculus

There exist several versions of polymorphic gradual languages in the literature [Ahmed et al. 2011a, 2017; Igarashi et al. 2017; New et al. 2019a; Toro et al. 2019; Xie et al. 2018]. We take \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) to be the polymorphic blame calculus as described by Ahmed et al. [2017]. This version modifies certain behaviour that was “topsy turvy” in the original version [Ahmed et al. 2011a]: a peculiar operational semantics that performs evaluation under type and value abstractions and an ad hoc postponing of run-time type generation in certain situations.

The syntax of \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) is presented in Figure 6. The calculus contains all terms and types of \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) except for existentials. However, we can use a standard encoding of existentials in terms of universals as follows [Pierce 2002, Section 24.3, pp. 377–379]:

Fig. 6.

Fig. 6. The polymorphic blame calculus [Ahmed et al. 2017]. Note: we have adapted notations, added the \( {\color {orange}{\mathit {{Unit} }}} \) type and removed the \( {\color {orange}{\mathit {int}}} \) type to align more closely with other calculi in this paper.

Even though existentials under this encoding are not entirely equivalent to regular existentials in our non-terminating calculus (because they contain a kind of bottom value), we can adapt our counterexample without trouble.

Then, \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) contains a number of constructs to let typed and untyped code coexist. First we have the type \( {\color {orange}{\mathit {\star }}} \): the type of untyped values. Untyped code can be typed with respect to the single, universal type \( {\color {orange}{\mathit {\star }}} \). \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) provides both a notion of casts (\( {\color {orange}{\mathit {t:\tau \Rightarrow {p}\tau ^{\prime }}}} \)) and a notion of conversions (\( {\color {orange}{\mathit {t:\tau \Rightarrow {\phi }\tau }}} \)).

Casts (\( {\color {orange}{\mathit {t:\tau \Rightarrow {p}\tau ^{\prime }}}} \)) represent a form of dynamic casts from \( {\color {orange}{\mathit {\tau }}} \) to \( {\color {orange}{\mathit {\tau ^{\prime }}}} \) that can potentially fail at runtime (in which case \( {\color {orange}{\mathit {blame~ p}}} \) is raised). Casts can be used to inject types \( {\color {orange}{\mathit {\tau }}} \) into the universal type \( {\color {orange}{\mathit {\star }}} \) and also to extract those types out of \( {\color {orange}{\mathit {\star }}} \) again. More generally, they can be used to convert between any types \( {\color {orange}{\mathit {\tau }}} \) and \( {\color {orange}{\mathit {\tau ^{\prime }}}} \) that satisfy a compatibility judgement \( {\color {orange}{\mathit {\Sigma ;\Delta \vdash \tau \prec \tau ^{\prime }}}} \), but we omit details for this because they are not relevant for our discussion. As part of the design that solves certain topsy-turvy aspects of the operational semantics in previous versions, \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) carefully defines some casts as values: those where the term being cast is a value and the cast is either (1) between function types, (2) towards a polymorphic function type or (3) from a ground type \( {\color {orange}{\mathit {\gamma }}} \) into \( {\color {orange}{\mathit {\star }}} \).

Polymorphic function application in \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) does not use type substitution like in System F, but uses a notion of runtime type generation instead. Full details are not relevant for our discussion, but essentially, a polymorphic function application does not reduce to \( {\color {orange}{\mathit {\lambda x:{Unit} \ldotp x}}} \) but to \( {\color {orange}{\mathit {\lambda x:\alpha \ldotp x}}} \) for a fresh runtime type label \( {\color {orange}{\mathit {\alpha }}} \), where the assignment \( {\color {orange}{\mathit {\alpha \mathbin {:=} {Unit} }}} \) is remembered in a type-name store \( {\color {orange}{\mathit {\Sigma }}} \). Conversions (\( {\color {orange}{\mathit {t:\tau \Rightarrow {\phi }\tau ^{\prime }}}} \)) represent a notion of static casts for converting between such a runtime type label \( {\color {orange}{\mathit {\alpha }}} \) and the type that is assigned to it in the store \( {\color {orange}{\mathit {\Sigma }}} \). More generally, a convertibility judgement \( {\color {orange}{\mathit {\Sigma ;\Delta \vdash \tau \prec ^{\phi } \tau ^{\prime }}}} \) defines when \( {\color {orange}{\mathit {\tau }}} \) can be legally converted into \( {\color {orange}{\mathit {\tau ^{\prime }}}} \) by expanding (\( {\color {orange}{\mathit {+\alpha }}} \in {\color {orange}{\mathit {\phi }}} \)) or reducing (\( {\color {orange}{\mathit {-\alpha }}} \in {\color {orange}{\mathit {\phi }}} \)) runtime type labels’ definitions.

7.2 Embedding of λF into λB is not Fully Abstract

To embed \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) (defined in section 2.1) into \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \), most constructs can simply be mapped to the corresponding construct in \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \). However, there is a discrepancy between type abstractions in \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) and \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \). The difference is that \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) uses value polymorphism: the bodies of type abstractions are required to be values. This choice has some desirable consequences, particularly that type abstractions and applications can be removed entirely during type erasure.

The difference is essentially orthogonal to the topics of this paper, but we are unable to standardise on using value polymorphism or not, because the non-parametrically polymorphic language \( {\color {#41A9A6}{\mathtt {G}}} \) from the previous section and the polymorphic blame calculus \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) make different choices and would both be non-trivial to modify.

Therefore, we embed polymorphic functions from \( {{\color {black}{\lambda }}}^{{{\color {#0C80CF}{\mathbf {F}}}}} \) into \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) by introducing a form of thunking for polymorphic functions: the type \( {{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}} \) is mapped to \( {{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {{{{\color {#0C80CF}{\mathbf {\forall }}}}}X\ldotp \mathbf {{\color {#0C80CF}{\tau }}}}}}}{\rfloor }}}} \mathrel {\overset{\text {def}}{=}}{\color {orange}{\mathit {\forall X\ldotp {Unit} \rightarrow {{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\tau }}} }}}}{\rfloor }}}}}}} \) and type abstractions \( {{\color {#0C80CF}{\mathbf {\mathbf {{\color {#0C80CF}{\Lambda }}} X\ldotp t}}}} \) are mapped to .

Our two contextually equivalent System F terms \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) and \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \) embed into \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) as \( {{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_u }}}}}}}}{\rfloor }}}} \) and \( {{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}}}}}}{\rfloor }}}} \). In this section, we show that they do not remain contextually equivalent, showing that the embedding is not fully abstract. Similarly to before, we can construct a \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) context \( {\color {orange}{\mathit {{C}^B}}} \) that differentiates them. As before, the context simply applies the terms to a non-degenerate value of type \( {\color {orange}{\mathit {\mathrm{Univ}}}} \), which we can construct thanks to the existence of the universal type \( {\color {orange}{\mathit {\star }}} \):

The constructed \( {\color {orange}{\mathit {\mathrm{Univ}}}} \) value simply takes \( {\color {orange}{\mathit {\star }}} \) as the existentially quantified universal type and uses casts to implement the functions from an arbitrary \( {\color {orange}{\mathit {X}}} \) into \( {\color {orange}{\mathit {\star }}} \) and back.

In the following, contextual equivalence in \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \), indicated with \( {\color {orange}{\mathit {\mathrel {\simeq }}}} \), is defined analogously to 2.1.

Theorem 7.1

(\( {{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t_u }}}}{\rfloor }}}} \) and \( {{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}}{\rfloor }}}} \) are Not Equivalent in \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \)).

.

Proof.

We have that \( {\color {orange}{\mathit {{C}^B[\mathbf {{\color {#0C80CF}{[}}}]\big ]{{{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t_u }}}}{\rfloor }}}}}}}}\mathrel {{\color {orange}{\mathit {\hookrightarrow ^*}}}}{\color {orange}{\mathit {{unit} }}} \) while \( {\color {orange}{\mathit {{C}^B[\mathbf {{\color {#0C80CF}{[}}}]\big ]{{{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}}{\rfloor }}}}}}}}{\color {orange}{\mathit {\Uparrow }}} \). We have verified this on paper and using the interpreter provided by Jamner and Siek to support Ahmed et al. [2017]’s results.15\( ^{,} \)16 We provide the literal encoding of \( {\color {orange}{\mathit {{C}^B[\mathbf {{\color {#0C80CF}{[}}}]\big ]{{{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t_u }}}}{\rfloor }}}}}}}} \) and \( {\color {orange}{\mathit {{C}^B[\mathbf {{\color {#0C80CF}{[}}}]\big ]{{{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}}{\rfloor }}}}}}}} \) for use in the interpreter in the supplementary material.□

Theorem 7.2

(Embedding λFinto λBis Not Fully Abstract)

It is not true that \( \begin{*} \forall {{\color {#0C80CF}{\mathbf {t_1}}}},{{\color {#0C80CF}{\mathbf {t_2}}}}. {{\color {#0C80CF}{\mathbf {t_1}}}}\mathrel {{{\color {#0C80CF}{\mathbf {\mathrel {\simeq }}}}}}{{\color {#0C80CF}{\mathbf {t_2}}}} \iff {\color {orange}{\mathit {{{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t_1}}}}{\rfloor }}}}}}}{\color {orange}{\mathit {\mathrel {\simeq }}}}{\color {orange}{\mathit {{{\color {black}{{\lfloor }{{\color {#0C80CF}{\mathbf {t_2}}}}{\rfloor }}}}}}} \end{align*} \)

Proof.

Follows directly from Theorems 3.1 and 7.1.□

Although the above discussion looks just at \( {{\color {black}{\lambda }}}^{{\color {orange}{\mathit {B}}}} \) by Ahmed et al. [2017], our results also apply to the more recent polymorphic gradual languages proposed by Toro et al. [2019], New et al. [2019a] and Xie et al. [2018].

Skip 8DISCUSSION Section

8 DISCUSSION

So Sumii and Pierce’s compiler is not fully abstract, the polymorphic blame calculus breaks contextual equivalences in System F, and enforcing parametricity in a non-parametric calculus also breaks contextual equivalence. But what to conclude from this? Should we start looking for alternative ways to dynamically enforce parametricity or were we wrong to hope for these properties to hold in the first place? In this section we present some thoughts on the different possible options.

First, it is interesting to investigate whether full abstraction could be recovered by fixing Sumii and Pierce’s compiler or the polymorphic blame calculus. We discuss in the sections below some possible paths to explore, but we believe there are no straightforward solutions.

Second, another possible conclusion from our negative results is that full abstraction is perhaps too strong a property to aim for when doing secure compilation or gradual typing. We still think the Sumii-Pierce compiler is a useful secure compiler, even if it is not fully abstract. Hence, we discuss how to weaken the requirements that full abstraction imposes on a translation from System F, by modifying System F in a way that weakens its contextual equivalences.

8.1 Fixing Sumii and Pierce’s Compiler?

One of the attractive features of Sumii and Pierce’s original conjecture is that it relies only on encryption (or at least, an idealised version of encryption in the form of seals). Because it required only encryption, this suggested that System F types could even be enforced as the contract for an untrusted adversary, running at the other end of a communication channel, on an untrusted computer. However, if we analyse the counterexample, this ambition of using just encryption seems hard to maintain.

Imagine that a compiled System F term (e.g., \( {{\color {#0C80CF}{\mathbf {t_u }}}} \) or \( {{\color {#0C80CF}{\mathbf {t_{\mathbf {{\color {#0C80CF}{\omega }}}} }}}} \)) is communicating with such an adversary over a communication channel and we want to enforce that the adversary respects the contract represented by System F type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \). What happens is the following:

(1)

The compiled term transmits the value \( {{\color {#0C80CF}{\mathbf {{unit} }}}} \) of type \( {{\color {#0C80CF}{\mathbf {{Unit} }}}} \), encrypted as \( {\color {#EF257F}{\mathsf {\lbrace {unit} \rbrace _{\sigma }}}} \) of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) that is kept opaque from the adversary. The seal \( {\color {#EF257F}{\mathsf {\sigma }}} \) represents a fresh cryptographic key that we take care not to disclose to the adversary.

(2)

The adversary replies with a value of the unknown type \( {{\color {#0C80CF}{\mathbf {Y}}}} \) (chosen by the adversary). The actual value transmitted back in our counterexample, is simply the encrypted value \( {\color {#EF257F}{\mathsf {\lbrace {unit} \rbrace _{\sigma }}}} \) received in step 1.

(3)

The compiled term does not inspect the received value but simply transmits it back to the adversary as a value of type \( {{\color {#0C80CF}{\mathbf {Y}}}} \).

(4)

The adversary now takes the received value \( {\color {#EF257F}{\mathsf {\lbrace {unit} \rbrace _{\sigma }}}} \) and sends it back as a value of type \( {{\color {#0C80CF}{\mathbf {X}}}} \).

(5)

The compiled term receives this value, decrypts it using the private cryptographic key \( {\color {#EF257F}{\mathsf {\sigma }}} \) and uses the result as a value of type \( {{\color {#0C80CF}{\mathbf {{Unit} }}}} \).

What goes wrong in the above communication is that the value \( {\color {#EF257F}{\mathsf {\lbrace {unit} \rbrace _{\sigma }}}} \) sent back by the adversary in step 2 is essentially illegal. The adversary should have chosen a \( {{\color {#0C80CF}{\mathbf {Y}}}} \) independently of \( {{\color {#0C80CF}{\mathbf {X}}}} \) and values of such a type should intuitively not be able to contain values of type \( {{\color {#0C80CF}{\mathbf {X}}}} \) (unless they are themselves packed in an existential package somehow). Let us try to think of what we could change in the communication protocol to enforce this.

In a pure cryptographic setting, we believe there is little hope to fix the compiler. To understand this, consider how, in the cryptography setting, the value \( {\color {#EF257F}{\mathsf {\lbrace {unit} \rbrace _{\sigma }}}} \), that we send to the adversary in step 1, simply represents a sequence of bits that is the result of some encryption algorithm applied to value \( {{\color {#0C80CF}{\mathbf {{unit} }}}} \). On the other hand, the value sent back by the adversary in step 2 is another sequence of bits that represents a value of an unknown type \( {{\color {#0C80CF}{\mathbf {Y}}}} \). We want to prevent this second value from somehow including the first value \( {\color {#EF257F}{\mathsf {\lbrace {unit} \rbrace _{\sigma }}}} \), but since the type \( {{\color {#0C80CF}{\mathbf {Y}}}} \) is unknown and the adversary is running on an untrusted computer, there seems to be little the compiler can check. Any sequence of bits received from the adversary could in principle be a cleverly-encoded version of \( {\color {#EF257F}{\mathsf {\lbrace {unit} \rbrace _{\sigma }}}} \): they could have XORed the value with an arbitary other bitsequence and still be able to retrieve the original afterwards.

This (informal) argument suggests that the Sumii-Pierce compiler cannot be fixed in any way, as long as the target language contains only features that can be interpreted as a form of (idealised) cryptography. This would include the original sealing primitives (whatever way they are used), but also possible extensions that model a form of idealised signing (rather than encryption) (a track we were initially exploring).

To fix the compiler, it seems like we need to add some kind of feature that takes us beyond a pure-cryptography setting. We believe such a feature could take the form of a primitive that checks whether a value directly or indirectly contains values sealed with a certain seal. Such a primitive could perhaps allow to perform the required check on the value received from the adversary in step 2. Such a primitive does not correspond to a form of idealised encryption: noticing, for example, that a value like \( {\color {#EF257F}{\mathsf {\lbrace \lbrace v\rbrace _{\sigma _1}\rbrace _{\sigma _2}}}} \) contains a value sealed with \( {\color {#EF257F}{\mathsf {\sigma _1}}} \) would break the cryptographic interpretation of \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \), as it requires looking inside an encrypted value without access to the key (\( {\color {#EF257F}{\mathsf {\sigma _2}}} \)) and requires detecting, for example, arbitrarily XORed versions of a ciphertext. However, the primitive could still be implementable in non-cryptographic settings, like the hardware-enforced seals that are present in capability machines: a form of processor with native support for capabilities and sealing that has been developed recently [Watson et al. 2015]. Note that the attacker model in this setting is a bit different: we assume that the untrusted attacker is now running on trusted hardware.

8.2 Polymorphic Blame Calculus Without a Universal Type?

Whether or not it is feasible to construct a gradual polymorphic language that fully abstractly embeds System F is unclear. In fact, even simply reconciling type safety results like the Blame Theorem (see Section 7) or the Dynamic Gradual Guarantee (which expresses that removing type annotations from a term should never cause the term to fail at runtime) with parametricity is the topic of ongoing research. In fact,in the design of their GSF calculus, Toro et al. [2019] explicitly abandon the dynamic gradual guarantee in order to salvage parametricity, formulated using a TWLR. New et al. [2019a] have recently reconciled (a TWLR-based form of) parametricity with the dynamic gradual guarantee, by requiring explicit sealing annotations in the source.

All published gradual polymorphic calculi make use of dynamic sealing and as such, do not satisfy the FAE criterion, except perhaps for one. Labrada et al. [2022] have investigated an alternative design, based on a form of lexically-scoped sealing (in addition to some other new ideas like plausible sealing). It would lead us too far to expain the details here, but the design replaces the type \( {\color {orange}{\mathit {\star }}} \) with a family of types \( {\color {orange}{\mathit {\star _{\lbrace \bar{X}\rbrace }}}} \), indexed by a set of type variables \( {\color {orange}{\mathit {\bar{X}}}} \). The type \( {\color {orange}{\mathit {\star _{\bar{X}}}}} \) is only legal (i.e., well-formed) when the type variables \( {\color {orange}{\mathit {\bar{X}}}} \) are in scope. Injecting values of type \( {\color {orange}{\mathit {X^{\prime }}}} \) into \( {\color {orange}{\mathit {\star _{\bar{X}}}}} \) is only legal if \( {\color {orange}{\mathit {X^{\prime }}}} \) is in the set \( {\color {orange}{\mathit {\bar{X}}}} \). For our FAE counterexample, the effect is that the context can no longer produce a non-degenerate value of type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \), as there would no longer be a viable choice for \( {{\color {#0C80CF}{\mathbf {Y}}}} \). Any instance \( {\color {orange}{\mathit {\star _{\lbrace \bar{X}\rbrace }}}} \) of the universal type we could choose, could not have \( {{\color {#0C80CF}{\mathbf {X}}}} \) as part of \( {\color {orange}{\mathit {\lbrace \bar{X}\rbrace }}} \), as \( {{\color {#0C80CF}{\mathbf {X}}}} \) is not yet in scope at the moment where \( {{\color {#0C80CF}{\mathbf {Y}}}} \) needs to be produced.

Although the new design still has some restrictions, it satisfies a form of RLR-based parametricity. As such, the jury is still out, but we believe the FAE criterion may not be out of reach in the context of gradual parametricity.

8.3 Adjusting our Expectations

For us, the solutions suggested above look like they might work, but they are not without downsides. The modified Sumii-Pierce compiler could no longer be used in a purely-cryptographic setting and the family of universal types \( {\color {orange}{\mathit {\star _{\lbrace \bar{X}\rbrace }}}} \) might be harder to use than the original \( {\color {orange}{\mathit {\star }}} \). As such, we might consider alternative ways to address the lack of full abstraction.

One alternative is to abandon the choice of fully abstract compilation and rely on other notions. More concretely, perhaps a secure compiler or gradually typed language should not preserve arbitrary System F equivalences but only some of them, namely those that follow from a TWLR-based formulation of parametricity?

Another alternative is to keep relying on fully abstract compilation and decide to simply adjust our expectations: perhaps preserving all System F equivalences is overly ambitious and we should find a way to eat what is on the table instead. Both in the case of Sumii and Pierce’s compiler and the gradual lambda calculus, it seems like something non-trivial is being enforced, even though it is not the preservation of arbitrary System F contextual equivalences. A way to formalise this is to recover full abstraction by modifying the source language System F: weakening its contextual equivalences in order to make them easier to preserve.

In fact, our counterexample suggests a way to accomplish this: the problem is essentially that the type \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) is degenerate in System F, but not in the target language. So what if we modify System F to remove that degeneracy in the source language too? Specifically, what if we add a primitive type that all other types can be embedded into and extracted from? Interestingly, it seems like what we end up here is a simple version of the gradual type \( {\color {orange}{\mathit {\star }}} \), together with injection and extraction functions.

Without working this out in more detail, we find it plausible that we can recover full abstraction with such a modification, both for Sumii and Pierce’s compiler and the embedding into the polymorphic blame calculus. Ahmed et al. [2017], Toro et al. [2019] and New et al. [2019a] have shown that such a variant of System F still satisfies useful (TWLR-based) parametricity results and that useful free theorems follow from it, suggesting it is a suitable language for programmers to work in.

Skip 9RELATED WORK Section

9 RELATED WORK

System F and parametricity. Parametric polymorphism was first introduced 50 years ago as an informal concept by Strachey [2000]. A few years later, System F was independently discovered by Reynolds [1974] and Girard [1972]. Reynolds [1983] later formalised Strachey’s informal concept of parametricity using a logical relation for System F, as explained in Example 2.2 and Wadler [1989] popularised the property using the slogan “Theorems for Free”. The property was further developed by many different researchers over the years but for space reasons, we refer to Wadler [2007]; Atkey et al. [2014] for an overview of related work.

Enforcing parametricity using dynamic sealing. Dynamic sealing/unsealing was (informally) proposed more than 40 years ago by Morris [1973a]; , 1973b] as a way for dynamically enforcing type abstractions. Much later, Pierce and Sumii [2000] developed this idea into a compiler that uses sealing to enforce System F’s parametricity and conjectured full abstraction of the proposed compiler. The target language in this work is a simply typed cryptographic \( \lambda \)-calculus. They already mention that the dynamic enforcement of parametricity may also be useful to combine parametric polymorphism and untyped languages, foreshadowing the work on parametrically polymorphic gradual type systems that we discuss next.

A few years later, the same authors report further on the simply typed cryptographic \( \lambda \)-calculus and construct a logical relation for proving contextual equivalences for it [Sumii and Pierce 2003]. Another year later, they report on a bisimulation that can be used to prove contextual equivalence in \( {{\color {black}{\lambda }}}^{{\color {#EF257F}{\mathsf {\sigma }}}} \), which they originally constructed for proving the conjectured full abstraction [Sumii and Pierce 2004]. In this last paper, the compiler is presented for an untyped version of the cryptographic \( \lambda \)-calculus (as in this text), which renders it significantly simpler.

Sealing was also used to enforce polymorphic contracts in PLT Scheme by Guha et al. [2007]. While technically similar, the assumptions in that work are somewhat different than in the above, as contracts are about protecting the context from misbehaving terms, while Sumii and Pierce’s compiler protects trusted terms from a misbehaving context. Like other work discussed in this paper, Guha et al.’s polymorphic contracts fail to enforce the degeneracy of \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \), so if they satisfy a form of parametricity, it would have to be TWLR-based.

Gradual typing. Gradual typing is a specific way of combining dynamic and static typing in a single language, intended to create a gradual migration path from untyped to typed codebases. Since it was originally proposed by Siek and Taha [2006] and Tobin-Hochstadt and Felleisen [2006], gradual typing has received a lot of attention: gradual extensions have been constructed for many different type systems, the notion of blame was adapted from the world of contracts [Findler and Felleisen 2002] to track the origin of a dynamic cast failure [Wadler and Findler 2009], correctness criteria were studied [Siek et al. 2015], the process of constructing a gradually-typed version of a pre-existing type system was to some extent automated [Cimini and Siek 2016; Garcia et al. 2016] and last but not least, the entire approach has also been declared dead because of severe performance issues [Takikawa et al. 2016].

Prior to the work on gradual typing, calculi which combined statically-typed languages with a universal type for interacting with untyped code, have been proposed by Henglein [1994] and Abadi et al. [1991].

As mentioned in Section 7, formal criteria for gradual type systems have been proposed by Siek et al. [2015], including the gradual guarantee. Garcia and Tanter [2020] later argued that gradually typed languages should additionally preserve reasoning principles of the static type system. Jacobs et al. [2021] have proposed that this can be formulated in a standard way in the form of the Fully Abstract Embedding (FAE) criterion and have established the criterion for the GTLC, a basic gradual type system.

Gradual typing and parametric polymorphism. As an instance of a multi-language (as proposed by Matthews and Findler [2009]), Matthews and Ahmed [2008] construct a language that can embed both Scheme (i.e., an untyped lambda calculus) and ML (i.e., a parametrically polymorphic typed lambda calculus) using a notion of dynamic casts from one to the other. They enforce parametric polymorphism using a notion of run-time type generation17 and prove a parametricity result. An error in the proof was later corrected [Ahmed et al. 2011].

Next, Ahmed et al. [2011a]; , 2009] present the first version of the polymorphic blame calculus, a gradually-typed extension of System F that includes a notion of blame. The authors prove a number of correctness results, but Perconti found an incorrectible error in one of the proofs later [Ahmed et al. 2011b]. However, they do not consider parametricity or preservation of System F contextual equivalences (i.e., fully abstract embedding).

Ahmed et al. [2017] present \( \lambda _B \): a new version of the polymorphic blame calculus rectifying certain “topsy-turvy” aspects of its operational semantics (see section 7). Additionally, they prove a parametricity result for this calculus, which we have discussed from the perspective of our results in section 8.3.

Igarashi et al. [2017] also present a new version of the polymorphic blame calculus, as an internal runtime representation for System \( F_G \) a new gradually-typed extension of System F. They make certain special restrictions to the consistency and precision relation of the system (later criticised by others [Toro et al. 2019]), which allow them to prove a version of the gradual guarantee. However, it does not seem to prevent our counterexample to the fully abstract embedding of System F.

In an unpublished draft, Siek and Wadler [2016] study and interrelate three ways to achieve relational parametricity: universal types, runtime type generation and cryptographic sealing. They show translations from the polymorphic blame calculus from [Ahmed et al. 2017] into the cryptographic lambda calculus and back that they show to be simulations. They also study a calculus \( \lambda _G \), obtained by removing the universal type \( {\color {orange}{\mathit {\star }}} \) and casts from the polymorphic blame calculus, but keeping runtime type generation. They show that embedding System F into \( \lambda _G \) is also fully abstract. Both of these full abstraction results tally with our observations: both System F and \( \lambda _G \) lack a universal type (making \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) degenerate) while both the polymorphic blame calculus and the cryptographic lambda calculus feature a universal type (making \( {{\color {#0C80CF}{\mathbf {{{\color {#0C80CF}{\mathbf {\underline{Univ}}}}} }}}} \) non-degenerate). As such, the embedding of \( \lambda _G \) into the polymorphic blame calculus will not be fully abstract, supplementing their results.

Xie et al. [2018] present a gradually typed language with parametric polymorphism, focusing on the interplay of gradual typing with the subtyping relation in the presence of implicit polymorphism. The result of their work is a source language that elaborates to \( \lambda _B \), which we discussed before. As such, the language provides the same form of parametricity than \( \lambda _B \) and we think our results apply to it as well.

More recently, Toro et al. [2019] proposed a new gradually typed calculus with explicit polymorphism, based on the AGT methodology by Garcia et al. [2016]. The methodology allows them to construct a system that satisfies the refined criteria by Siek et al. [2015], except for the Dynamic Gradual Guarantee. They show that this property is in conflict with parametricity in their system, but they demonstrate a weaker property which they do satisfy. The gradual type is also a universal type in their system and they prove a TWLR-based parametricity.

Finally, New et al. [2019a] have developed PolyG\( ^\nu \), the first gradual language to support both parametricity and the dynamic gradual guarantee (which they refer to as graduality) at the same time. The syntax of PolyG\( ^\nu \) departs from System F, requiring programmers to write explicit sealing and unsealing annotations. Like previous work, New et al. use dynamic sealing and they prove a form of parametricity based on a TWLR logical relation, although it is closer to standard System F logical relations in some other respects.

Universal types. Universal types have been studied by Longley [2003]. Our observation and proof that System F’s parametricity excludes a universal type is, to the best of our knowledge, novel.

Alternatives for full abstraction. The property of full abstraction was proposed by Abadi [1998]. Abate et al. [2019] provide a lattice of secure compilation criteria (dubbed robust compilation) that preserve classes of hyperproperties [Clarkson and Schneider 2010], i.e., arbitrary behaviours. The general nature of the framework makes it hard to make precise statements, but we believe our counterexamples would also disprove most of these alternative properties.

Skip 10CONCLUSION Section

10 CONCLUSION

This work started out years ago as an effort to prove Sumii and Pierce’s conjecture, discussed in section 5. Our failure to do so has perhaps proven more interesting than a success might have been. Specifically, we disprove the conjecture rather than proving it, we disprove another conjecture for languages with non-parametric parametricity and we identify what we see as an important problem in current parametrically polymorphic gradual languages: programmers reasoning about System F programs cannot trust contextual equivalences to remain valid in the gradually typed extended language. In addition to highlighting these problems, we discuss in Section 8 some ideas about how the issues might be solved. None of them seem easy to solve and the solutions we propose have downsides of their own, but we do believe they might be worth exploring further.

During the work on the Sumii-Pierce conjecture, we also gained some more high-level insights about variations of parametricity (type-world LRs versus lexically-scoped LRs) and their relation to the lexical scope of type variables and the existence of universal types. These insights were not mentioned explicitly in the previous version of this paper [Devriese et al. 2018] and in discussions with experts in the field, we found that these insights were unclear. For this reason, this paper focuses very clearly on these more high-level insights and we hope they may improve understanding of the issues involved.

Skip ACKNOWLEDGMENTS Section

ACKNOWLEDGMENTS

The authors thank Phil Wadler for interesting comments and suggestions.

Footnotes

  1. 1 In this paper we strive to reserve the term parametricity for the informal property that polymorphic functions must preserve relatedness of values of parametric types, following Strachey’s [Strachey 2000] and Reynolds’ [Reynolds 1983] use of the term. However, it is sometimes hard to formally draw the line between this restricted interpretation of parametricity and other properties (like purity or forms of type safety) that happen to be formulated together with the intuitive notion of parametricity in the Fundamental Theorem of Logical Relations for a specific logical relation. We will refer to this formal theorem as “a formulation of parametricity”. Because the line between (informal) parametricity and a formal formulation of it is not very clear, we are not always very strict about this distinction.

    Footnote
  2. 2 Other formal characterisations of secure compilation have been proposed more recently [Abate et al. 2019; Patrignani and Garg 2019; , 2017; Abate et al. 2018]. We discuss their relation to our work in section 9.

    Footnote
  3. 3 This is related to the notion that fully abstract compilation can also be used to reason about language expressiveness in general, beyond just language security (which is what is done in the case of secure compilation) [Parrow 2008; Mitchell 1993; Felleisen 1991].

    Footnote
  4. 4 This seems to imply non-lexical scoping of type variables, so it suffices for our results. Ultimately, we think that the non-lexical scope of type variables is the more fundamental characteristic of the systems we are interested in.

    Footnote
  5. 5 The term universal type was introduced by Longley [2003] based on a similarity to universal objects in category theory and related terms have been used in the literature [New et al. 2016a]. As mentioned before, the term universal type should be clearly distinguished from universally-quantified types, i.e., types of the form \( \forall X\ldotp \tau \).

    Footnote
  6. 6 Unlike the previous two, this was not an existing conjecture we debunk.

    Footnote
  7. 7 We will continue to use words like relation, related etc. despite the fact that they are unary.

    Footnote
  8. 8 For lack of a better name, we call this lemma as in Dreyer et al. [2011b]’s lecture notes. Neis et al. [2011] call this the irrelevance lemma.

    Footnote
  9. 9 Obviously, the situation is entirely different if we swap the quantifications in the type: \( {{\color {#0C80CF}{\mathbf {\underline{Triv}}}}} \mathrel {\overset{\text {def}}{=}}{{\color {#0C80CF}{\mathbf {\forall X \ldotp \exists Y\ldotp (X \rightarrow Y) \times (Y \rightarrow X)}}}} \).

    Footnote
  10. 10 For ease of discussion, we use this notation to give names to hypotheses as they become available during the proof and use the name later in the proof when we use the hypothesis.

    Footnote
  11. 11 The extra complexity in the typed version comes from the difficulty of erasing a polymorphic function to a simply typed language, and from the fact that the compiler protects all type variables in a separate pass rather than using a single pass for all type variables.

    Footnote
  12. 12 We are assuming a standard desugaring of let expressions to function applications.

    Footnote
  13. 13 A claim that was indeed true, since much of the research in proof techniques for fully abstract compilation postdates that paper [Abate et al. 2019; Ahmed and Blume 2011; Devriese et al. 2016; Fournet et al. 2013; New et al. 2016b; Patrignani and Garg 2019; Schmidt-Schauß et al. 2015]. An exception is the work by Ahmed and Blume [2008] on typed closure conversion.

    Footnote
  14. 14 As mentioned, to the best of our knowledge this is not an existing conjecture that we disprove.

    Footnote
  15. 15 Available at http://www.ccs.neu.edu/home/dijamner/paramblame/artifact/.

    Footnote
  16. 16 Thanks to Jeremy Siek and others, for their kind support in doing this.

    Footnote
  17. 17 They call this sealing, but since their seals have no run-time representation, we prefer the term run-time type generation.

    Footnote

REFERENCES

  1. Abadi Martín. 1998. Protection in programming-language translations. In ICALP’98. 868883.Google ScholarGoogle Scholar
  2. Abadi Martín, Cardelli Luca, Pierce Benjamin, and Plotkin Gordon. 1991. Dynamic typing in a statically typed language. ACM Trans. Program. Lang. Syst.w 13, 2 (April 1991), 237268. Google ScholarGoogle ScholarDigital LibraryDigital Library
  3. Abadi Martín, Cardelli Luca, Pierce Benjamin, and Rémy Didier. 1995. Dynamic typing in polymorphic languages. Journal of Functional Programming 5 (1995), 92103.Google ScholarGoogle ScholarCross RefCross Ref
  4. Abadi Martín, Fournet Cédric, and Gonthier Georges. 1998. Secure implementation of channel abstractions. In IEEE Symposium on Logic in Computer Science. 105116.Google ScholarGoogle Scholar
  5. Abadi Martín, Fournet Cédric, and Gonthier Georges. 1999. Secure communications processing for distributed languages. In IEEE Symposium on Security and Privacy. 7488.Google ScholarGoogle Scholar
  6. Abadi Martín, Fournet Cédric, and Gonthier Georges. 2000. Authentication primitives and their compilation. In Principles of Programming Languages. ACM, 302315. Google ScholarGoogle ScholarDigital LibraryDigital Library
  7. Abadi Martín and Plotkin Gordon D.. 2012. On protection by layout randomization. ACM Transactions on Information and System Security 15, Article 8 (July 2012), 8:1–8:29 pages. Google ScholarGoogle ScholarDigital LibraryDigital Library
  8. Abate Carmine, Amorim Arthur Azevedo de, Blanco Roberto, Evans Ana Nora, Fachini Guglielmo, Hritcu Catalin, Laurent Théo, Pierce Benjamin C., Stronati Marco, and Tolmach Andrew. 2018. When good components go bad: Formally secure compilation despite dynamic compromise(CCS’18).Google ScholarGoogle Scholar
  9. Abate Carmine, Blanco Roberto, Garg Deepak, Patrignani Marco Hriţcu, Cătălin, and Thibault Jérémy. 2019. Journey beyond full abstraction: Exploring robust property preservation for secure compilation. In 2019 IEEE 32nd Computer Security Foundations Symposium (CSF’2019).Google ScholarGoogle Scholar
  10. Agten Pieter, Strackx Raoul, Jacobs Bart, and Piessens Frank. 2012. Secure compilation to modern processors. In Computer Security Foundations Symposium. IEEE, 171185. Google ScholarGoogle ScholarDigital LibraryDigital Library
  11. Ahmed Amal. 2004. Semantics of Types for Mutable State. Ph.D. Dissertation. USA. AAI3136691.Google ScholarGoogle ScholarDigital LibraryDigital Library
  12. Ahmed Amal and Blume Matthias. 2008. Typed closure conversion preserves observational equivalence. In International Conference on Functional Programming. ACM, 157168. Google ScholarGoogle ScholarDigital LibraryDigital Library
  13. Ahmed Amal and Blume Matthias. 2011. An equivalence-preserving CPS translation via multi-language semantics. In Proceedings of the 16th ACM SIGPLAN International Conference on Functional Programming (ICFP’11). ACM, 431444. Google ScholarGoogle ScholarDigital LibraryDigital Library
  14. Ahmed Amal, Dreyer Derek, and Rossberg Andreas. 2009. State-dependent representation independence. In Principles of Programming Languages. ACM, 340353. Google ScholarGoogle ScholarDigital LibraryDigital Library
  15. Ahmed Amal, Findler Robert Bruce, Siek Jeremy G., and Wadler Philip. 2011a. Blame for all. In Principles of Programming Languages. 201214.Google ScholarGoogle Scholar
  16. Ahmed Amal, Findler Robert Bruce, Siek Jeremy G., and Wadler Philip. 2011b. Blame for All. Technical Report. https://plt.eecs.northwestern.edu/blame-for-all/.Google ScholarGoogle ScholarDigital LibraryDigital Library
  17. Ahmed Amal, Jamner Dustin, Siek Jeremy G., and Wadler Philip. 2017. Theorems for free for free: Parametricity, with and without types. Proceedings of the ACM on Programming Languages 1, ICFP (Aug. 2017), 39:1–39:28. Google ScholarGoogle ScholarDigital LibraryDigital Library
  18. Ahmed Amal, Kuper Lindsey, and Matthews Jacob. 2011. Parametric Polymorphism Through Run-time Sealing, or, Theorems for Low, Low Prices! (April 2011). http://www.ccs.neu.edu/home/amal/papers/paramseal-tr.pdf.Google ScholarGoogle Scholar
  19. Ahmed Amal, Matthews Jacob, Findler Robert Bruce, and Wadler Philip. 2009. Blame for all. In Workshop on Script-to-Program Evolution (STOP). 113.Google ScholarGoogle Scholar
  20. Atkey Robert, Ghani Neil, and Johann Patricia. 2014. A relationally parametric model of dependent type theory. In Principles of Programming Languages. ACM, 503515. Google ScholarGoogle ScholarDigital LibraryDigital Library
  21. Bugliesi Michele and Giunti Marco. 2007. Secure implementations of typed channel abstractions. In Principles of Programming Languages. ACM, 251262. Google ScholarGoogle ScholarDigital LibraryDigital Library
  22. Cimini Matteo and Siek Jeremy G.. 2016. The gradualizer: A methodology and algorithm for generating gradual type systems. In Principles of Programming Languages. ACM. Google ScholarGoogle ScholarDigital LibraryDigital Library
  23. Clarkson Michael R. and Schneider Fred B.. 2010. Hyperproperties. J. Comput. Secur. 18, 6 (Sept. 2010), 11571210.Google ScholarGoogle ScholarCross RefCross Ref
  24. Amorim Arthur Azevedo de, Fredrikson Matt, and Jia Limin. 2020. Reconciling noninterference and gradual typing. In LICS’20: 35th Annual ACM/IEEE Symposium on Logic in Computer Science, Saarbrücken, Germany, July 8-11, 2020, Hermanns Holger, Zhang Lijun, Kobayashi Naoki, and Miller Dale (Eds.). ACM, 116129. Google ScholarGoogle ScholarDigital LibraryDigital Library
  25. Devriese Dominique, Patrignani Marco, and Piessens Frank. 2016. Fully-abstract compilation by approximate back-translation. In Principles of Programming Languages. 164177.Google ScholarGoogle Scholar
  26. Devriese Dominique, Patrignani Marco, and Piessens Frank. 2018. Parametricity versus the Universal Type. In Proceedings of the 45th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, POPL 2018, Los Angeles, CA, USA, 2016.Google ScholarGoogle ScholarDigital LibraryDigital Library
  27. Devriese Dominique, Patrignani Marco, Piessens Frank, and Keuchel Steven. 2017. Modular, fully-abstract compilation by approximate back-translation. Logical Methods in Computer Science 13, 4 lmcs:4011 (Oct. 2017). arxiv:cs.PL/1703.09988.Google ScholarGoogle ScholarCross RefCross Ref
  28. Dreyer Derek, Ahmed Amal, and Birkedal Lars. 2011a. Logical step-indexed logical relations. Logical Methods in Computer Science 7, 2 (2011).Google ScholarGoogle ScholarCross RefCross Ref
  29. Dreyer Derek, Jung Ralf, Kaiser Jan-Oliver, Dang Hoang-Hai, and Swasey David. 2011b. Semantics of Type Systems Lecture Notes. (2011). Available at https://plv.mpi-sws.org/semantics/2017/lecturenotes.pdf.Google ScholarGoogle Scholar
  30. Dreyer Derek, Neis Georg, and Birkedal Lars. 2010. The impact of higher-order state and control effects on local relational reasoning. In International Conference on Functional Programming. ACM, 143156. Google ScholarGoogle ScholarDigital LibraryDigital Library
  31. Felleisen Matthias. 1991. On the expressive power of programming languages. In Selected Papers from the Symposium on 3rd European Symposium on Programming (ESOP’90). Elsevier North-Holland, Inc., New York, NY, USA, 3575.Google ScholarGoogle Scholar
  32. Findler Robert Bruce and Felleisen Matthias. 2002. Contracts for higher-order functions. In International Conference on Functional Programming. ACM. Google ScholarGoogle ScholarDigital LibraryDigital Library
  33. Fournet Cedric, Swamy Nikhil, Chen Juan, Dagand Pierre-Evariste, Strub Pierre-Yves, and Livshits Benjamin. 2013. Fully abstract compilation to JavaScript. In Principles of Programming Languages. ACM, 371384. Google ScholarGoogle ScholarDigital LibraryDigital Library
  34. Garcia Ronald, Clark Alison M., and Tanter Éric. 2016. Abstracting gradual typing. In Principles of Programming Languages. ACM. Google ScholarGoogle ScholarDigital LibraryDigital Library
  35. Garcia Ronald and Tanter Éric. 2020. Gradual Typing as if Types Mattered. (2020). https://wgt20.irif.fr/wgt20-final28-acmpaginated.pdf. Workshop on Gradual Typing.Google ScholarGoogle Scholar
  36. Girard Jean-Yves. 1972. Interprétation Fonctionelle et Élimination Des Coupures de l’arithmétique d’ordre Supérieur. Ph.D. Dissertation. Université Paris VII.Google ScholarGoogle Scholar
  37. Guha Arjun, Matthews Jacob, Findler Robert Bruce, and Krishnamurthi Shriram. 2007. Relationally-parametric polymorphic contracts. In Symposium on Dynamic Languages. ACM. Google ScholarGoogle ScholarDigital LibraryDigital Library
  38. Henglein Fritz. 1994. Dynamic typing: Syntax and proof theory. Science of Computer Programming 22, 3 (June 1994), 197230. Google ScholarGoogle ScholarDigital LibraryDigital Library
  39. Igarashi Yuu, Sekiyama Taro, and Igarashi Atsushi. 2017. On polymorphic gradual typing. In International Conference on Functional Programming. ACM.Google ScholarGoogle ScholarDigital LibraryDigital Library
  40. Jacobs Koen, Timany Amin, and Devriese Dominique. 2021. Fully abstract from static to gradual. Proceedings of the ACM on Programming Languages 5, POPL (Jan. 2021), 7:1–7:30. Google ScholarGoogle ScholarDigital LibraryDigital Library
  41. Jagadeesan Radha, Pitcher Corin, Rathke Julian, and Riely James. 2011. Local memory via layout randomization. In Computer Security Foundations Symposium. IEEE Computer Society, 161174. Google ScholarGoogle ScholarDigital LibraryDigital Library
  42. Juglaret Yannis, Hriţcu Cătălin, Amorim Arthur Azevedo de, and Pierce Benjamin C.. 2016. Beyond good and evil: Formalizing the security guarantees of compartmentalizing compilation. In Computer Security Foundations Symposium.Google ScholarGoogle Scholar
  43. Juglaret Yannis, Hritcu Catalin, Amorim Arthur Azevedo de, Pierce Benjamin C., Spector-Zabusky Antal, and Tolmach Andrew. 2015. Towards a fully abstract compiler using micro-policies: Secure compilation for mutually distrustful components. CoRR abs/1510.00697 (2015). http://arxiv.org/abs/1510.00697.Google ScholarGoogle Scholar
  44. Labrada Elizabeth, Toro Matías, Tanter Ãric, and Devriese Dominique. 2022. Plausible sealing for gradual parametricity. Proceedings of the ACM on Programming Languages 7, OOPSLA (2022). To appear.Google ScholarGoogle Scholar
  45. Larmuseau Adriaan, Patrignani Marco, and Clarke Dave. 2015. A secure compiler for ML modules. In Programming Languages and Systems - 13th Asian Symposium. 2948. Google ScholarGoogle ScholarCross RefCross Ref
  46. Larmuseau Adriaan, Patrignani Marco, and Clarke Dave. 2016. Implementing a secure abstract machine. In Symposium on Applied Computing. ACM, 20412048. Google ScholarGoogle ScholarDigital LibraryDigital Library
  47. Longley John R.. 2003. Universal types and what they are good for. In Domain Theory, Logic and Computation. Springer, Dordrecht, 2563. Google ScholarGoogle ScholarCross RefCross Ref
  48. Matthews Jacob and Ahmed Amal. 2008. Parametric polymorphism through run-time sealing or, theorems for low, low prices!LNCS, Vol. 4960. 1631.Google ScholarGoogle Scholar
  49. Matthews Jacob and Findler Robert Bruce. 2009. Operational semantics for multi-language programs. ACM Trans. Program. Lang. Syst. 31, 3 (April 2009), 12:1–12:44. Google ScholarGoogle ScholarDigital LibraryDigital Library
  50. Mitchell John C.. 1986. Representation independence and data abstraction. In Proceedings of the 13th ACM SIGACT-SIGPLAN Symposium on Principles of Programming Languages (POPL’86). ACM, New York, NY, USA, 263276. Google ScholarGoogle ScholarDigital LibraryDigital Library
  51. Mitchell John C.. 1993. On abstraction and the expressive power of programming languages. Science of Computer Programming 21, 2 (1993), 141163.Google ScholarGoogle ScholarDigital LibraryDigital Library
  52. Jr. James H. Morris,1973a. Protection in programming languages. Commun. ACM 16, 1 (Jan. 1973), 1521. Google ScholarGoogle ScholarDigital LibraryDigital Library
  53. Jr. James H. Morris,1973b. Types are not sets. In Principles of Programming Languages. 120124.Google ScholarGoogle Scholar
  54. Neis Georg, Dreyer Derek, and Rossberg Andreas. 2009. Non-parametric parametricity. In ICFP’09. 135148.Google ScholarGoogle ScholarDigital LibraryDigital Library
  55. Neis Georg, Dreyer Derek, and Rossberg Andreas. 2011. Non-parametric parametricity. Journal of Functional Programming 21 (2011), 497562.Google ScholarGoogle ScholarDigital LibraryDigital Library
  56. New Max, Bowman William J., and Ahmed Amal. 2016a. Fully abstract compilation via universal embedding. In ICFP’16.Google ScholarGoogle Scholar
  57. New Max S., Bowman William J., and Ahmed Amal. 2016b. Fully abstract compilation via universal embedding. In International Conference on Functional Programming. ACM, 103116. Google ScholarGoogle ScholarDigital LibraryDigital Library
  58. New Max S., Jamner Dustin, and Ahmed Amal. 2019a. Graduality and parametricity: Together again for the first time. Proceedings of the ACM on Programming Languages 4, POPL (Dec. 2019), 46:1–46:32. Google ScholarGoogle ScholarDigital LibraryDigital Library
  59. New Max S., Licata Daniel R., and Ahmed Amal. 2019b. Gradual type theory. Proc. ACM Program. Lang. 3, POPL (2019), 15:1–15:31. Google ScholarGoogle ScholarDigital LibraryDigital Library
  60. Parrow Joachim. 2008. Expressiveness of process algebras. Elec. Not. Theo. Comp. Sci. 209, 0 (2008), 173186.Google ScholarGoogle ScholarDigital LibraryDigital Library
  61. Patrignani Marco. 2020. Why Should Anyone use Colours? Or, syntax highlighting beyond code snippets. CoRR abs/2001.11334. (2020).Google ScholarGoogle Scholar
  62. Patrignani Marco, Agten Pieter, Strackx Raoul, Jacobs Bart, Clarke Dave, and Piessens Frank. 2015. Secure compilation to protected module architectures. ACM Trans. Program. Lang. Syst. 37, Article 6 (April 2015), 6:1–6:50 pages. Google ScholarGoogle ScholarDigital LibraryDigital Library
  63. Patrignani Marco, Ahmed Amal, and Clarke Dave. 2019. Formal approaches to secure compilation a survey of fully abstract compilation and related work. ACM Comput. Surv. 51, 6, Article 125 (Jan. 2019), 36 pages.Google ScholarGoogle ScholarDigital LibraryDigital Library
  64. Patrignani Marco, Devriese Dominique, and Piessens Frank. 2016. On modular and fully abstract compilation. In Computer Security Foundations Symposium.Google ScholarGoogle Scholar
  65. Patrignani Marco and Garg Deepak. 2017. Secure compilation and hyperproperties preservation. In Proceedings of the 30th IEEE Computer Security Foundations Symposium CSF 2017, Santa Barbara, USA (CSF’2017).Google ScholarGoogle ScholarCross RefCross Ref
  66. Patrignani Marco and Garg Deepak. 2019. Robustly safe compilation. In Programming Languages and Systems - 28th European Symposium on Programming, ESOP 2019 (ESOP’19).Google ScholarGoogle Scholar
  67. Pierce Benjamin. 2002. Types and Programming Languages. MIT Press.Google ScholarGoogle ScholarDigital LibraryDigital Library
  68. Pierce Benjamin and Sumii Eijiro. 2000. Relating cryptography and polymorphism. (2000). http://www.kb.ecei.tohoku.ac.jp/sumii/pub/infohide.pdf.Google ScholarGoogle Scholar
  69. Pitts Andrew M.. 1998. Existential types: Logical relations and operational equivalence. In Automata, Languages and Programming (Lecture Notes in Computer Science), Larsen Kim G., Skyum Sven, and Winskel Glynn (Eds.). Springer, Berlin, 309326. Google ScholarGoogle ScholarCross RefCross Ref
  70. Plotkin Gordon D.. 1977. LCF considered as a programming language. Theoretical Computer Science 5 (1977), 223255.Google ScholarGoogle ScholarCross RefCross Ref
  71. Reynolds John C.. 1974. Towards a theory of type structure. In Programming Symposium. Lecture Notes in Computer Science, Vol. 19. Springer-Verlag, 408423.Google ScholarGoogle ScholarDigital LibraryDigital Library
  72. Reynolds John C.. 1983. Types, abstraction, and parametric polymorphism. In Information Processing. North Holland, 513523.Google ScholarGoogle Scholar
  73. Rossberg Andreas. 2003. Generativity and dynamic opacity for abstract types. In Proceedings of the 5th ACM SIGPLAN International Conference on Principles and Practice of Declaritive Programming (PPDP’03). ACM, New York, NY, USA, 241252. Google ScholarGoogle ScholarDigital LibraryDigital Library
  74. Schmidt-Schauß Manfred, Sabel David, Niehren Joachim, and Schwinghammer Jan. 2015. Observational program calculi and the correctness of translations. Theoretical Computer Science 577 (2015), 98124. Google ScholarGoogle ScholarDigital LibraryDigital Library
  75. Siek Jeremy and Wadler Philip. 2016. The key to blame: Gradual typing meets cryptography. (2016). http://homepages.inf.ed.ac.uk/wadler/papers/blame-key/blame-key.pdf.Google ScholarGoogle Scholar
  76. Siek Jeremy G. and Taha Walid. 2006. Gradual typing for functional languages. In SCHEME. 8192.Google ScholarGoogle Scholar
  77. Siek Jeremy G., Vitousek Michael M., Cimini Matteo, and Boyland John Tang. 2015. Refined criteria for gradual typing. In Summit on Advances in Programming Languages (Leibniz International Proceedings in Informatics (LIPIcs)), Vol. 32. Schloss Dagstuhl-Leibniz-Zentrum für Informatik, Dagstuhl, Germany, 274293. Google ScholarGoogle ScholarCross RefCross Ref
  78. Statman Richard. 1991. A Local Translation of Untyped [lambda] Calculus into Simply Typed [lambda] Calculus. Technical Report. http://repository.cmu.edu/cgi/viewcontent.cgi?article=1454&context=math.Google ScholarGoogle Scholar
  79. Strachey Christopher. 2000. Fundamental concepts in programming languages. Higher-Order and Symbolic Computation 13, 1-2 (April 2000), 1149. Google ScholarGoogle ScholarDigital LibraryDigital Library
  80. Sumii Eijiro and Pierce Benjamin C.. 2003. Logical relations for encryption. J. Comput. Secur. 11, 4 (July 2003), 521554.Google ScholarGoogle ScholarDigital LibraryDigital Library
  81. Sumii Eijiro and Pierce Benjamin C.. 2004. A bisimulation for dynamic sealing. In Principles of Programming Languages. 161172.Google ScholarGoogle Scholar
  82. Takikawa Asumu, Feltey Daniel, Greenman Ben, New Max S., Vitek Jan, and Felleisen Matthias. 2016. Is sound gradual typing dead? In Principles of Programming Languages. ACM. Google ScholarGoogle ScholarDigital LibraryDigital Library
  83. Tobin-Hochstadt Sam and Felleisen Matthias. 2006. Interlanguage migration: From scripts to programs. In Companion to the 21st ACM SIGPLAN Symposium on Object-Oriented Programming Systems, Languages, and Applications (OOPSLA’06). Association for Computing Machinery, New York, NY, USA, 964974. Google ScholarGoogle ScholarDigital LibraryDigital Library
  84. Toro Matías, Garcia Ronald, and Tanter Éric. 2018. Type-driven gradual security with references. ACM Trans. Program. Lang. Syst. 40, 4 (2018), 16:1–16:55. Google ScholarGoogle ScholarDigital LibraryDigital Library
  85. Toro Matías, Labrada Elizabeth, and Tanter Éric. 2019. Gradual parametricity, revisited. Proc. ACM Program. Lang. 3, POPL (Jan. 2019), 17:1–17:30. Google ScholarGoogle ScholarDigital LibraryDigital Library
  86. Wadler Philip. 1989. Theorems for free!. In Functional Programming Languages and Computer Architecture. ACM, 347359.Google ScholarGoogle Scholar
  87. Wadler Philip. 2007. The Girard-Reynolds isomorphism (second edition). Theoretical Computer Science 375, 1 (2007). Google ScholarGoogle ScholarDigital LibraryDigital Library
  88. Wadler Philip and Findler Robert Bruce. 2009. Well-typed programs can’t be blamed. In Programming Languages and Systems. Springer, Berlin, 116. Google ScholarGoogle ScholarDigital LibraryDigital Library
  89. Watson Robert N. M., Woodruff Jonathan, Neumann Peter G., Moore Simon W., Anderson Jonathan, Chisnall David, Dave Nirav H., Davis Brooks, Gudka Khilan, Laurie Ben, Murdoch Steven J., Norton Robert M., Roe Michael, Son Stacey D., and Vadera Munraj. 2015. CHERI: A hybrid capability-system architecture for scalable software compartmentalization. In IEEE Symposium on Security and Privacy. Google ScholarGoogle ScholarDigital LibraryDigital Library
  90. Wright Andrew K.. 1995. Simple imperative polymorphism. LISP and Symbolic Computation 8, 4 (Dec. 1995), 343355. Google ScholarGoogle ScholarDigital LibraryDigital Library
  91. Xie Ningning, Bi Xuan, and Oliveira Bruno C. d. S.. 2018. Consistent subtyping for all. In Programming Languages and Systems (Lecture Notes in Computer Science), Ahmed Amal (Ed.). Springer International Publishing, 330.Google ScholarGoogle Scholar

Index Terms

  1. Two Parametricities Versus Three Universal Types

        Recommendations

        Comments

        Login options

        Check if you have access through your login credentials or your institution to get full access on this article.

        Sign in

        Full Access

        • Published in

          cover image ACM Transactions on Programming Languages and Systems
          ACM Transactions on Programming Languages and Systems  Volume 44, Issue 4
          December 2022
          378 pages
          ISSN:0164-0925
          EISSN:1558-4593
          DOI:10.1145/3551655
          • Editor:
          • Jan Vitek
          Issue’s Table of Contents

          Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted. To copy otherwise, or republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Request permissions from [email protected].

          Publisher

          Association for Computing Machinery

          New York, NY, United States

          Publication History

          • Published: 21 September 2022
          • Accepted: 13 May 2022
          • Revised: 20 April 2022
          • Received: 15 October 2020
          Published in toplas Volume 44, Issue 4

          Permissions

          Request permissions about this article.

          Request Permissions

          Check for updates

          Qualifiers

          • research-article
          • Refereed

        PDF Format

        View or Download as a PDF file.

        PDF

        eReader

        View online with eReader.

        eReader

        HTML Format

        View this article in HTML Format .

        View HTML Format
        About Cookies On This Site

        We use cookies to ensure that we give you the best experience on our website.

        Learn more

        Got it!