Abstract
Shared session types generalize the CurryHoward correspondence between intuitionistic linear logic and the sessiontyped \(\pi \)calculus with adjoint modalities that mediate between linear and shared session types, giving rise to a programming model where shared channels must be used according to a locking discipline of acquirerelease. While this generalization greatly increases the range of programs that can be written, the gain in expressiveness comes at the cost of deadlockfreedom, a property which holds for many linear session type systems. In this paper, we develop a type system for logicallyshared sessions in which types capture not only the interactive behavior of processes but also constrain the order of resources (i.e., shared processes) they may acquire. This typelevel information is then used to rule out cyclic dependencies among acquires and synchronization points, resulting in a system that ensures deadlockfree communication for welltyped processes in the presence of shared sessions, higherorder channel passing, and recursive processes. We illustrate our approach on a series of examples, showing that it rules out deadlocks in circular networks of both shared and linear recursive processes, while still being permissive enough to type concurrent implementations of shared imperative data structures as processes.
Keywords
 Linear and shared session types
 Deadlockfreedom
Supported by NSF Grant No. CCF1718267: “Enriching Session Types for Practical Concurrent Programming” and NOVA LINCS (Ref. UID/CEC/04516/2019).
Download conference paper PDF
1 Introduction
Session types [25,26,27] naturally describe the interaction protocols that arise amongst concurrent processes that communicate via messagepassing. This typing discipline has been integrated (with varying static safety guarantees) into several mainstream language such as Java [28, 29], F# [43], Scala [49, 50], Go [11] and Rust [33]. Session types moreover enjoy a logical correspondence between linear logic and the sessiontyped \(\pi \)calculus [8, 9, 51, 55]. Languages building on this correspondence [24, 52, 55] not only guarantee session fidelity (i.e., type preservation) but also deadlockfreedom (i.e., global progress). The latter is guaranteed even in the presence of interleaved sessions, which are often excluded from the deadlockfree fragments of traditional sessiontyped frameworks [20, 26, 27, 53]. These logical session types, however, exclude programming scenarios that demand sharing of mutable resources (e.g., shared databases or shared output devices) instead of functional resource replication.
To increase their practicality, logical session types have been extended with manifest sharing [2]. In the resulting language, linear and shared sessions coexist, but the type system enforces that clients of shared sessions run in mutual exclusion of each other. This separation is achieved by enforcing an acquirerelease policy, where a client of a shared session must first acquire the session before it can participate in it along a private linear channel. Conversely, when a client releases a session, it gives up its linear channel and only retains a shared reference to the session. Thus, sessions in the presence of manifest sharing can change, or shift, between shared and linear execution modes. At the typelevel, the acquirerelease policy manifests in a stratification of session types into linear and shared with adjoint modalities [5, 47, 48], connecting the two strata. Operationally, the modality shifting up from the linear to the shared layer translates into an acquire and the one shifting down from shared to linear into a release.
Manifest sharing greatly increases the range of programs that can be written because it recovers the expressiveness of the untyped asynchronous \(\pi \)calculus [3] while maintaining session fidelity. As in the \(\pi \)calculus, however, the gain in expressiveness comes at the cost of deadlockfreedom. An illustrative example is an implementation of the classical dining philosophers problem, shown in Fig. 1, using the language \(\mathsf {SILL}_{\mathsf {S}}\) [2] that supports manifest sharing (in this setting we often equate a process with the session it offers along a distinguished channel). The code shows the process \( fork\_proc \), implementing a session of type \(\mathsf {sfork}\), and the processes \( thinking \) and \( eating \), implementing sessions of type \(\mathsf {philosopher}\). We defer the details of the typing and the definition of the session types \(\mathsf {sfork}\) and \(\mathsf {philosopher}\) to Sect. 2 and focus on the programmatic working of the processes for now. For ease of reading, we typeset shared session types and variables denoting shared channel references in .
A \( fork\_proc \) process represents a fork that can be perpetually acquired and released. The actions \(\mathsf {accept}\) and \(\mathsf {detach}\) are the duals of \(\mathsf {acquire}\) and \(\mathsf {release}\), respectively, allowing a process to accept an acquire by a client and to initiate a release by a client, respectively. Process \(\mathsf {thinking}\) has two shared channel references as arguments, for the forks to the left and right of the philosopher, which the process tries to acquire. If the acquire succeeds, the process recurs as an \(\mathsf {eating}\) philosopher with two (now) linear channel references of type \(\mathsf {lfork}\). Once a philosopher is done eating, it releases both forks and recurs as a \(\mathsf {thinking}\) philosopher. Let’s set a table for three philosopher that share three forks, all spawned as processes executing in parallel:
Infamously, this configuration may deadlock because of the circular dependency between the acquires. We can break this cycle by changing the last line to , ensuring that forks are acquired in increasing order.
Perhaps surprisingly, cyclic dependencies between acquire requests are not the only source of deadlocks. Fig. 2 gives an example, defining the processes \( owner \) and \( contester \), which both have a shared channel reference to a common resource that can be perpetually acquired and released. Both processes acquire the shared resource, but additionally exchange the message \(\mathsf {ping}\). More precisely, process \( owner \) spawns the process \( contester \), acquires the shared resource, and only releases the resource after having received the message \(\mathsf {ping}\) from the \( contester \). Process \( contester \), on the other hand, first attempts to acquire the resource and then sends the message \( ping \) to the owner. The program deadlocks if process \( owner \) acquires the resource first. In that case, process \( owner \) waits for process \( contester \) to send the message \(\mathsf {ping}\) while process \( contester \) waits to acquire the resource held by process \( owner \). We note that this deadlock arises in both synchronous and asynchronous semantics.
In this paper, we develop a type system for manifest sharing that rules out cycles between acquire requests and interdependencies between acquire requests and synchronization actions, detecting the two kinds of deadlocks explained above. In our type system, session types not only prescribe when resources must be acquired and released, but also the range of resources that may be acquired. To this end, we equip the type system with the notion of a world, an abstract value at which a process resides, and type processes relative to an acyclic ordering on worlds, akin to the partialorder based approaches of [34, 37]. The contributions of this paper are:

a characterization of the possible forms of deadlocks that can arise in shared session types;

the introduction of manifest deadlockfreedom, where resource dependencies are manifest in the type structure via world modalities;

its elaboration in the programming language \(\mathsf {SILL}_{\mathsf {S}^+}\), resulting in a type system, a synchronous operational semantics, and proofs of session fidelity (preservation) and a strong form of progress that excludes all deadlocks;

the novel abstraction of green and red arrows to reason about the interdependencies between processes;

an illustration of the concepts on various examples, including an extensive comparison with related work.
This paper is structured as follows: Sect. 2 provides a short introduction to manifest sharing. Sect. 3 develops the type system and dynamics of the language \(\mathsf {SILL}_{\mathsf {S}^+}\). Sect. 4 illustrates the introduced concepts on an extended example. Sect. 5 discusses the metatheoretical properties of \(\mathsf {SILL}_{\mathsf {S}^+}\), emphasizing progress. Sect. 6 compares with examples of related work and identifies future work. Sect. 7 discusses related work, and Sect. 8 concludes this paper.
2 Manifest Sharing
In the previous section, we have already explored the programmatic workings of manifest sharing [2], which enforces an acquirerelease policy on shared channel references. In this section, we clarify the typing of shared processes.
A key contribution of manifest sharing is not only to support acquirerelease as a programming primitive but also to make it manifest in the type system. Generalizing the idea of type stratification [5, 47, 48], session types are partitioned into a linear and shared layer with two adjoint modalities connecting the layers:
In the linear layer, we get the standard connectives of intuitionistic linear logic (\( A _{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\otimes B _{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\), \( A _{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\multimap B _{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\), \(\oplus \{\overline{l:A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\}\), , and \(\mathbf {1}\)). These connectives are extended with the modal operator \({\downarrow }^{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}A_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\), shifting down from the shared to the linear layer. Similarly, in the shared layer, we have the operator \({\uparrow }^{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\), shifting up from the linear to the shared layer. The former translates into a release (and, dually, detach), the latter into an acquire (and, dually, accept). As a result, we obtain a system in which session types prescribe all forms of communication, including the acquisition and release of shared processes.
Table 1 provides an overview of \(\mathsf {SILL}_{\mathsf {S}}\)’s session types and their operational reading. Since \(\mathsf {SILL}_{\mathsf {S}}\) is based on an intuitionistic interpretation of linear logic session types [8], types are expressed from the point of view of the providing process with the channel along which the process provides the session behavior being characterized by its session type. This choice avoids the explicit duality operation present in original presentations of session types [25, 26] and in those based on classical linear logic [55]. Table 1 lists the points of view of the provider and client of a given connective in the first and second lines, respectively. Moreover, Table 1 gives for each connective its session type before and after the message exchange, along with their respective process terms. We can see that the process terms of a provider and a client for a given connective come in matching pairs, indicating that the participants’ views of the session change consistently. We use the subscripts \({\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\) and \({\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\) to distinguish between linear and shared channels, respectively.
We are now able to give the session types of the processes \( fork\_proc \), \( thinking \), and \( eating \) defined in the previous section:
The mutually recursive session types \(\mathsf {lfork}\) and \(\mathsf {sfork}\) represent a fork that can perpetually be acquired and released. We adopt an equirecursive [14] interpretation for recursive session types, silently equating a recursive type with its unfolding and requiring types to be contractive [19].
We briefly discuss the typing and the dynamics of acquirerelease. The typing and the dynamics of the residual linear connectives are standard, and we detail them in the context of \(\mathsf {SILL}_{\mathsf {S}^+}\) (see Sect. 3). As is usual for an intuitionistic interpretation, each connective gives rise to a left and a right rule, denoting the use and provision, respectively, of a session of the given type:
The typing judgments \(\varGamma \vdash P \; {:}\,\!{:} \; (x_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}: A_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}})\) and \(\varGamma ; \varDelta \vdash P \; {:}\,\!{:} \; (x_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}})\) indicate that process P provides a session of type A along channel x, given the typing of the channels specified in typing contexts \(\varGamma \) (and \(\varDelta \)). \(\varGamma \) and \(\varDelta \) consist of hypotheses on the typing of shared and linear channels, respectively, where \(\varGamma \) is a structural and \(\varDelta \) a linear context. To allow for recursive process definitions, the typing judgment depends on a signature \(\varSigma \) that is populated with all process definitions prior to typechecking. The adjoint formulation precludes shared processes from depending on linear channel references [2, 47], a restriction motivated from logic referred to as the independence principle [47]. Thus, when a shared session accepts an acquire and shifts to linear, it starts with an empty linear context.
Operationally, the dynamics of \(\mathsf {SILL}_{\mathsf {S}}\) is captured by multiset rewriting rules [12], which denote computation in terms of state transitions between configurations of processes. Multiset rewriting rules are local in that they only mention the parts of a configuration they rewrite. For acquirerelease we have the following:
Configuration states are defined by the predicates \(\mathsf {proc}( c_{ m } , \, P )\) and \(\mathsf {unavail}( a_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}} )\). The former denotes a running process with process term P providing along channel \(c_{ m }\), the latter acts as a placeholder for a shared process providing along channel \(a_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\) that is currently not available. The above rule exploits the invariant that a process’ providing channel a can appear at one of two modes, a linear one, \(a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\), and a shared one, \(a_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\). While the process (i.e. the session) is linear, it provides along \(a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\), while it is shared, along \(a_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\). When a process shifts between modes, it switches between the two modes of its offering channel. The channel at the appropriate mode is substituted for the variables occurring in process terms.
3 Manifest DeadlockFreedom
In this section, we introduce our language \(\mathsf {SILL}_{\mathsf {S}^+}\), a sessiontyped language that supports sharing without deadlock. We focus on \(\mathsf {SILL}_{\mathsf {S}^+}\)’s type system and dynamics in this section and discuss its metatheoretical properties in Sect. 5.
3.1 Competition and Collaboration
The introduction of acquirerelease, to ensure that the multiple clients of a shared process interact with the process in mutual exclusion from each other, gives rise to an obvious source of deadlocks, as acquirerelease effectively amounts to a locking discipline. The typical approach to prevent deadlocks in that case is to impose a partial order on the resources and to “lockup”, i.e., to lock the resources in ascending order. We adopted this strategy in Sect. 1 (Fig. 1) to break the cyclic dependencies among the acquires in the dining philosophers.
In Sect. 1, however, we also considered another example (Fig. 2) and discovered that cyclic acquisitions are not the only source of deadlocks, but deadlocks can also arise from interdependent acquisitions and synchronizations. In that example, we can prevent the deadlock by moving the acquire past the synchronization, in either of the two processes. Whereas in a purely linear sessiontyped system the sequencing of actions within a process do not affect other processes, the relative placement of acquire requests and synchronizations become relevant in a shared sessiontyped system.
Based on this observation, we can divide the processes in a sharedsession discipline into competitors and collaborators. The former compete for a set of resources, whereas the latter do not overlap in the set of resources they acquire. For example, in the dining philosophers (Fig. 1), the philosophers \( p_0 \), \( p_1 \), and \( p_2 \) compete with each other for the set of forks \( f_0 \), \( f_1 \), and \( f_2 \), whereas the process that spawns the philosophers and the forks collaborates with either of them.
Transferring this idea to the process graph that emerges at runtime, we note that competitors are siblings whereas collaborators stand in a parentdescendant relationship. We illustrate this outcome on Fig. 3 that shows a possible runtime process graph for the dining philosophers. Linear processes are depicted as solid black circles with a white identifier and shared processes are depicted as dotted filled violet circles with a black identifier. Linear channels are depicted as black lines, shared channel references as dotted violet lines with the arrow head pointing to the shared process being acquired^{Footnote 1}. The identifiers \(P_0\), \(P_1\), and \(P_2\) stand for the three philosophers, \(F_0\), \(F_1\), and \(F_2\) for the three forks, and T for the process that sets the table. The current runtime graph depicts the scenario in which \(P_1\) is eating, while the other two philosophers are still thinking.
Embedded in the graph is a tree that arises from the linear processes and the linear channels connecting them. For any two nodes in this tree, the parent node denotes the client process and the child node the providing process. We note that the independence principle (see Sect. 2), which precludes shared processes from depending on linear channel references, guarantees that there exists exactly one tree in the process graph, with the linear main process as its root. The shape of the tree changes when new processes are spawned, linear channels exchanged (through \(\otimes \) and \(\multimap \)), or shared processes acquired. For example, process \(P_2\) could acquire the shared fork \(F_0\), which then becomes a linear child process of \(P_2\), should the acquire succeed. As indicated by the shared channel references, the sibling nodes \(P_0\), \(P_1\), and \(P_2\) compete with each other for the nodes \(F_0\), \(F_1\), and \(F_2\), whereas the node T does not compete for any of the resources acquired by its descendants (including \(F_1\) and \(F_2\)). Our type system enforces this paradigm, as we discuss in the next section.
3.2 Type System
Invariants. Having identified the notions of collaborators and competitors, our type system must guarantee: (i) that collaborators acquire mutually disjoint sets of resources; (ii) that competitors employ a lockingup strategy for the resources they share; and, (iii) that competitors have released all acquired resources when synchronizing with other competitors. Invariant (ii) rules out cyclic acquisitions and invariants (i) and (iii) combined rule out interdependent acquisitions and synchronizations.
To express the highlevel invariants above in our type system, we introduce the notion of a world – an abstract value that is equipped with a partial order – and associate such a world with every process. Programmers can create worlds, indicate the world at which a process resides at spawn time, and define an order on worlds. Moreover, we associate with each process a range of worlds that indicates the worlds of resources that the process may acquire. As a result, we obtain the following typing judgments:
The typing judgments reveal that we impose worlds at the judgmental level, resulting in a hybrid system, in which the adjoint modalities for acquirerelease are complemented with world modalities that occur as syntactic objects in propositions [7]. We use the notation \(x_m : A_m [{\omega _k}\updownarrow ^{\omega _n}_{\omega _l}]\) (where m stands for \(\mathsf {S}\) or \(\mathsf {L}\)) to associate worlds \(\omega _k\), \(\omega _l\), and \(\omega _n\) with a process that offers a session of type \(A_m\) along channel x. World \(\omega _k\) denotes the world at which the process resides. We refer to this world as the self world. Worlds \(\omega _l\) and \(\omega _n\) indicate the range of worlds of resources that the process may acquire, with \(\omega _l\) denoting the minimal (min) world in this range and \(\omega _n\) the maximal (max) one.
Process terms are typed relative to the order specified in \(\varPsi \) and the contexts \(\varGamma \), \(\varPhi \), and \(\varDelta \). As in Sect. 2, \(\varGamma \) is a structural context consisting of hypotheses on the typing of variables bound to shared channel references, augmented with world annotations. We find it necessary to split the linear context “\(\varDelta \)” from Sect. 2 into the two disjoint contexts \(\varPhi \) and \(\varDelta \), allowing us to separate channels that are possibly aliased (due to sharing) from those that are not, respectively. Both \(\varPhi \) and \(\varDelta \) consist of hypotheses on the typing of variables that are bound to linear channels, augmented with world annotations. \(\varPsi \) is presupposed to be acyclic and defined as: \( \varPsi \,\triangleq \,\cdot \,\mid \,\varPsi ', \; \omega _{ k } < \omega _{ l } \,\mid \,\varPsi ', \; \omega _{ o } \), where \(\omega \) stands for a concrete world \(\mathsf {w}\) or a world variable \(\delta \). We allow \(\varPsi \) to contain single worlds, to support singletons as well as to accommodate world creation prior to order declaration. We define the transitive closure \(\varPsi ^+\), yielding a strict partial order, and the reflexive transitive closure \(\varPsi ^*\), yielding a partial order.
The highlevel invariants (i), (ii), and (iii) identified earlier naturally transcribe into the following invariants, which we impose on the typing judgments above. We use the notation \(\_\langle x_m \rangle ; P\) to denote a process term that currently executes an action along channel \(x_m\).

1.
\(\mathsf {min}(\mathsf {parent}) \le \mathsf {self}(\mathsf {acquired\_child}) \le \mathsf {max}(\mathsf {parent})\):
\(\forall y_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: B_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\omega _o}\updownarrow ^{\omega _r}_{\omega _p}] \in \varPhi : \varPsi ^* \,\vdash \,\omega _l \le \omega _o \le \omega _n\)

2.
\(\mathsf {max}(\mathsf {parent}) < \mathsf {min}(\mathsf {child})\):
\(\forall y_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: B_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\omega _o}\updownarrow ^{\omega _r}_{\omega _p}] \in \varDelta \cup \varPhi : \varPsi ^+ \,\vdash \,\omega _n < \omega _p\)

3.
If \(\varPsi ; \, \varGamma , x_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}: {A}[{\omega _t}\updownarrow ^{\omega _v}_{\omega _u}]; \, \varPhi ; \, \varDelta \vdash x_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} \leftarrow \mathsf {acquire}\; x_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}; \, Q_{x_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}} \; {:}\,\!{:} \; (z_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: C_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\omega _k}\updownarrow ^{\omega _n}_{\omega _l}])\), then \(\forall y_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: B_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\omega _o}\updownarrow ^{\omega _r}_{\omega _p}] \in \varPhi : \varPsi ^+ \,\vdash \,\omega _o < \omega _t\).

4.
If \(\varPsi ; \, \varGamma ; \, \varPhi ; \, \varDelta \vdash \_\langle x_m \rangle ; P \; {:}\,\!{:} \; (x_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\omega _k}\updownarrow ^{\omega _n}_{\omega _l}])\), then \(\varPhi = (\cdot )\).
Invariants 1 and 2 ensure that, for any node in the tree, the acquired resources reside at smaller worlds than those acquired by any descendant. As a result, the two invariants guarantee highlevel invariant (i). Invariant 3, on the other hand, imposes a lockup strategy on acquires and thus guarantees highlevel invariant (ii). To guarantee highlevel invariant (iii), we impose Invariant 4, which forces a process to release any acquired resources before communicating along its offering channel. Since sibling nodes cannot be directly connected by a linear channel, the only way for them to synchronize is through a common parent. Finally, to guarantee that world annotations are internally consistent, we require for each annotation \([{\omega _k}\updownarrow ^{\omega _n}_{\omega _l}]\) that \(\omega _k < \omega _l \le \omega _n\).
Rules. We now present select process typing rules, a complete listing is provided in the companion technical report [4]. The only new rules with respect to the language \(\mathsf {SILL}_{\mathsf {S}}\) [2] are those pertaining to world creation and order determination. These are extralogical judgmental rules. We allow both linear and shared processes to create and relate worlds. Rules and create a new world \(\mathsf {w}\) and make it available to the continuation \(Q_{\mathsf {w}}\). Rules and relate two existing worlds, while preserving acyclicity of the order.
We now consider the typing rule for acquire, which must explicitly enforce the various lowlevel invariants above. Since an acquire results in the addition of a new child node to the executing process, the rule can interfere with Invariants 1 and 2. The first two premises of the rule ensure that the two invariants are preserved. Moreover, the rule has to ensure that the acquiring process is lockingup (Invariant 3), which is achieved by the third premise.
The remaining shift rules are actually unchanged with respect to \(\mathsf {SILL}_{\mathsf {S}}\), modulo the world annotations. In particular, lowlevel Invariant 4 is already satisfied because the conclusion of rule does not have a context \(\varPhi \) and because the independence principle forces \(\varPhi \) to be empty in rule .
We now consider the linear connectives, starting with \(\mathbf {1}\). Rule reveals that only processes that have never been acquired may be terminated. This restriction is important to guarantee progress because existing clients of a shared process may wait indefinitely otherwise. We impose the restriction as a wellformedness condition on a session type, giving rise to a strictly equisynchronizing session type. The notion of an equisynchronizing session type [2] has been defined for \(\mathsf {SILL}_{\mathsf {S}}\) and guarantees that a process that has been acquired at a type \(A_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\) is released back to the type \(A_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\), should it ever be released. A strictly equisynchronizing session type additionally requires that an acquired resource must be released. The corresponding rules can be found in [4]. Linearity enforces Invariant 4 in rule , making sure that no linear channels are left behind.
Next, we consider internal and external choice. Since internal and external choice cannot alter the linear process tree of a process graph, the rules are very similar to the ones in \(\mathsf {SILL}_{\mathsf {S}}\). The only differences are that we get two left rules for each connective and that the \(\varPhi \)context of each right rule must be empty to satisfy Invariant 4. The former is merely due to the tracking of possibly aliased sessions in the \(\varPhi \) context. We only list rules for internal choice, those for external choice are dual and can be found in [4].
More interesting are linear channel output and input, since these alter the linear process tree of a process graph. Moreover, additional world annotations are needed to indicate the worlds of the channel that is exchanged. For the latter we use the notation \(@{\omega _l}\updownarrow ^{\omega _r}_{\omega _p}\), indicating that the exchanged channel has the worlds \(\omega _l\), \(\omega _p\), and \(\omega _r\) for \(\mathsf {self}\), \(\mathsf {min}\), and \(\mathsf {max}\), respectively. To account for induced changes in the process graph, the rules that type an input of a linear channel must guard against any disturbance of Invariants 1 and 2. Because the two invariants guarantee that parents do not overlap with their descendants in terms of acquired resources, they prevent any exchange of acquired channels. We thus restrict \(\otimes \) and \(\multimap \) to the exchange of channels that have not yet been acquired. This is not a limitation since, as we will see below, shared channel output and input are unrestricted.
Even with the above restriction in place, we still have to make sure that a received channel satisfies Invariant 2. If we were to state a corresponding premise on the receiving rules, invertibility of the rules would be disturbed. To uphold invertibility, we impose a wellformedness condition on session types that ensures for a session of type \(A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}@{\omega _l}\updownarrow ^{\omega _r}_{\omega _p} \otimes B_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\omega _m}\updownarrow ^{\omega _v}_{\omega _u}]\) that \(\omega _v < \omega _p\) and, analogously, for a session of type \(A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}@{\omega _l}\updownarrow ^{\omega _r}_{\omega _p} \multimap B_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\omega _m}\updownarrow ^{\omega _v}_{\omega _u}]\) that \(\omega _v < \omega _p\). Session types are checked to be wellformed upon process definition. Given type wellformedness, we obtain the following rules for \(\multimap \), noting that the right rule enforces Invariant 4 by requiring an empty \(\varPhi \)context. The rules for \(\otimes \) are dual.
Since there are no invariants imposed on the shared context \(\varGamma \), the rules for shared channel output and input are identical to those in \(\mathsf {SILL}_{\mathsf {S}}\). The only differences are that we have two left rules and that the \(\varPhi \)context of the right rule must be empty to satisfy Invariant 4. The former is merely due to the tracking of possibly aliased sessions in the \(\varPhi \) context.
We finally consider the rules for forwarding and spawning. We allow a shared forward between processes that offer the same session at the same worlds. Because forwards have to be worldinvariant, however, no welltyped program could ever have a linear forward. The process being forwarded to must be in either of the contexts \(\varPhi \) or \(\varDelta \), and thus satisfies Invariant 2, making it impossible for the world annotations of the forwarder and forwardee to match. We omit linear forwarding and discuss possible future extensions in Sect. 6.
The rules for spawning depend on the possible modes of the spawning and spawned processes: specifies how a linear process can spawn another linear process; specifies how a shared processes can spawn another shared process. The rules are checked relative to a process definition found in the signature \(\varSigma \) and to a world substitution mapping \(\gamma : \varPsi  \rightarrow \varPsi '\), such that for each \(\delta \in \varPsi '\) we have \(\varPsi \,\vdash \,\gamma (\delta )\), where \(\varPsi \) denotes the field of \(\varPsi \) (i.e., the union of its domain and range). As usual, we lift substitution to types \(\hat{\gamma }(A_m)\), contexts \(\hat{\gamma }(\varGamma )\), and orders \(\hat{\gamma }(\varPsi )\). Both rules ensure that, given the mapping \(\gamma \), the order \(\varPsi \) of the spawning process entails the one of the process definition (\(\varPsi \,\vdash \,\hat{\gamma }(\varPsi ')\)). The linear spawn rule further enforces Invariant 2 for the spawned child. We note that the spawned child enters the linear context \(\varDelta \) in the spawning process’ continuation since no aliases to such a process can exist at this point.
In the companion technical report [4], we provide a variant of rule for the case of a linear recursive tail call. Without linear forwarding, a linear tail call can no longer be implicitly “desugared” into a spawn and a linear forward [2, 22, 52], but must be accounted for explicitly. In the report, we also provide the rules for checking process definitions. Those rules make sure that the process’ world order is acyclic, that the types of the providing session and argument sessions are wellformed, and that the process satisfies Invariants 1 and 2.
3.3 Dining Philosophers in \(\mathsf {SILL}_{\mathsf {S}^+}\)
Having introduced our type system, we revisit the dining philosophers from Sect. 1 and show how to program the example in \(\mathsf {SILL}_{\mathsf {S}^+}\), ensuring that the program will run without deadlocks. The code is given in Fig. 4. We note the world annotations in the signature of the process definitions. For instance,
indicates that, given the order \(\delta _0< \delta _1< \delta _2 < \delta _3\), process \( thinking \) provides a session of type \(\mathsf {phil}[{\delta _0}\updownarrow ^{\delta _2}_{\delta _1}]\) and uses two shared channel references of type \(\mathsf {sfork}[{\delta _1}\updownarrow ^{\delta _3}_{\delta _3}]\) and \(\mathsf {sfork}[{\delta _2}\updownarrow ^{\delta _3}_{\delta _3}]\). The two \(\cdot \) signify that neither acquired nor linear channel references are given as arguments. The signature indicates that the two shared fork references reside at different worlds, such that the world of the first one is smaller than the one of the second.
Let’s briefly convince ourselves that the two acquires in process \( thinking \) in Fig. 4 are typecorrect. For each acquire we have to show that: the world of the resource to be acquired is within the acquiring process’ range; the \(\mathsf {max}\) of the acquiring process is smaller than the \(\mathsf {min}\) of the acquired resource; and, that the \(\mathsf {self}\) of the acquired resource is larger than those of all already acquired resources. We can convince ourselves that all those conditions are readily met. We note, however, that if we were to swap the two acquires, the program would not typecheck.
Let us once more set the table for three philosophers and three forks. We execute this code in a process with world annotations \([{\delta _a}\updownarrow ^{\delta _b}_{\delta _b}]\) such that \(\delta _a < \delta _b\). We first create new worlds and define their order:
We then spawn the forks, each residing at a different world, such that the \(\mathsf {max}\) world of a fork is higher than the \(\mathsf {self}\) of the highest fork, ensuring Invariant 2 for the philosopher processes that we spawn afterwards:
When we spawn the philosophers, we ensure that \(P_0\) is going to pick up fork \(F_1\) and then \(F_2\), \(P_1\) is going to pick up \(F_2\) and then \(F_3\), and \(P_2\) is going to pick up \(F_1\) and then \(F_3\).
We note that the deadlocking spawn
is typeincorrect since we would substitute both \(\mathsf {w_1}\) and \(\mathsf {w_3}\) for \(\delta _1\) and \(\mathsf {w_3}\) and \(\mathsf {w_1}\) for \(\delta _2\), which violates the ordering constraints put in place by typing.
3.4 Dynamics
We now give the dynamics of \(\mathsf {SILL}_{\mathsf {S}^+}\). Our current system is based on a synchronous dynamics. While this choice is more conservative, it allows us to narrow the complexity of the problem at hand.
As in \(\mathsf {SILL}_{\mathsf {S}}\), we use multiset rewriting rules [12] to capture the dynamics of \(\mathsf {SILL}_{\mathsf {S}^+}\) (see Sect. 2). Multiset rewriting rules represent computation in terms of local state transitions between configurations of processes, only mentioning the parts of a configuration they rewrite. We use the predicates \(\mathsf {proc}( a_m , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P_{a_m} )\) and \(\mathsf {unavail}( a_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}})\) to define the states of a configuration (see Sect. 5.1). The former denotes a process executing term P that provides along channel \(a_m\) at mode m with worlds \(\mathsf {w_{a_1}}\), \(\mathsf {w_{a_2}}\), and \(\mathsf {w_{a_3}}\) for \(\mathsf {self}\), \(\mathsf {min}\), and \(\mathsf {max}\), respectively. The latter acts as a placeholder for a shared process providing along channel \(a_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\) with worlds \(\mathsf {w_{a_1}}\), \(\mathsf {w_{a_2}}\), and \(\mathsf {w_{a_3}}\) for \(\mathsf {self}\), \(\mathsf {min}\), and \(\mathsf {max}\), respectively, that is currently unavailable. We note that since worlds are also runtime artifacts, they must occur as part of the statedefining predicates.
Fig. 5 lists selected rules of the dynamics. Since the rules remain largely the same as those of \(\mathsf {SILL}_{\mathsf {S}}\), apart from the world annotations that are “threaded through” unchanged, we only discuss the rules that actually differ from the \(\mathsf {SILL}_{\mathsf {S}}\) rules. The interested reader can find the remaining rules in the companion technical report [4].
Noteworthy are the rules and for creating and relating worlds, respectively. Rule creates a fresh world, which will be globally available in the configuration. Rule , on the other hand, updates the configuration’s order with the pair \(\mathsf {w} < \mathsf {w}'\). Rule , lastly, substitutes actual worlds for world variables in the body of the spawned process, using the substitution mapping \(\gamma \) defined earlier. It relies on the existence of a corresponding definition predicate for each process definition contained in the signature \(\varSigma \). We note that the substitution \(\gamma \) in rule instantiates the appropriate world variables in the spawned process P.
4 Extended Example: An Imperative Shared Queue
We now develop a typical imperativestyle implementation of a queue that uses a list data structure internally to store the queue’s elements and has shared references to the front and the back of the list for concurrent dequeueing and enqueueing, respectively. The session types for the queue and the list are^{Footnote 2}
The list is implemented in terms of processes \( empty \) and \( elem \), denoting the empty list and a cons cell, respectively. We show the more interesting case of a cons cell (Fig. 6). The queue is defined by processes \( head \) (Fig. 7) and \( queue \_ proc \) (Fig. 8), the latter being the queue’s interface to its clients.
We can now define a client (Fig. 8) for the queue, assuming existence of a corresponding shared session type \(\mathsf {item}\) and a process \( item\_proc \) offering a session of type \(\mathsf {item}[{\delta _3}\!\!\!\updownarrow ^{\delta _4}_{\delta _4}]\). The client instantiates the queue at world \(\delta _b\), allowing it to acquire resources at world \(\mathsf {w_1}\), which is exactly the world at which process \( queue\_proc \) instantiates the list. Given that the client itself resides at world \(\delta _a\), which is smaller than the queue’s world \(\delta _b\), the client is allowed to acquire the queue, which in turn will acquire the list to satisfy any requests by the client.
The example showcases a paradigmatic use of several collaborators, where collaborators can hold resources while they “talk down” in the tree. In particular, as illustrated in Fig. 9, the clients \(C_1\), \(C_2\), and \(C_3\) compete for resources at world \(\delta _b\), i.e., the queue Q. On the other hand, a client \(C_i\) collaborates with the queue Q, the list elements \(L_i\), and the items \(I_i\), since they do not overlap in the set of resources they may acquire: a client acquires resources at \(\delta _b\), a queue resources at \(\mathsf {w_1}\), a list resources at \(\mathsf {w_2}\), and an item resources at \(\mathsf {w_4}\), and we have \(\delta _a< \delta _b< \mathsf {w_1}< \mathsf {w_2}< \mathsf {w_3} < \mathsf {w_4}\). We note in particular that the setup prevents a list element from acquiring its successor, forcing linear access through the queue.
5 Semantics
In this section, we discuss the metatheoretical properties of \(\mathsf {SILL}_{\mathsf {S}^+}\), focusing on deadlockfreedom. The companion technical report [4] provides further details.
5.1 Configuration Typing and Preservation
Given the hierarchy between mode \(\mathsf {S}\) and \(\mathsf {L}\) and the fact that shared processes cannot depend on linear processes, we divide a configuration into a shared part \(\varLambda \) and a linear part \(\varTheta \). We use the typing judgment \(\varPsi ; \varGamma \vDash \varLambda ; \varTheta \; {:}\,\!{:} \; \varGamma ; \varPhi , \varDelta \) to type configurations. The judgment expresses that a wellformed configuration \(\varLambda ; \varTheta \) provides the shared channels in \(\varGamma \) and the linear channels in \(\varPhi \) and \(\varDelta \). A configuration is typechecked relative to all shared channel references and a global order \(\varPsi \). While typechecking is compositional insofar as each process definition can be typechecked separately, solely relying on the process’ local \(\varPsi \) (and \(\varGamma \)), at runtime, the entire order that a configuration relies upon is considered. We give the configuration typing rules in Fig. 10.
Our progress theorem crucially depends on the guarantee that the Invariants 1 and 2 from Sect. 3 hold for every linear process in a configuration’s tree. This is expressed by the premises and in rule , based on the Definitions 1 and 2 below that restate Invariants 1 and 2 for an entire configuration. We note that Invariant 2 is based on the set of all transitive children (i.e., descendants) of a process. We formally define the notion of a descendant inductively over a welltyped linear configuration. The interested reader can find the definition in the companion technical report [4].
Invariant 1
(\(\mathsf {min}(\mathsf {parent})\le \mathsf {self}(\mathsf {acquired\_child})\le \mathsf {max}(\mathsf {parent})\)). If \(\varPsi ; \, \varGamma \vDash \varTheta \; {:}\,\!{:} \; \varPhi , \varDelta \) and for any \(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}} )\in \varTheta \) such that \(\varPsi ; \, \varGamma ; \, \varPhi _1; \, \varDelta _1 \vdash P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}} \; {:}\,\!{:} \; (a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}])\), \(\mathsf {Inv}_{{1}}(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}} ))\) holds if an only if for every acquired resource \(b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: B_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\mathsf {w_{b_1}}}\updownarrow ^{\mathsf {w_{b_3}}}_{\mathsf {w_{b_2}}}] \in \varPhi _1\) it holds that \(\varPsi ^* \,\vdash \,\mathsf {w_{a_2}} \le \mathsf {w_{b_1}} \le \mathsf {w_{a_3}}\). Moreover, if \(P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}} = x_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\leftarrow \mathsf {acquire} \, c_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}\,; Q_{ x_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} }\), for a \((c_{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}: {\uparrow }^{\mathchoice{\mathsf {S}}{\mathsf {S}}{\scriptscriptstyle \mathsf {S}}{\scriptscriptstyle \mathsf {S}}}_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}C_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\mathsf {w_{c_1}}}\updownarrow ^{\mathsf {w_{c_3}}}_{\mathsf {w_{c_2}}}]) \in \varGamma \), then, for every acquired resource \(b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: B_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\mathsf {w_{b_1}}}\updownarrow ^{\mathsf {w_{b_3}}}_{\mathsf {w_{b_2}}}] \in \varPhi _1\), it holds that \(\varPsi ^+ \,\vdash \,\mathsf {w_{b_1}} < \mathsf {w_{c_1}}\) and that \(\varPsi ^* \,\vdash \,\mathsf {w_{a_2}} \le \mathsf {w_{c_1} \le \mathsf {w_{a_3}}}\).
Invariant 2
(max(parent) < minima(descendants)). If \(\varPsi ; \, \varGamma \vDash \varTheta \; {:}\,\!{:} \; \varPhi , \varDelta \) and for any \(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}} ) \in \varTheta \) and that process’ descendants \((\varPsi ; \, \varGamma \vDash \varTheta \; {:}\,\!{:} \; \varPhi , \varDelta ) \, \vartriangleright \, a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} \; = \; (\varPhi ', \varDelta ')\), \(\mathsf {Inv}_{{2}}(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}} ))\) holds iff for every descendant \(b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: B_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\mathsf {w_{b_1}}}\updownarrow ^{\mathsf {w_{b_3}}}_{\mathsf {w_{b_2}}}] \in (\varPhi ', \varDelta ')\) it holds that \(\varPsi ^+ \,\vdash \,\mathsf {w_{a_3}} < \mathsf {w_{b_2}}\).
Our preservation theorem states that Invariants 1 and 2 are preserved for every linear process in the configuration along transitions. Moreover, the theorem expresses that the types of the providing linear channels \(\varPhi \) and \(\varDelta \) are maintained along transitions and that new shared channels and worlds may be allocated. The proof relies, in particular, on session types being strictly equisynchronizing, on a process’ type wellformedness and assurance that the process’ \(\mathsf {min}\) world is less than or equal to its \(\mathsf {max}\) world.
Theorem 5.1
(Preservation). If \(\varPsi ; \, \varGamma \vDash \varLambda ; \, \varTheta \; {:}\,\!{:} \; \varGamma ; \, \varPhi , \varDelta \) and \(\varLambda ; \varTheta \longrightarrow \varLambda '; \varTheta '\), then \(\varPsi '; \, \varGamma ' \vDash \varLambda '; \, \varTheta ' \; {:}\,\!{:} \; \varGamma '; \, \varPhi , \varDelta \), for some \(\varLambda '\), \(\varTheta '\), \(\varPsi '\), and \(\varGamma '\).
5.2 Progress
In our development so far we have distilled the two scenarios of interdependencies between processes that can lead to deadlocks: cyclic acquisitions and interdependent acquisitions and synchronizations. This has lead to the development of a type system that ingrains the notions of competitors and collaborators, such that the former compete for a set of resources whereas the latter do not overlap in the set of resources they acquire. Our type system then ties these notions to a configuration’s linear process tree such that collaborators stand in a parentdescendant relationship to each other and competitors in a sibling/cousin relationship. In this section, we prove that this orchestration is sufficient to rule out any of the aforementioned interdependencies.
To this end we introduce the notions of red and green arrows that allow us to reason about process interdependencies in a configuration’s tree. A red arrow points from a linear \(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, Q )\) to a linear \(\mathsf {proc}( b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{b_1}}}\updownarrow ^{\mathsf {w_{b_3}}}_{\mathsf {w_{b_2}}}}, \, P )\), if the former is attempting to acquire a resource held by the latter and, consequently, is waiting for the latter to release that resource. A green arrow points from a linear \(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, Q )\) to a linear \(\mathsf {proc}( b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{b_1}}}\updownarrow ^{\mathsf {w_{b_3}}}_{\mathsf {w_{b_2}}}}, \, P )\), if the former is waiting to synchronize with the latter. We define these arrows formally as follows:
Definition 5.2
(Acquire Dependency — “Red Arrow”). Given a wellformed and welltyped configuration \(\varPsi ; \varGamma \vDash \varLambda ; \varTheta \; {:}\,\!{:} \; \varGamma ; \varPhi , \varDelta \), there exists a waitingduetoacquire relation \(\mathcal {A}(\varTheta )\) among linear processes in \(\varTheta \) at runtime such that
where \(P\langle c_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\rangle \) denotes a process term with an occurrence of channel \(c_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\).
Definition 5.3
(Synchronization Dependency — “Green Arrow”). Given a wellformed and welltyped configuration \(\varPsi ; \varGamma \vDash \varLambda ; \varTheta \; {:}\,\!{:} \; \varGamma ; \varPhi , \varDelta \), there exists a waitingduetosynchronization relation \(\mathcal {S}(\varTheta )\) among linear processes in \(\varTheta \) at runtime such that
where \(P\langle a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\rangle \) denotes a process term with an occurrence of channel \(b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}\), \(\_\langle a \rangle ; \, P\) a process term that currently executes an action along channel a, and \(\_\langle \lnot a \rangle ; \, P\) a process term whose currently executing action does not involve the channel a.
It may be helpful to consult Fig. 3 at this point and note the semantic difference between the violet arrows in that figure and the red arrows discussed here. Whereas violet arrows point from the acquiring process to the resource being acquired, red arrows point from the acquiring process to the process that is holding the resource. Thus, violet arrows can go out of the tree, while red arrows stay within. Given the definitions of red and green arrows, we can define the relation \(\mathcal {W}(\varTheta )\) on the configuration’s tree, which contains all process pairs that are in some way waiting for each other:
Definition 5.4
(Waiting Dependency). Given a wellformed and welltyped configuration \(\varPsi ; \varGamma \vDash \varLambda ; \varTheta \; {:}\,\!{:} \; \varGamma ; \varPhi , \varDelta \), there exists a waiting relation \(\mathcal {W}(\varTheta )\) among processes in \(\varTheta \) at runtime such that \(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P ) <_{{\mathchoice{\mathsf {\mathcal {W}}}{\mathsf {\mathcal {W}}}{\scriptscriptstyle \mathsf {\mathcal {W}}}{\scriptscriptstyle \mathsf {\mathcal {W}}}}} \mathsf {proc}( b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{b_1}}}\updownarrow ^{\mathsf {w_{b_3}}}_{\mathsf {w_{b_2}}}}, \, Q )\),

if \(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P ) <_{{\mathchoice{\mathsf {\mathcal {A}}}{\mathsf {\mathcal {A}}}{\scriptscriptstyle \mathsf {\mathcal {A}}}{\scriptscriptstyle \mathsf {\mathcal {A}}}}} \mathsf {proc}( b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{b_1}}}\updownarrow ^{\mathsf {w_{b_3}}}_{\mathsf {w_{b_2}}}}, \, Q )\), or

if \(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P ) <_{{\mathchoice{\mathsf {\mathcal {S}}}{\mathsf {\mathcal {S}}}{\scriptscriptstyle \mathsf {\mathcal {S}}}{\scriptscriptstyle \mathsf {\mathcal {S}}}}} \mathsf {proc}( b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{b_1}}}\updownarrow ^{\mathsf {w_{b_3}}}_{\mathsf {w_{b_2}}}}, \, Q )\).
Having defined the relation \(\mathcal {W}(\varTheta )\), we can now state the key lemma underlying our progress theorem, indicating that \(\mathcal {W}(\varTheta )\) is acyclic in a wellformed and welltyped configuration.
Lemma 5.5
(Acyclicity of \(\mathcal {W}(\varTheta )\)). If \(\varPsi ; \, \varGamma \vDash \varLambda ; \, \varTheta \; {:}\,\!{:} \; \varGamma ; \, \varPhi , \varDelta \), then \(\mathcal {W}(\varTheta )\) is acyclic.
We focus on explaining the main idea of the proof here. The proof proceeds by induction on \(\varPsi ; \varGamma \vDash \varTheta \; {:}\,\!{:} \; \varPhi , \varDelta \), assuming for the nonempty case \(\varPsi ; \varGamma \vDash \varTheta , \mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}} ) \; {:}\,\!{:} \; (\varPhi , \varDelta , a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}[{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}])\) that \(\mathcal {W}(\varTheta )\) is acyclic, by the inductive hypothesis. We then know that there cannot exist any paths of green and red arrows in \(\varTheta \) that form a cycle, and we have to show that there is no way of introducing such a cyclic path by adding node \(\mathsf {proc}( a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}} , \, \mathsf {{\mathsf {w_{a_1}}}\updownarrow ^{\mathsf {w_{a_3}}}_{\mathsf {w_{a_2}}}}, \, P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}} )\) to the configuration \(\varTheta \). In particular, the proof considers all possible new arrows that may be introduced by adding the node and that are necessary for creating a cycle, showing that such arrows cannot come about in a welltyped configuration.
We illustrate the reasoning for the two selected cases shown in Fig. 11. Case (a) represents a case in which process \(P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) is waiting to synchronize with its child \(P_{b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) while holding a resource a descendant of \(P_{b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) or \(P_{b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) itself wants to acquire. However, this scenario cannot come about in a welltyped configuration because \(P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) and \(P_{b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) are collaborators and thus cannot overlap in resources they acquire. Case (b) represents a case in which process \(P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) is waiting to synchronize with its child \(P_{b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) while another child, process \(P_{c_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\), is waiting to synchronize with \(P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\). Given acyclicity of \(\mathcal {W}(\varTheta )\), a necessary condition for a cycle to form is that there already must exist a red arrow \(\mathbf C \) in the configuration that connects the subtrees in which the siblings \(P_{b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) and \(P_{c_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) reside. However, this scenario cannot come about in a welltyped configuration because \(P_{b_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) and \(P_{c_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) are competitors, forcing \(P_{c_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\) or any of its descendant to release a resource before synchronizing with \(P_{a_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}}\). These arguments are made precise in various lemmas in [4].
Given acyclicity of \(\mathcal {W}(\varTheta )\), we can state and prove the following strong progress theorem. The theorem relies on the notion of a poised process, a process currently executing an action along its offering channel, and distinguishes a configuration only consisting of the toplevel, linear “main” process from one that consists of several linear processes. We use \(\varTheta \) to denote the cardinality of \(\varTheta \):
Theorem 5.6
(Progress). If \(\varPsi ; \varGamma \vDash \varLambda ; \varTheta \; {:}\,\!{:} \; (\varGamma ; c_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}: \mathbf {1}[{\mathsf {w_{c_1}}}\updownarrow ^{\mathsf {w_{c_3}}}_{\mathsf {w_{c_2}}}])\), then either

\(\varLambda \longrightarrow \varLambda '\), for some \(\varLambda '\), or

\(\varLambda \) is poised and

if \(\varTheta  = 1\), then either \(\varLambda ; \varTheta \longrightarrow \varLambda '; \varTheta '\), for some \(\varLambda '\) and \(\varTheta '\), or \(\varTheta \) is poised, or

if \(\varTheta  > 1\), then \(\varLambda ; \varTheta \longrightarrow \varLambda '; \varTheta '\), for some \(\varLambda '\) and \(\varTheta '\).

The theorem indicates that, as long as there exist at least two linear processes in the configuration, the configuration can always step. If the configuration only consists of the main process, then this process will become poised (i.e., ready to close), once all subcomputations are finished. The proof of the theorem relies on the acyclicity of \(\mathcal {W}(\varTheta )\) and the fact that all sessions must be strictly equisynchronizing.
6 Additional Discussion
Linear Forwarding. Our current formalization does not include linear forwarding because a forward changes the process tree and thus endangers the invariants imposed on it. This means that certain programs from the purely linear fragment may not typecheck in our system. However, the correspondingly \(\eta \)expanded versions of these programs should be expressible and typecheckable in \(\mathsf {SILL}_{\mathsf {S}^+}\). As part of future work, we want to explore the addition of the linear forward
which allows forwarding to processes that are known to not yet be aliased and whose world annotations meet the premise \(\varPsi ^+ \,\vdash \,\omega _n < \omega _u\). Restricting to processes in \(\varDelta \) should uphold Invariant 1, while the premise of the rule should uphold Invariant 2. However, this change will affect the inner working of the proofs, the use of inversion in particular, which might have farreaching consequences that need to be carefully explored.
Unbounded Process Networks and World Polymorphism. The typing discipline presented in the previous sections, while rich enough to account for a wide range of interesting programs, cannot type programs that spawn a statically undetermined number of shared sessions that are then to be used. For instance, while we can easily type a configuration of any given number of dining philosophers (Sect. 3.3), we cannot type a recursive process in which the number of philosophers (and forks) is potentially unbounded (as done in [21, 38]), due to the way worlds are created and propagated across processes.
The general issue lies in implementing a statically unbounded network of processes that interact with each other. These interactions require the processes to be spawned at different worlds which must be generated dynamically as needed. To interact with such a statically unknown number of processes uniformly, their offering channels must be stored in a listlike structure for later use. However, in our system, recursive types have to be invariant with respect to worlds. For instance, in a recursive type such as \(T = A_{\mathchoice{\mathsf {L}}{\mathsf {L}}{\scriptscriptstyle \mathsf {L}}{\scriptscriptstyle \mathsf {L}}}@{\omega _l}\updownarrow ^{\omega _r}_{\omega _p} \otimes T\), the worlds \(\omega _l\), \(\omega _p\), \(\omega _r\) are fixed in the unfoldings of T. Thus, we cannot type a worldheterogeneous list and cannot form such process networks.
Given that the issues preventing us from typing such unbounded networks lie in problems of world invariance, the natural solution is to explore some form of world polymorphism, where types can be parameterized by worlds which are instantiated at a later stage. Such techniques have been studied in the context of hybrid logical processes in [7] by considering session types of the form \(\forall \delta .A\) and \(\exists \delta .A\), sessions that are parametric in the world variable \(\delta \), that is instantiated by a concrete reachable world at runtime. While their development cannot be mapped directly to our setting, it is a promising avenue of future work.
7 Related Work
Behavioral Type Analysis of Deadlocks. The addition of channel usage information to types in a concurrent, messagepassing setting was pioneered by Kobayashi and Igarashi [30, 34], who applied the idea to deadlock prevention in the \(\pi \)calculus and later to more general properties [31, 32], giving rise to a generic system that can be instantiated to produce a variety of concrete typing disciplines for the \(\pi \)calculus (e.g., race detection, deadlock detection, etc.).
This line of work types \(\pi \)calculus processes with a simplified form of process (akin to CCS [42] terms without name restriction) that characterizes the input/output behavior of processes. These types are augmented with abstract data that pertain to the relative ordering of channel actions, with the type system ensuring that the transitive closure of such orderings forms a strict partial order, ensuring deadlockfreedom (i.e., communication succeeds unless a process diverges). Building on this, Kobayashi et al. proposed type systems that ensure a stronger property dubbed lockfreedom [35] (i.e., communication always succeeds), and variants that are amenable to type inference [36, 39]. Kobayashi [37] extended this latter system to more accurately account for recursive processes while preserving the existence of a type inference algorithm.
Our system draws significant inspiration from this line of work, insofar as we also equip types with abstract ordering data on certain communication actions, which is then statically enforced to form a strict partial order. We note that our \(\mathsf {SILL}_{\mathsf {S}^+}\) language differs sufficiently from the pure \(\pi \)calculus in terms of its constructs and semantics to make the formulation of a direct comparison or an immediate application of their work unclear (e.g., [37] uses replication to encode recursive processes). Moreover, we integrate this style of orderbased reasoning with both linear and shared session typing, which interact in nontrivial ways (especially in the presence of recursive types and recursive process definitions).
In terms of typability, enforcing session fidelity can be a doubleedged sword: some examples of the works above can be transposed to \(\mathsf {SILL}_{\mathsf {S}^+}\) with mostly cosmetic changes and without making use of shared sessions (e.g., a parallel implementation of factorial that recurses via replication but always answers on a private channel); others are incompatible with linear sessions and require the use of shared sessions via the acquirerelease discipline, which entails a more indirect but still arguably faithful modelling of the original \(\pi \)calculus behavior; some examples, however, cannot be easily adapted to the shared session discipline (e.g., \(*c?(x,y).x?(z).y?(z) \mid *c?(x,y).y?(z).x?(z)\) is typable in [37], where x?(z) denotes input on x and \(*c?(x,y)\) denotes replicated input) and their transcription, while possible, would be too far removed from the original term to be deemed a faithful representation. Recursive processes are known to produce patterns that can be challenging to analyze using such orderbased techniques. The work of [21, 38] specializes Kobayashi’s system to account for potentially unbounded process networks with nontrivial forms of sharing. Such systems are not typable in our work (see Sect. 6 for additional discussion on this topic).
The work of Padovani [44] develops techniques inspired by [35, 37] to develop a typing system for deadlock (and lock) freedom for the linear \(\pi \)calculus where (linear) channels must be used exactly once. By enforcing this form of linearity, the resulting system uses only one piece of ordering data per channel usage and can easily integrate a form of channel polymorphism that accounts for intricate cyclic interleavings of recursive processes. The combination of manifest sharing and linear session typing does not seem possible without the use of additional ordering data, and the lack of singleuse linear channels make the robust channel polymorphism of [44] not feasible in our setting.
Dardha and Gay [15] recently integrated a system of Kobayashistyle orderings in a logical session \(\pi \)calculus based on classical linear logic, extended with the ability to form cyclic dependencies of actions on linear session channels (Atkey et al. [1] study similar cycles but do not consider deadlockfreedom), without the need for new process constructs or an acquirerelease discipline. Their work considers only a restricted form of replication common in linear logicbased works, not including recursive types nor recursive process definitions. This reduces the complexity of their system, at the cost of expressiveness. We also note that the cycles enabled by their system are produced by processes sharing multiple linear names. Since linearity is still enforced, they cannot represent the more general form of cycles that exploit shared channels, as we do.
A comparative study of session typing and Kobayashistyle systems in terms of sharing was developed by Dardha and Pérez [16], showing that such orderbased techniques can account for sharing in ways that are out of reach of both classical session typing and pure logicbased session typing. Our system (and that of [15]) aims to combine the heightened power of Kobayashistyle systems with the benefits of session typing, which seems to be better suited as a typing discipline for a highlevel programming language [18].
Progress and Session Typing. To address limitations of classical binary session types, Honda et al. [27] introduced multiparty session types, where sessions are described by socalled global types that capture the interactions between an arbitrary number of session participants. Under some wellformedness constraints, global types can be used to ensure that a collection of processes correctly implements the global behavior in a deadlockfree way. However, these global typebased approaches do not ensure deadlock freedom in the presence of higherorder channel passing or interleaved multiparty sessions. Coppo et al. [13] and Bettini et al. [6] develop systems that track usage orders among interleaved multiparty sessions, ruling out cyclic dependencies that can lead to deadlocks. The resulting system is quite intricate, since it combines the full multiparty session theory with the order tracking mechanism, interacts negatively with recursion (essentially disallowing interleaving with recursion) and, by tracking order at the multiparty sessionlevel, ends up rejecting various benign configurations that can be accounted for by our more finegrained analysis. We also highlight the analyses of Vieira and Vasconcelos [54] and Padovani et al. [45] that are more powerful than the approaches above, at the cost of a more complex analysis based on conversation types [10] (themselves a partialorder based technique).
Static Analysis of Concurrent Programs. Lange et al. [40, 41] develop a deadlock detection framework applied to the Go programming language. Their work distills CCS processes from programs which are then checked for deadlocks by a form of symbolic execution [40] and modelchecked against modal \(\mu \)calculus formulae [41] which encode deadlockfreedom of the abstracted process (among other properties of interest). Their abstraction introduces some distance between the original program and the analysed process and so the analysis is sound only for certain restricted program fragments, excluding any combination of recursion and process spawning. Our direct approach does not suffer from this limitation.
de’Liguoro and Padovani [17] develop a typing discipline for deadlockfreedom in a setting where processes exchange messages via unordered mailboxes. Their calculus subsumes the actor model and their analysis combines both socalled mailbox types and specialized dependency graphs to track potential cycles between mailboxes in actorbased systems. The unordered nature of actorbased communication introduces significant differences wrt our work, which crucially exploits the ordering of exchanged messages.
8 Concluding Remarks
In this paper we have developed the concept of manifest deadlockfreedom in the context of the language \(\mathsf {SILL}_{\mathsf {S}^+}\), a shared sessiontyped language, showcasing both the programming methodology and the expressiveness of our framework with a series of examples. Deadlockfreedom of welltyped programs is established by a novel abstraction of socalled green and red arrows to reason about the interdependencies between processes in terms of linear and shared channel references.
In future work, we plan to address some of the limitations of the interactions of deadlockfree shared sessions with recursion, by considering promising notions of world polymorphism and world communication. We also plan to study the problem of world inference and the inclusion of a linear forwarding construct.
References
Atkey, R., Lindley, S., Morris, J.G.: Conflation confers concurrency. In: Lindley, S., McBride, C., Trinder, P., Sannella, D. (eds.) A List of Successes That Can Change the World. LNCS, vol. 9600, pp. 32–55. Springer, Cham (2016). https://doi.org/10.1007/9783319309361_2
Balzer, S., Pfenning, F.: Manifest sharing with session types. Proc. ACM Program. Lang. (PACMPL) 1(ICEP), 37:1–37:29 (2017)
Balzer, S., Pfenning, F., Toninho, B.: A universal session type for untyped asynchronous communication. In: 29th International Conference on Concurrency Theory (CONCUR). LIPIcs, pp. 30:1–30:18. Schloss Dagstuhl  LeibnizZentrum fuer Informatik (2018)
Balzer, S., Toninho, B., Pfenning, F.: Manifest deadlockfreedom for shared session types. Technical report CMUCS19102, Carnegie Mellon University (2019)
Benton, P.N.: A mixed linear and nonlinear logic: proofs, terms and models. In: Pacholski, L., Tiuryn, J. (eds.) CSL 1994. LNCS, vol. 933, pp. 121–135. Springer, Heidelberg (1995). https://doi.org/10.1007/BFb0022251
Bettini, L., Coppo, M., D’Antoni, L., Luca, M.D., DezaniCiancaglini, M., Yoshida, N.: Global progress in dynamically interleaved multiparty sessions. In: van Breugel, F., Chechik, M. (eds.) CONCUR 2008. LNCS, vol. 5201, pp. 418–433. Springer, Heidelberg (2008). https://doi.org/10.1007/9783540853619_33
Caires, L., Pérez, J.A., Pfenning, F., Toninho, B.: Logicbased domainaware session types, unpublished draft
Caires, L., Pfenning, F.: Session types as intuitionistic linear propositions. In: Gastin, P., Laroussinie, F. (eds.) CONCUR 2010. LNCS, vol. 6269, pp. 222–236. Springer, Heidelberg (2010). https://doi.org/10.1007/9783642153754_16
Caires, L., Pfenning, F., Toninho, B.: Linear logic propositions as session types. Math. Struct. Comput. Sci. 26(3), 367–423 (2016)
Caires, L., Vieira, H.T.: Conversation types. Theor. Comput. Sci. 411(51–52), 4399–4440 (2010)
Castro, D., Hu, R., Jongmans, S., Ng, N., Yoshida, N.: Distributed programming using roleparametric session types in go: staticallytyped endpoint APIs for dynamicallyinstantiated communication structures. PACMPL 3(POPL), 29:1–29:30 (2019)
Cervesato, I., Scedrov, A.: Relating statebased and processbased concurrency through linear logic. Inf. Comput. 207(10), 1044–1077 (2009)
Coppo, M., DezaniCiancaglini, M., Yoshida, N., Padovani, L.: Global progress for dynamically interleaved multiparty sessions. Math. Struct. Comput. Sci. 26(2), 238–302 (2016)
Crary, K., Harper, R., Puri, S.: What is a recursive module? In: ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI), pp. 50–63 (1999)
Dardha, O., Gay, S.J.: A new linear logic for deadlockfree sessiontyped processes. In: Baier, C., Dal Lago, U. (eds.) FoSSaCS 2018. LNCS, vol. 10803, pp. 91–109. Springer, Cham (2018). https://doi.org/10.1007/9783319893662_5
Dardha, O., Pérez, J.A.: Comparing deadlockfree session typed processes. In: EXPRESS/SOS, pp. 1–15 (2015)
de’Liguoro, U., Padovani, L.: Mailbox types for unordered interactions. In: 32nd European Conference on ObjectOriented Programming, ECOOP 2018, pp. 15:1–15:28 (2018)
Gay, S.J., Gesbert, N., Ravara, A.: Session types as generic process types. In: 21st International Workshop on Expressiveness in Concurrency and 11th Workshop on Structural Operational Semantics, EXPRESS/SOS 2014, pp. 94–110 (2014)
Gay, S.J., Hole, M.: Subtyping for session types in the \(\pi \)calculus. Acta Informatica 42(2–3), 191–225 (2005)
Gay, S.J., Vasconcelos, V.T., Ravara, A., Gesbert, N., Caldeira, A.Z.: Modular session types for distributed objectoriented programming. In: 37th ACM SIGPLANSIGACT Symposium on Principles of Programming Languages (POPL), pp. 299–312 (2010)
Giachino, E., Kobayashi, N., Laneve, C.: Deadlock analysis of unbounded process networks. In: Baldan, P., Gorla, D. (eds.) CONCUR 2014. LNCS, vol. 8704, pp. 63–77. Springer, Heidelberg (2014). https://doi.org/10.1007/9783662445846_6
Gommerstadt, H., Jia, L., Pfenning, F.: Sessiontyped concurrent contracts. In: Ahmed, A. (ed.) ESOP 2018. LNCS, vol. 10801, pp. 771–798. Springer, Cham (2018). https://doi.org/10.1007/9783319898841_27
Griffith, D.: Polarized substructural session types. Ph.D. thesis, University of Illinois at UrbanaChampaign (2016)
Griffith, D., Pfenning, F.: SILL (2015). https://github.com/ISANobody/sill
Honda, K.: Types for dyadic interaction. In: Best, E. (ed.) CONCUR 1993. LNCS, vol. 715, pp. 509–523. Springer, Heidelberg (1993). https://doi.org/10.1007/3540572082_35
Honda, K., Vasconcelos, V.T., Kubo, M.: Language primitives and type discipline for structured communicationbased programming. In: Hankin, C. (ed.) ESOP 1998. LNCS, vol. 1381, pp. 122–138. Springer, Heidelberg (1998). https://doi.org/10.1007/BFb0053567
Honda, K., Yoshida, N., Carbone, M.: Multiparty asynchronous session types. In: 35th ACM SIGPLANSIGACT Symposium on Principles of Programming Languages (POPL), pp. 273–284. ACM (2008)
Hu, R., Yoshida, N.: Hybrid session verification through endpoint API generation. In: Stevens, P., Wąsowski, A. (eds.) FASE 2016. LNCS, vol. 9633, pp. 401–418. Springer, Heidelberg (2016). https://doi.org/10.1007/9783662496657_24
Hu, R., Yoshida, N.: Explicit connection actions in multiparty session types. In: Huisman, M., Rubin, J. (eds.) FASE 2017. LNCS, vol. 10202, pp. 116–133. Springer, Heidelberg (2017). https://doi.org/10.1007/9783662544945_7
Igarashi, A., Kobayashi, N.: Typebased analysis of communication for concurrent programming languages. In: Van Hentenryck, P. (ed.) SAS 1997. LNCS, vol. 1302, pp. 187–201. Springer, Heidelberg (1997). https://doi.org/10.1007/BFb0032742
Igarashi, A., Kobayashi, N.: A generic type system for the Picalculus. In: Conference Record of POPL 2001: The 28th ACM SIGPLANSIGACT Symposium on Principles of Programming Languages, pp. 128–141 (2001)
Igarashi, A., Kobayashi, N.: A generic type system for the Picalculus. Theor. Comput. Sci. 311(1–3), 121–163 (2004)
Jespersen, T.B.L., Munksgaard, P., Larsen, K.F.: Session types for rust. In: 11th ACM SIGPLAN Workshop on Generic Programming, WGP 2015, pp. 13–22 (2015)
Kobayashi, N.: A partially deadlockfree typed process calculus. In: Proceedings of the 12th Annual IEEE Symposium on Logic in Computer Science, pp. 128–139 (1997)
Kobayashi, N.: A type system for lockfree processes. Inf. Comput. 177(2), 122–159 (2002)
Kobayashi, N.: Typebased information flow analysis for the \(\pi \)calculus. Acta Inf. 42(4–5), 291–347 (2005)
Kobayashi, N.: A new type system for deadlockfree processes. In: Baier, C., Hermanns, H. (eds.) CONCUR 2006. LNCS, vol. 4137, pp. 233–247. Springer, Heidelberg (2006). https://doi.org/10.1007/11817949_16
Kobayashi, N., Laneve, C.: Deadlock analysis of unbounded process networks. Inf. Comput. 252, 48–70 (2017)
Kobayashi, N., Saito, S., Sumii, E.: An implicitlytyped deadlockfree process calculus. In: Palamidessi, C. (ed.) CONCUR 2000. LNCS, vol. 1877, pp. 489–504. Springer, Heidelberg (2000). https://doi.org/10.1007/3540446184_35
Lange, J., Ng, N., Toninho, B., Yoshida, N.: Fencing off go: liveness and safety for channelbased programming. In: 44th ACM SIGPLANSIGACT Symposium on Principles of Programming Languages (POPL), pp. 748–761. ACM (2017)
Lange, J., Ng, N., Toninho, B., Yoshida, N.: A static verification framework for message passing in go using behavioural types. In: Proceedings of the 40th International Conference on Software Engineering, ICSE 2018, Gothenburg, Sweden, 27 May–03 June 2018, pp. 1137–1148 (2018)
Milner, R.: A Calculus of Communicating Systems. LNCS, vol. 92. Springer, Heidelberg (1980). https://doi.org/10.1007/3540102353
Neykova, R., Hu, R., Yoshida, N., Abdeljallal, F.: A session type provider: compiletime API generation of distributed protocols with refinements in F#. In: Proceedings of the 27th International Conference on Compiler Construction, CC 2018, pp. 128–138 (2018)
Padovani, L.: Deadlock and lock freedom in the linear \(\pi \)calculus. In: Computer Science Logic  Logic in Computer Science (CSLLICS), pp. 72:1–72:10 (2014)
Padovani, L., Vasconcelos, V.T., Vieira, H.T.: Typing liveness in multiparty communicating systems. In: Kühn, E., Pugliese, R. (eds.) COORDINATION 2014. LNCS, vol. 8459, pp. 147–162. Springer, Heidelberg (2014). https://doi.org/10.1007/9783662433768_10
Pérez, J.A., Caires, L., Pfenning, F., Toninho, B.: Linear logical relations and observational equivalences for sessionbased concurrency. Inf. Comput. 239, 254–302 (2014)
Pfenning, F., Griffith, D.: Polarized substructural session types. In: Pitts, A. (ed.) FoSSaCS 2015. LNCS, vol. 9034, pp. 3–22. Springer, Heidelberg (2015). https://doi.org/10.1007/9783662466780_1
Reed, J.: A judgmental deconstruction of modal logic, January 2009. http://www.cs.cmu.edu/~jcreed/papers/jdml.pdf, unpublished manuscript
Scalas, A., Dardha, O., Hu, R., Yoshida, N.: A linear decomposition of multiparty sessions for safe distributed programming. In: 31st European Conference on ObjectOriented Programming, ECOOP 2017, pp. 24:1–24:31 (2017)
Scalas, A., Yoshida, N.: Lightweight session programming in scala. In: 30th European Conference on ObjectOriented Programming, ECOOP 2016, pp. 21:1–21:28 (2016)
Toninho, B.: A logical foundation for sessionbased concurrent computation. Ph.D. thesis, Carnegie Mellon University and New University of Lisbon (2015)
Toninho, B., Caires, L., Pfenning, F.: Higherorder processes, functions, and sessions: a monadic integration. In: Felleisen, M., Gardner, P. (eds.) ESOP 2013. LNCS, vol. 7792, pp. 350–369. Springer, Heidelberg (2013). https://doi.org/10.1007/9783642370366_20
Vasconcelos, V.T.: Fundamentals of session types. Inf. Comput. 217, 52–70 (2012)
Vieira, H.T., Vasconcelos, V.T.: Typing progress in communicationcentred systems. In: De Nicola, R., Julien, C. (eds.) COORDINATION 2013. LNCS, vol. 7890, pp. 236–250. Springer, Heidelberg (2013). https://doi.org/10.1007/9783642384936_17
Wadler, P.: Propositions as sessions. In: 17th ACM SIGPLAN International Conference on Functional Programming (ICFP), pp. 273–286. ACM (2012)
Author information
Authors and Affiliations
Corresponding authors
Editor information
Editors and Affiliations
Rights and permissions
Open Access This chapter is licensed under the terms of the Creative Commons Attribution 4.0 International License (http://creativecommons.org/licenses/by/4.0/), which permits use, sharing, adaptation, distribution and reproduction in any medium or format, as long as you give appropriate credit to the original author(s) and the source, provide a link to the Creative Commons license and indicate if changes were made.
The images or other third party material in this chapter are included in the chapter's Creative Commons license, unless indicated otherwise in a credit line to the material. If material is not included in the chapter's Creative Commons license and your intended use is not permitted by statutory regulation or exceeds the permitted use, you will need to obtain permission directly from the copyright holder.
Copyright information
© 2019 The Author(s)
About this paper
Cite this paper
Balzer, S., Toninho, B., Pfenning, F. (2019). Manifest DeadlockFreedom for Shared Session Types. In: Caires, L. (eds) Programming Languages and Systems. ESOP 2019. Lecture Notes in Computer Science(), vol 11423. Springer, Cham. https://doi.org/10.1007/9783030171841_22
Download citation
DOI: https://doi.org/10.1007/9783030171841_22
Published:
Publisher Name: Springer, Cham
Print ISBN: 9783030171834
Online ISBN: 9783030171841
eBook Packages: Computer ScienceComputer Science (R0)