loader
Generating audio...

arxiv

Paper 2503.07328

Complete the Cycle: Reachability Types with Expressive Cyclic References

Authors: Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, Tiark Rompf

Published: 2025-03-10

Abstract:

Reachability Types (RT) are a qualified type system for tracking aliasing and separation in functional and higher-order programming. By formalizing resource reachability with a sound static type system, RT enable higher-order programming patterns with runtime safety and non-interference guarantees. However, previous RT systems have been based on calculi that restrict cyclic dependencies and are shown to be terminating in the absence of built-in recursive constructs. While termination is sometimes a desirable property, simplifying reasoning and ensuring predictable behavior, it implies an inability to encode expressive programs involving non-termination and advanced recursive patterns, such as mutual recursion and various fixed-point combinators. In this paper, we address this limitation by extending RT with an expressive cyclic reference type that permits the formation of cyclic dependencies through the store, thereby allowing the system to encode recursive programming patterns without relying on extra built-in constructs. In addition, we redesign qualifier typing in the reference introduction rule, allowing separate references to point to a shared and tracked referent. We formalize the system as the $\lambda^{\circ}_{<:}$-calculus, with a mechanized soundness proof via the standard progress and preservation lemmas. As a demonstration, we implement a well-typed fixpoint operator, proving that recursive patterns can be encoded using the novel cyclic reference type.

Paper Content:
Page 1: Complete the Cycle: Reachability Types with Expressive Cyclic References HAOTIAN DENG, Purdue University, USA SIYUAN HE, Purdue University, USA SONGLIN JIA, Purdue University, USA YUYAN BAO, Augusta University, USA TIARK ROMPF, Purdue University, USA Reachability Types (RT) are a qualified type system for tracking aliasing and separation in functional and higher-order programming. By formalizing resource reachability with a sound static type system, RT enable higher-order programming patterns with runtime safety and non-interference guarantees. However, previous RT systems have been based on calculi that restrict cyclic dependencies and are shown to be terminating in the absence of built-in recursive constructs. While termination is sometimes a desirable property, sim- plifying reasoning and ensuring predictable behavior, it implies an inability to encode expressive programs involving non-termination and advanced recursive patterns, such as mutual recursion and various fixed-point combinators. In this paper, we address this limitation by extending RT with an expressive cyclic reference type that permits the formation of cyclic dependencies through the store, thereby allowing the system to encode recursive programming patterns without relying on extra built-in constructs. In addition, we redesign qualifier typing in the reference introduction rule, allowing separate references to point to a shared and tracked referent. We formalize the system as the 𝜆◦<:-calculus, with a mechanized soundness proof via the standard progress and preservation lemmas. As a demonstration, we implement a well-typed fixpoint operator, proving that recursive patterns can be encoded using the novel cyclic reference type. CCS Concepts: •Software and its engineering →Semantics ;Functional languages ;General program- ming languages . 1 Introduction The challenge of bringing local reasoning to sharing and aliasing has been thoroughly explored in the development of ownership systems [Clarke et al .2013, 2001, 1998; Hogg 1991], linear/affine types [Girard 1987; Wadler 1990], and uniqueness types [Barendsen and Smetsers 1996]. These ideas have also seen practical adoption: notably, Rust [Matsakis and II 2014] incorporates concepts from both uniqueness types and ownership systems to provide strong static memory safety guarantees in a low-level systems language; Linear Haskell [Bernardy et al .2018] extends Haskell’s type system with linear types, controlling the multiplicity of resource use; Scala Capture Types [Boruch- Gruszecki et al .2023] introduce capturing sets to track free variables in a value, preventing illegal captures and escapes. Inspired by separation logic [Reynolds 2002], Reachability Types (RT) [Bao et al .2021; Wei et al . 2024] are a recent proposal to bring reasoning about memory sharing and separation to higher-level functional languages. While Rust, a systems-level language, enforces safety through global heap invariants—specifically, the “shared XOR mutable” uniqueness constraint—Linear Haskell and Scala Capture Types, as higher-level languages with garbage collection, focus on specific usage patterns, such as linearity or particular resource types like captured effects. In contrast, RT provides a more Authors’ Contact Information: Haotian Deng, Purdue University, West Lafayette, IN, USA, deng254@purdue.edu; Siyuan He, Purdue University, West Lafayette, IN, USA, he662@purdue.edu; Songlin Jia, Purdue University, West Lafayette, IN, USA, jia137@purdue.edu; Yuyan Bao, Augusta University, USA, yubao@augusta.edu; Tiark Rompf, Purdue University, USA, tiark@purdue.edu.arXiv:2503.07328v1 [cs.PL] 10 Mar 2025 Page 2: 2 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf 1valc : Ref[(Unit => Unit)q]c 2deff(x : Unit) = {(!c)(x)} 3//⊣[ f : (Unit => Unit)c] 4c := f // error! c ≮:q 5// (Unit => Unit)c≮:(Unit => Unit)q (a) Landin’s knot is not typeable in 𝜆q([Wei et al . 2024]) due to the lack of cyclic references. Line 4 fails to type check because the referent qualifier qcan only reach observable resources before cis declared, which does not include c.1valc :𝝁𝑧.Ref[(Unit => Unit)z]c 2deff(x : Unit) = {(!c)(x)} 3//⊣[ f : (Unit => Unit)c] 4c := f 5// Okay, because c is a cyclic reference (b) Landin’s knot typed with a cyclic reference in 𝜆◦<:(this work). Line 4 is type checked with t-sassgn-v . Its reachability graph is shown below (Figure 1c). c:𝜇z.Ref[(Unit => Unit)𝑧]𝑐f =𝜆x.(...c...):(Unit => Unit)𝑐c := f f : (Unit => Unit)c (c) Reachability graph of a well-typed cyclic reference assigned with a self-capturing function, expressing a simple cycle through the store (this work). Fig. 1. Typing Landin’s Knot flexible alternative, enabling selective enforcement of uniqueness, linear usage, resource capturing, and other patterns through reachability tracking and a flow-sensitive effect system [Bao et al .2021]. However, RT’s treatment of reference typing has limited expressiveness and flexibility due to (1) a lack of cyclic references and (2) constrained, imprecise reference qualifiers. 1.1 Lack of Cyclic References Recent theoretical advances in RT have shown that variants of RT that support higher-order references remain terminating [Bao et al .2023]. This is counterintuitive, as higher-order state typically permits cycles in the store, thereby enabling unrestricted general recursion. In fact, it turns out that RT prohibit creating such cycles through the store, due to the absence of cyclic reference types. As shown in Figure 1a, Landin’s Knot, an idiomatic way to construct cyclic dependencies through higher-order state, is not typeable in Wei et al .[2024]’s polymorphic 𝜆q system due to its restriction on cyclic references. We address this limitation by first providing a brief overview of RT (Section 2.1), presenting potential challenges of supporting cyclic reference typing with RT, and then explaining our approach to overcome these challenges (Section 2.2). We further demonstrate how our solution enables the correct typing of Landin’s Knot in Section 2.3 by supporting cyclic references. 1.2 Constrained, Imprecise Reference Qualifiers Wei et al .[2024]’s reference typing employs a "deep" tracking mechanism, which tracks not only the reference itself but also its transitively reachable locations. While this approach ensures soundness, it constrains the heap structures expressible with nested references and introduces imprecision in reference tracking. Page 3: Complete the Cycle: Reachability Types with Expressive Cyclic References 3 𝜆 T⊥ Ref[T⊥]Ref[T⊥](a) Reachability graph of Bao et al .[2021]’s system. Be- cause references are first-order with untracked referents (depicted as a dotted gray cloud), the system cannot rep- resent hierarchical structures using reference types. Ref[Tp]qRef[Tq]q...𝜆...𝜆... ...... ... (b) Reachability graph illustrating the “deep sep- aration” reference tracking model in Wei et al . [2024]’s system. References marked with qare separate from each other and enforce strict sepa- ration of all transitively reachable locations. Un- tracked data, which separate references may still reach, is depicted as dotted gray clouds.Ref[Tp]qRef[Tq]q...𝜆...𝜆 𝜆... ... ... (c) Reachability graph illustrating the "shallow separation" reference tracking model in 𝜆◦<:(this work). Unlike Wei et al .[2024]’s system, our model allows separate references to share child nodes (de- picted in yellow ). Additionally, the system sup- ports cyclic references where values can reach the references themselves (highlighted in purple ). Fig. 2. Reachability graph illustrating references in Bao et al .[2021], Wei et al .[2024], and this work. The 𝜆-labeled clouds represent non-location values, and the circular nodes ( ⃝) represent store locations. All store locations are tracked (we denote tracked values using pale blue ). We discuss a concrete example in Section 2.4. As illustrated in Figure 2b, separate references1remain not only distinct themselves but also strictly separate from each other in terms of their transitively reachable locations.2This restriction prevents parent references from sharing store locations, further limiting the expressiveness of heap structures involving nested references. Beyond structural constraints, this overapproximation of reference reachability affects precision in reference typing. For instance, extending the system with effect tracking to model a linked-list structure would cause an update to a single node to affect the entire list, violating the intended semantics. The inability to distinguish between a reference and its reachable locations limits expressiveness in programs that require fine-grained reference tracking. To address these limitations, we refine the reference introduction rule, allowing references to share underlying objects while preserving soundness (Section 2.4). 1Separation is indicated by the qmarker, which signifies contextual freshness. Resources with a sole qmarker only reach contextually fresh objects and are considered separate from currently observable resources. See Section 2.1 for a detailed explanation of the qmarker. 2This follows directly from t-ref , whereqappears in the qualifiers of both the inner referent and the outer reference. As a result, the outer qualifier always includes all transitively reachable locations. Page 4: 4 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf This Work .In this work, we extend RT’s reference typing in two directions to improve the expressiveness of the system. First, we introduce well-typed cyclic references that store values which may capture the reference itself. This is key to enabling recursive programming patterns within the primitive RT framework without built-in recursion support, allowing the system to type-check various non-terminating applications (Section 4). The presence of cycles introduces complexity not encountered in previous systems. In particular, the assignment operation of cyclic references must be carefully controlled in order to maintain the soundness of the type system (Section 2.2). We observe that by requiring the assigned reference term to be a variable, and the assignee’s qualifier to be a singleton qualifier matching that variable, we can effectively retain soundness in the presence of mutable references containing cycles through the store (Section 3.2). Second, we introduce shallow and precise reference tracking, allowing separate references to contain shared objects indirectly. This design improves the precision of reference qualifiers by distinguishing references from their transitively reachable locations. Consequently, this design also enables the construction of graph structures in the reachability hierarchy not possible in prior systems (cf. Figure 2c). We present the 𝜆◦ <:-calculus, which enables the typing of cyclic references in the presence of reachability tracking. Specifically, it enables the language to express advanced non-terminating patterns through a fixed-point operator (see Section 4). Contributions and Organization .The main contributions of this paper are as follows: •We informally present the encoding of recursion using cyclic references alone in RT, without relying on built-in language support (Section 2). We present basic concepts of RT (Section 2.1), key ideas of this work including cyclic references (Section 2.2) leading to the typing of Landin’s Knot in RT (Section 2.3), and precise reference tracking (Section 2.4). •We present the 𝜆◦ <:-calculus, a variant of the RT systems that permits well-typed cyclic structures with a cyclic reference type (Section 3), covering basic syntax (Section 3.1), static typing (Section 3.2), dynamic typing (Section 3.3), implementation details of the mechanized proof (Section 3.4), as well as meta-theory (Section 3.5) leading to the main soundness result. •We present a case study on a fixed-point combinator that demonstrates 𝜆◦ <:’s ability to write non-terminating programs (Section 4). We discuss related work in Section 5, and in Section 6, we address limitations of this work as well as the trade-offs that justify our design decisions. As in Wei et al .[2024], we extend the system with type polymorphism in the style of system F <:and fully mechanize it in Coq, showing type soundness by proving the progress and preservation lemma.3 2 Reachability Types (RT) In this section, we introduce key concepts of Reachability Types (RT) (Section 2.1), discuss cyclic references (Section 2.2) and their role in typing examples such as Landin’s Knot (Section 2.3), and explore shallow reference tracking (Section 2.4). 2.1 Key Ideas of RT Type Qualifiers: Tracking Named, Reachable Resources .Reachability Types assign type qualifiers to terms, in addition to types. The type qualifiers keep track of the reachable set of resource of a given term, thus providing static guarantee about resource sharing and separation. 3The proof artifact can be found at https://github.com/TiarkRompf/reachability. Page 5: Complete the Cycle: Reachability Types with Expressive Cyclic References 5 Type qualifiers are finite sets of names used in the program, optionally including the qmarker that signifies a fresh resource (See Figure 4). For example, a variable (that is a reference to an (untracked) integer value) named counter naturally tracks itself with its qualifier, and has counter in its own qualifier signifying this tracking: valcounter = newRef(0) // : Ref[Int]counter⊣[ counter: Ref[Int]...] When an alias is created for the counter variable, the alias has counter in its qualifier: valcounter2 = counter // : Ref[Int]counter2⊣[ counter2: Ref[Int]counter , counter: ... ] Note that through the context, we can trace the reachability of resource. For functions, qualifiers keep track of their captured variables . For example, in an idiomatic, functional implementation of the counter increment method inccaptures the free variable counter , and this capturing is reflected in its observability qualifier: def inc(n: Int): Unit = { counter := !counter + n } // : inc: (Int => Unit)counter In addition to the qualifier, function argument type and return type also have their qualifiers. We refer readers to Wei et al .[2024] for a complete description at the meaning of function argument qualifier and return qualifier. Fresh Marker q: Tracking Unbound, Freshly Allocated Resource .Qualifiers can also be a special marker (a.k.a. the “fresh” marker, denoted by the qsymbol), which serves a dual purpose depending on their occuring context. We illustrate the two purposes below. 1. Fresh Marker in Regular Qualifier. When qoccurs in the qualifier of a concrete resource, it signifies that the resource is a freshly allocated resource that is not (yet) bound to a name. For example, a newly created reference has a qas its type qualifier: newRef(0) // : Ref[Int]q As the fresh resource is bound to a variable name, the context keeps track of the fact that the name refers to a fresh resource, and the fresh marker no longer appears in the variable: varcounter = newRef(0) // : Ref[Int]counter⊣[ counter: Ref[Int]q] 2. Fresh Marker in Function Argument Qualifier. Whenqappears in a function argument qualifier, it signifies that the argument may contain unobservable resources, allowing the function to be used in a growing application (a.k.a. a “fresh” application). This means that the function does not assume a fixed set of reachable variables in its argument but instead allows qualifiers that can expand during evaluation. A key motivation for using qin function arguments is to prevent incorrect aliasing assumptions. Specifically, function applications must enforce a separation constraint between the function’s qualifier and the argument’s qualifier. If the function were allowed to access an argument with an overlapping qualifier, inconsistencies in qualifier tracking could arise. Consider the following identity function, which simply returns its argument: defid(x: Tq): Tx= x Here, the argument xis marked with q, meaning that the function does not assume any aliasing relationships between xand the function’s environment. This allows idto be applied to newly allocated or untracked resources without interfering with existing references. However, failing to enforce this separation constraint can lead to unsound aliasing. Consider the following function, which modifies its argument: defupdate(x: Ref[Int]q): Unit = { counter := !(x) + 1 } Applying update to an argument that aliases counter violates the separation constraint: Page 6: 6 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf update(counter) // Invalid: counter overlaps with x The issue arises because counter is a tracked resource that already appears in the function’s environment, whereas xis marked with q, indicating that it should be fresh or previously untracked. The function body assumes that xis disjoint from its environment, but in this case, xaliases counter , leading to a violation. By enforcing the separation constraint with q, we prevent function applications where the argument is already part of the function’s tracked environment. This ensures that function bodies do not inadvertently mix fresh and existing references, preserving sound alias tracking. Again, we refer readers to Wei et al .[2024] for details (See t-app-fresh for the formal typing rule of fresh applications). Reference Type: Mutable Cells .So far, the examples involving reference types only have base types ( e.g.Int) as the referent type, whose qualifier is untracked ( ∅), and thus elided. In fact, Wei et al.[2024]’s system does support references with referent qualifiers, and the assigned referent must possess only the specified qualifier: vala = ... // : Ta valb = ... // : Tb valcell = newRef(...) // : Ref[Ta ]... cell := a // Okay cell := b // Error: referent qualifier mismatch! As shown above, since cellhasaas its referent qualifier, it is only permitted to assign cellwith a(or any resource whose qualifier is upper-bounded by a), and an attempt to assign it with, for example, b, will trigger a type error. Qualifier Subtyping: Subset Relation .Qualifiers in RT support subtyping, following an intu- itive subset relation where a qualifier can be upcast to a “larger” qualifier (See q-sub ). For example, in the code below, the qualifier of the reference cellis adjusted to allow both aand bwith qualifier subtyping: vala = ... // : Ta valb = ... // : Tb valcell = newRef(...) // : Ref[Ta,b ]... cell := a // Okay. Ta <: Ta,b cell := b // Okay. Tb <: Ta,b Here, subtyping allows precise tracking of aliasing relationships: since TaandTbare both subtypes ofTa,b, the reference cell can safely store either. Additional qualifier subtyping rules are presented in Figure 6, and we refer readers to Wei et al . [2024] for an in-depth discussion. Limited Reference Typing .Building on Bao et al .[2021]’s system, which only supports un- tracked, first-order references, Wei et al .[2024] extend reference typing to handle nested references. However, their system imposes the following constraints: (1)The referent qualifier must be in scope when the reference is created, prohibiting cyclic references. (2) The referent qualifier is always included in the qualifier of the newly created reference. The first constraint prevents cyclic dependencies between the referent and the reference. Specifi- cally, it disallows the referent qualifier from depending on the reference qualifier that contains it. As a result, cyclic constructs such as Landin’s Knot cannot be typed (See Figure 1a). The second constraint introduces an unnecessary coupling between the reference (parent node) and its referent Page 7: Complete the Cycle: Reachability Types with Expressive Cyclic References 7 First-Order Reference (Bao et al .[2021])4Nested Reference (Wei et al .[2024])5Non-Cyclic Reference (This work)Cyclic Reference (This work) y = new Ref(e)𝑦:Ref[𝑇⊥]𝑞 𝑒:𝑇⊥𝑦:Ref[𝑇𝑞]𝑞,q 𝑒:𝑇𝑞𝑦:𝝁𝑥.Ref[𝑇𝑞]q 𝑒:𝑇𝑞𝝁𝑥.Ref[𝑇𝑥,𝑞]q 𝑒:𝑇𝑞 y := x 𝑥:𝑇⊥𝑥:𝑇𝑞𝑥:𝑇𝑞𝑥:𝑇𝑞,𝑦 ! y !𝑦:𝑇⊥!𝑦:𝑇𝑞!𝑦:𝑇𝑞!𝑦:𝑇𝑞,𝑦 Fig. 3. Comparison of Reference Typing Rules in RT. (child node), limiting the ability to track separate references that share the same referent (See Figure 2b). To address constraint (1), we introduce a more expressive core language capable of typing cyclic constructs such as Landin’s Knot and similar recursive programs (Section 2.2, Section 2.3). We resolve constraint (2) by refining the reference typing mechanism, which we discuss in Section 2.4. We list the key differences of reference types with other variants of RT systems in Figure 3. 2.2 Cyclic References In order to address constraint (1), we introduce a more expressive reference type that allows the inner referent qualifier to refer to its enclosing, outer reference qualifier. We denote the new form of reference as 𝝁𝑧.Ref[𝑇𝑞]𝑝, where 𝝁𝑧creates a binder that can be included in the inner referent qualifier 𝑞, to refer to the reference itself. This extension is key to enabling cyclic references where the referent qualifier can capture its containing reference cell. The idea is that when the bound variable 𝑧is present in the referent qualifier 𝑞, we permit updating the referent with values containing a cyclic pointer to the reference itself through the reference assignment operator: valouter = newRef(...) // 𝝁𝑧.Ref[Tz]outer valinner = ... // Touter outer := inner // Okay This construct introduces a cyclic dependency: the variable inner reaches reference outer (as indicated by its qualifier), while outer , being a cyclic reference, can containinner via the assignment operator. However, incorporating cyclic dependencies into the type system is non-trivial, as it must remain sound in their presence. Consider a naive (and erroneous) assignment rule t-sassgn-err :6 Γ𝜑⊢𝑡1:𝝁𝑧.Ref[𝑇𝑧,𝑞]𝑝 Γ𝜑⊢𝑡2:𝑇𝑝,𝑞 Γ𝜑⊢𝑡1B𝑡2:Unit∅(t-sassgn-err) The first premise requires that 𝑡1has a cyclic reference type, where its referent qualifier can reach either 𝑞or itself (indicated by 𝑧). The second premise states that any term 𝑡2can be assigned to𝑡1as long as its qualifier does not exceed 𝑞and the qualifier of 𝑡1, denoted by 𝑝. 4Bao et al .[2021] used⊥to denote untracked qualifiers, which is semantically equivalent to ∅in later systems. Their system does not have an equivalent concept of “freshness”. 5In this system, it is possible for references to have the qqualifier alone under a different context through fresh application (t-app-fresh ), but it is impossible to produce separate references that encapsulate a shared value (See Section 2.4). 6This rule also lacks an additional premise q∉𝑞, which is not discussed in this section. The design decisions around this rule are explored further in Section 3.2. Page 8: 8 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf While this rule provides flexibility for cyclic dependencies, it introduces a serious issue in the presence of subtyping. Specifically, it permits an assignee with anyqualifier to be assigned to a self-reference, which violates the intended semantics of cyclic references. To see why this is problematic, consider the following example, where the qualifier of the self reference e1is upcasted to (incorrectly) accommodate an arbitrary qualifier in e2, ande2is also upcasted to include e1in its qualifier: vale1 = newRef(...) // : 𝝁𝑥.Ref[Tx]e1 vale2 = ... // : Te2,a,b,c,d,e e1 := e2 // Unsound operation permitted by t-sassgn-err! // e1: 𝝁𝑥.Ref[Tx]e1<:𝝁𝑥.Ref[Tx]e1,e2,a,b,c,d,e // e2: Te2,a,b,c,d,e<: Te1,e2,a,b,c,d,e This operation is clearly unsound, yet it would be naively permitted by t-sassgn-err . This issue arises because upcasting of a cyclic reference’s outer qualifier allows it to generalize beyond its original scope. If assignments were based on the outer qualifier (as in t-sassgn-err ), the system’s qualifier tracking would become inconsistent. The key to fixing this issue is to constrain the assigned reference to a variable and the assignee’s qualifier to a singleton qualifier (i.e.∈P 1, see Figure 4), as shown in t-sassgn-v . We discuss this rule in detail in Section 3.2.3. Restricting assignment to variable terms and singleton qualifiers ensures safety, because at runtime, a variable of reference type ( e.g.e1in this case) will always be substituted into a single location, and the assignee’s singleton variable qualifier ( e.g.e2) will be substituted into the exact same singleton location qualifier. With the correct typing rule ( t-sassgn-v ) in place, the system would reject the assignment operation thereby retaining soundness: e1 := e2 // Error: e2’s qualifier must be exactly e1 // e2: Te2,a,b,c,d,e̸<: Te1 2.3 Landin’s Knot: Type Checked We now take a closer look at how cyclic references can allow RT to type a prime example of cycle through store: the Landin’s Knot. We explain the key components that enable such typing in the presence of reachability tracking without sacrificing the overall soundness of the system. Landin’s Knot [Landin 1964] is a lightweight method to encode recursion in a non-recursive lambda calculus utilizing higher-order state. Below is a typical implementation of Landin’s Knot (with Scala surface syntax): valc;deff(x) = {(!c)(x)}; c := f In the above example, cis a pointer to a reference cell in memory, and fis a function that invokes itself through the memory cell c. The assignment operation c := f “ties” the knot by assigning c with the desired function, after which, calling fwill initiate an infinite sequence of recursive calls to function f. Now, we highlight two limitations of the existing RT systems that prevent the typing of the Landin’s Knot. One key challenge with the encoding of Landin’s Knot in the presence of reachability tracking lies in the need to assign a self capturing referent into the reference itself. Note that in Figure 1a, we cannot simply assign qualifier cto the referent type Unit => Unit because the referent qualifier must already be in the current context prior to being used at the reference creation site, as demanded by constraint (1) mentioned in Section 2.1. However, equipped with cyclic references, Figure 1b shows how the use of a cyclic reference with a carefully controlled assignment operation ( t-sassgn-v ) can delegate the inner qualifier to the outer qualifier, thus correctly typing Landin’s Knot. Note that as mentioned in Section 2.2, the Page 9: Complete the Cycle: Reachability Types with Expressive Cyclic References 9 program only type checks because the assigned cyclic reference is of the variable form, whose singleton qualifier is present in the assignee’s qualifier set. This is key to ensuring the soundness of the system in the presence of cyclic structures, because it rules out illegal qualifier growth by restricting the assignee’s qualifier to a singleton qualifier matching a fixed variable term form. The typed Landin’s knot is illustrated in Figure 1c. We discuss technical details regarding the typing rules on cyclic references in Section 3. 2.4 Shallow, Precise Reference Tracking Constraint (2) stems from a design decision in Wei et al .[2024] that enforces a saturated, deep dependency on the reference qualifiers, in the sense that the reference’s (outer) qualifier always subsumes the referent’s (inner) qualifier. This design creates unnecessary coupling between the inner and the outer qualifier, and leads to imprecise reachability tracking. Consider a reference cellthat contains an inner element a, under Wei et al. [2024]’s system: vala = ... // : Ta valcell = newRef(a) // : (Ref[Ta])cell,a // Imprecision! cell and a are separate, but treated as shared cell’s qualifier overapproximates its reachable sets by including the qualifier of its enclosed element a. While such treatment is safe, it is largely imprecise and precludes complex uses of references where a more granular tracking precision is desired. Suppose we extend the system with flow-sensitive use effects upon reference assignment, then reassigning cellwould also impose a use effect on a, which is imprecise: cell := ... // (cell, use) ⊲(a, use) // a appears to be used, even though it is not used Note that under Wei et al .[2024]’s system, it is possible to create a function ( e.g.newctx ) that attempts to “remove” the outer qualifier by passing the reference as a fresh argument (by t-app- fresh ): valinner = ... // : Tinner valc1 = newRef(inner) // : (Ref[Tinner])c1,inner valc2 = newRef(inner) // : (Ref[Tinner])c2,inner defnewctx(c1' : Ref[Tinner]q)(c2' : Ref[Tinner]q) = { // attempt to use c1' and c2' as separate resource, okay } However, the function can never be invoked with the desired argument c1andc2, because the function demands the two separate references to contain a shared value inner, which is prohibited, as illustrated in Figure 2b. Semantically, the resulting function of partial application of the first argument c1captures inner, which overlaps with the second argument c2, but the function signature requires c2to be a contextually fresh argument: newctx(c1)(c2) // Error: newctx(c1) has overlapping qualifier ‘inner‘ with c2 In other words, in Wei et al .[2024], reference qualifiers are saturated tracking their transitively reachable store locations. Consequently, as illustrated in Figure 2b, individually fresh references must not reach shared store locations. To address this constraint, we disentangle the reference qualifier and the referent qualifier, removing the inclusion requirement on the outer reference qualifier. Now consider the same example shown in Section 1: vala = ... // : Ta valcell = newRef(a) // : (Ref[Ta])cell // a and cell are distinct locations now Page 10: 10 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf cell := ... // (cell, use) // Good: cell is used without affecting a Note that the qualifier of cellno longer contains the qualifier of its referent, a, in this case. This allows the type system to attain a higher precision and express separation between the reference and the referent, and aligns reference typing to the one-step reachability model. The shallow tracking mechanism we propose scales well to nested references. Figure 2c shows that references capturing the same resource are correctly treated as separate. 3𝜆◦ <:: Reachability Types with Cyclic Reference Type In this section, we formally define 𝜆◦ <:and prove key theorems to establish its type safety proof. We use Wei et al .[2024] as a base system, highlighting additions in gray boxes . When appropriate, we also use gray color to indicate typing rules in 𝜆qthat are superseded by new rules in 𝜆◦ <:and no longer present in the system, aligning them side-by-side for easy comparison. 3.1 Syntax We propose a cyclic reference type in the form of 𝝁𝑥.Ref[𝑇𝑞]𝑝. Intuitively, 𝝁𝑥creates a bound variable𝑥that can appear in 𝑞to refer to its outer qualifier 𝑝. The bound variable has a more significant meaning in the context of dereferencing (Section 3.2.2) and assignment (Section 3.2.3), which we defer to their corresponding sections. For any reference 𝝁𝑥.Ref[𝑇𝑞]𝑝, when there is no bound variable 𝑥present in the referent qualifiers𝑞, it is a non-cyclic reference , and can be abbreviated into Ref[𝑇𝑞]𝑝, which we adopt from Wei et al .[2024] as syntactic sugar (See Figure 4). When the bound variable 𝑥iscontained in the referent qualifier 𝑞, the full 𝝁𝑥notation must be used to avoid ambiguity. Although the 𝝁𝑥notation we use coincides with other systems such as recursive types ([Abadi and Fiore 1996; Pierce 2002]) and DOT ([Amin et al .2016; Rompf and Amin 2016]), cyclic references denoted by 𝝁𝑥have distinct meaning unlike that of other works, and we elaborate on the difference in Section 5. 3.2 Static Typing We now discuss details regarding the typing rules for 𝜆◦ <:.t-var andt-cst are typing rules for variables and constants. While the former provides typing for free variables in the context, the latter provides typing for base types. For this section, we assume Unit is the only base type in the system. We include natural numbers and boolean types as base types in Section 4. 3.2.1 Introduction Rules. t-sref andt-sref-2 are introduction rules for the reference type, con- structing non-cyclic references and cyclic references respectively. Like t-ref ,t-sref creates non- cyclic references, but it removes the deep dependency between the inner and the outer qualifiers. Specifically, the reference constructor does not propagate the referent qualifier ( e.g.q) to the outer qualifier. We maintain a shallow dependency, making the outer qualifier always track precisely what is reached by the reference itself without the resource contained within it. This modifies the interpretation of reference qualifiers from Wei et al .[2024]. Instead of tracking all the transitively reachable locations through the store typing, the reference qualifier only reaches the underlying location (see Section 2.4). Similar to Wei et al .[2024], we disallow creating references to fresh resources to ensure sound reachability tracking, preventing imprecise aliasing tracking. Without this restriction, dereferencing (see Section 3.2.2) such a reference multiple times would produce values that, from the qualifier’s perspective, appear to be distinct fresh resources while actually referring to the same underlying resource. Page 11: Complete the Cycle: Reachability Types with Expressive Cyclic References 11 Syntax 𝜆◦<:𝑥,𝑦,𝑧∈ Var Variables 𝑓,𝑔,ℎ∈ Var Function Variables 𝑋∈ Var Type Variables 𝑆,𝑇,𝑈,𝑉 ::= Unit|𝑓(𝑥:𝑄)→𝑅|𝝁𝑥.Ref[𝑄] |Top|𝑋|∀𝑓(𝑋𝑥<:𝑄).𝑄 Types 𝐵 ::= Unit Base Types 𝑡 ::=𝑐|𝑥|𝜆𝑓(𝑥).𝑡|𝑡𝑡|ref𝑡|!𝑡|𝑡B𝑡 |Λ𝑓(𝑋𝑥).𝑡|𝑡[𝑄] Terms 𝑝,𝑞,𝑟,𝑤∈ P fin(Var⊎{q}) Type Qualifiers 𝑂,𝑃,𝑄,𝑅 ::=𝑇𝑞Qualified Types 𝜑∈ P fin(Var) Observations Γ ::=∅|Γ,𝑥:𝑄|Γ,𝑋𝑥<:𝑄 Typing Environments Reference Notations Ref[𝑄]:=𝝁𝑥.Ref[𝑄] if𝑥∉fv(𝑄) Qualifier Notations 𝑝,𝑞 :=𝑝∪𝑞 Qualifier Union 𝑞⊖𝑥 :=𝑞\{𝑥} Qualifier Exclusion 𝑥 :={𝑥} Single Variable Qualifier q :={q} Single Fresh Qualifier {Var} :={{𝑥}|𝑥∈Var} Singleton Variable Qualifiers P1 :={Var} Singleton Qualifiers Fig. 4. The syntax of 𝜆◦<:. 3.2.2 Dereference Rules. The dereference rule ( t-sderef ) serves as the elimination form for refer- ence types, ensuring that the dereference operation ( !...) correctly retrieves the stored referent while preserving its typing and qualifier. A key subtlety in handling the referent qualifier is that, in addition to returning the inner qualifier 𝑞, we substitute the bound variable using the outer qualifier𝑝. This substitution is necessary because the bound variable acts as an abstraction for the outer qualifier within the reference type. Once dereferencing eliminates the reference type, this abstraction must be replaced with the actual outer qualifier, as the resulting value no longer contains a reference and thus cannot retain the abstraction. For non-cyclic references, where the bound variable xis absent from the referent qualifier, this rule generalizes the t-deref rule in Wei et al .[2024], simply retrieving the referent qualifier. However, for cyclic references where the referent qualifier contains the bound variable x, the operation must retrieve both the referent qualifier and the reference qualifier, by substituting the bound variable with the outer qualifier. Thus, the bound variable serves as a abstraction for the outer qualifier. Through dereferencing, we concretize this abstraction, making the outer reference qualifier explicit in the resulting type. However, such an abstraction is limited in that the bound variables can refer only to their immediate outer qualifier, rather than qualifiers at arbitrary depth, as seen in lambda abstractions (see Section 6). 3.2.3 Assignment Rules. Assignment updates the value stored in a mutable reference. Due to the complexities of assigning to cyclic references, we introduce two distinct assignment rules. Page 12: 12 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf Term Typing Γ𝜑⊢𝑡:𝑄 𝑦:𝑇𝑞∈Γ𝑦∈𝜑 Γ𝜑⊢𝑦:𝑇𝑦(t-var)𝑐∈𝐵 Γ𝜑⊢𝑐:𝐵∅(t-cst) Γ𝜑⊢𝑡:𝑇𝑞q∉𝑞 Γ𝜑⊢ref𝑡:(Ref𝑇𝑞)𝑞,q (t-ref)Γ𝜑⊢𝑡:𝑇𝑞q∉𝑞 Γ𝜑⊢ref𝑡:(Ref𝑇𝑞)q (t-sref)Γ𝜑⊢𝑡:𝑇𝑞q∉𝑞 Γ𝜑⊢ref𝑡:𝝁𝑥.Ref[𝑇𝑥,𝑞]q (t-sref-2) Γ𝜑⊢𝑡:(Ref𝑇𝑞)𝑝𝑞⊆𝜑 Γ𝜑⊢!𝑡:𝑇𝑞 (t-deref)Γ𝜑⊢𝑡:𝝁𝑥.Ref[𝑇𝑞]𝑝𝑞⊆𝜑,𝑥𝑥∉fv(𝑇) Γ𝜑⊢!𝑡:𝑇𝑞[𝑝/𝑥](t-sderef) Γ𝜑⊢𝑡1:(Ref𝑇𝑞)𝑝 Γ𝜑⊢𝑡2:𝑇𝑞q∉𝑞 Γ𝜑⊢𝑡1B𝑡2:Unit∅ (t-assgn)Γ𝜑⊢𝑡1:𝝁𝑥.Ref[𝑇𝑞]𝑝 Γ𝜑⊢𝑡2:𝑇𝑞⊖𝑥 Γ𝜑⊢𝑡1B𝑡2:Unit∅ (t-sassgn)Γ𝜑⊢𝑦:𝝁𝑥.Ref[𝑇𝑞,𝑥]𝑝 Γ𝜑⊢𝑡2:𝑇𝑦,𝑞 Γ𝜑⊢𝑦B𝑡2:Unit∅ (t-sassgn-v) Γ𝜑⊢𝑡1:(𝑓(𝑥:𝑇𝑝)→𝑈𝑟)𝑞 Γ𝜑⊢𝑡2:𝑇𝑝q∉𝑝 𝑟⊆q,𝜑,𝑥,𝑓𝑝∉P1⊎{∅}⇒𝑥∉fv(𝑈) Γ𝜑⊢𝑡1𝑡2:𝑈𝑟[𝑝/𝑥,𝑞/𝑓] (t-app)Γ𝜑⊢𝑡1:𝑓(𝑥:𝑇𝑝 q∩𝑞)→𝑈𝑟𝑞Γ𝜑⊢𝑡2:𝑇𝑝 q∈𝑝⇒𝑥∉fv(𝑈)q∈𝑞⇒𝑓∉fv(𝑈) 𝑟⊆q,𝜑,𝑥,𝑓𝑝∉P1⊎{∅}⇒𝑥∉fv(𝑈) Γ𝜑⊢𝑡1𝑡2:(𝑈𝑟)[𝑝/𝑥,𝑞/𝑓] (t-app-fresh) (Γ, 𝑓:𝐹 , 𝑥 :𝑃)𝑞,𝑥,𝑓⊢𝑡:𝑄 𝐹=(𝑓(𝑥:𝑃)→𝑄)𝑞𝑞⊆𝜑 Γ𝜑⊢𝜆𝑓(𝑥).𝑡:𝐹 (t-abs)(Γ, 𝑓:𝐹 , 𝑋𝑥<:𝑃)𝑞,𝑥,𝑓⊢𝑡:𝑄 𝐹=(∀𝑓(𝑋𝑥<:𝑃).𝑄)𝑞𝑞⊆𝜑 Γ𝜑⊢Λ𝑓(𝑋𝑥).𝑡:𝐹 (t-tabs)Γ𝜑⊢𝑡:𝑄 Γ⊢𝑄<:𝑇𝑞 𝑞⊆𝜑,q Γ𝜑⊢𝑡:𝑇𝑞 (t-sub) Γ𝜑⊢𝑡:(∀𝑓(𝑋𝑥<:𝑇𝑝).𝑄)𝑞 q∉𝑝 𝑓∉fv(𝑈) 𝑝⊆𝜑 𝑟⊆ q𝜑,𝑥,𝑓 𝑄 =𝑈𝑟 Γ𝜑⊢𝑡[𝑇𝑝]:𝑄[𝑇𝑝/𝑋𝑥,𝑞/𝑓](t-tapp)Γ𝜑⊢𝑡:∀𝑓(𝑋𝑥<:𝑇𝑝 q∩𝑞).𝑄𝑞 q∈𝑝⇒𝑥∉fv(𝑈)𝑓∉fv(𝑈) 𝑝⊆𝜑 𝑟⊆ q𝜑,𝑥,𝑓 𝑄 =𝑈𝑟 Γ𝜑⊢𝑡[𝑇𝑝]:𝑄[𝑇𝑝/𝑋𝑥,𝑞/𝑓](t-tapp-fresh) Fig. 5. Typing rules of 𝜆◦<:. Differences from Wei et al .[2024] are highlighted in gray boxes . The gray rules are directly taken from Wei et al. [2024] for comparison purposes, and are not a part of 𝜆◦<:. t-sassgn applies only when the assigned term’s qualifier does not refer to the assignee itself. When the assignee is a non-cyclic reference, the assignment rule follows the same semantics as t-assgn in Wei et al .[2024]’s system. Unlike t-assgn , which applies only to non-cyclic references, t-sassgn generalizes assignment to cyclic references as well. As a consequence, when assigning to a cyclic reference, the bound variable xin its referent qualifier is ignored. To ensure that the assigned term remains well-formed, the bound variable must not appear in the qualifier of the assigned term ( 𝑞⊖𝑥). Fort-sassgn-v , the assignee must be a cyclic reference. In this case, assignment becomes more complex, as it allows values to reach the reference’s outer qualifier. The system permits this assignment only when the assignee is a single variable and the assigned term has a singleton qualifier matching the assignee’s name. Allowing assignment without enforcing a variable-form assignee and a matching singleton qualifier, as in t-sassgn-err (see Section 2.2), would enable assignments with arbitrary qualifiers, violating the intended type discipline. This is because q-sub allows arbitrary upcasting of a reference’s outer qualifier, and including a rule like t-sassgn-err would lead to inconsistencies in qualifier tracking. Page 13: Complete the Cycle: Reachability Types with Expressive Cyclic References 13 Subtyping Γ⊢𝑞<:𝑞Γ⊢𝑇<:𝑇Γ⊢𝑄<:𝑄 Γ⊢𝐵<:𝐵(s-base) Γ⊢𝑇<:𝑆Γ⊢𝑆<:𝑈 Γ⊢𝑇<:𝑈(s-trans)Γ⊢𝑆<:𝑇Γ⊢𝑇<:𝑆 𝑞⊆dom(Γ) Γ⊢𝝁𝑧.Ref[𝑆𝑝]𝑞<:𝝁𝑧.Ref[𝑇𝑝]𝑞(s-ref) Γ⊢𝑃<:𝑂 Γ, 𝑓:(𝑓(𝑥:𝑂)→𝑄)q,𝑥:𝑃⊢𝑄<:𝑅 Γ⊢𝑓(𝑥:𝑂)→𝑄<:𝑓(𝑥:𝑃)→𝑅(s-fun) 𝑝⊆𝑞⊆ qdom(Γ) Γ⊢𝑝<:𝑞(q-sub) Γ⊢𝑞1<:𝑞2 Γ⊢𝑝,𝑞1<:𝑝,𝑞2(q-cong)𝑓:𝑇𝑞∈Γq∉𝑞 Γ⊢𝑞,𝑓<:𝑓(q-self) 𝑥:𝑇𝑞∈Γq∉𝑞 Γ⊢𝑥<:𝑞(q-var)𝑋𝑥<:𝑇𝑞∈Γq∉𝑞 Γ⊢𝑝,𝑥<:𝑝,𝑞(q-qvar) 𝑋𝑥<:𝑇𝑞∈Γ Γ⊢𝑋<:𝑇(s-tvar) Γ⊢𝑝<:𝑞Γ⊢𝑞<:𝑟 Γ⊢𝑝<:𝑟(q-trans)Γ⊢𝑆<:𝑇 Γ⊢𝑝<:𝑞 Γ⊢𝑆𝑝<:𝑇𝑞(sq-sub) Fig. 6. Subtyping rules of 𝜆◦<:. Transitive Lookup 𝑞{𝑛 Γ𝑞{Γ 𝑞{0 Γ:=𝑞 Qualifier Zero-step Transitive Lookup 𝑞{1 Γ:=Ð (𝑥∈𝑞∧𝑥:𝑇𝑝∈Γ)𝑝∪𝑞 Qualifier One-Step Transitive Lookup 𝑞{𝑛+1 Γ:=(𝑞{1 Γ){𝑛 ΓQualifier Multi-Step Transitive Lookup 𝑞{Γ:=𝑞{|Γ| ΓQualifier Full Transitive Lookup Qualifier Notations satΓ𝑞 :=𝑞{Γ=𝑞 Qualifier Saturation Γ⊢𝑝 q∩𝑞:= q(𝑝{Γ∩𝑞{Γ) Qualifier OverlapQualifier Cardinality |𝑞|Γ |𝑞|∅ :=0 |𝑞|(Γ,𝑥:𝑄):=1+|𝑞|Γ if𝑥∈𝑞 |𝑞|(Γ,𝑥:𝑄):=|𝑞|Γ otherwise Fig. 7. Qualifier Transitive Lookup. Why, then, is it safe to restrict assignment to term forms that are variables? By t-var , a variable is always assigned a singleton qualifier that matches its name. Although this variable’s qualifier can be upcasted arbitrarily, the singleton qualifier is its most precise tracking prior to any upcasting. Thus, restricting the assigned term’s qualifier to a matching singleton ensures that it refers to the intended reference and cannot be widened to include other resources. In summary, for cyclic reference assignment, we determine the assigned term’s qualifier based on the assignee’s term form, rather than its qualifier. Unlike qualifiers, which can be upcasted, term forms remain fixed, ensuring correctness in assignment. We find that t-sassgn-v achieves a balance between correctness and precision while successfully supporting cyclic reference assignment. 3.2.4 Application Rules. Similar to Wei et al .[2024],𝜆◦ <:defines two variants of the application rule: t-app for precise applications ( i.e.“non-fresh”) and t-app-fresh for growing applications ( i.e. “fresh”). Page 14: 14 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf Term Typing (with Store Typing) [Γ|Σ]𝜑⊢𝑡:𝑄 ℓ∈ Loc Locations 𝑡 ::=···|ℓ Terms 𝑣 ::=𝜆𝑓(𝑥).𝑡|𝑐|ℓ|unit|Λ𝑓(𝑋𝑥).𝑡 Values 𝑝,𝑞,𝑟∈ P fin(Var⊎Loc⊎{q}) Qualifiers 𝜑∈ P fin(Var⊎Loc) Observations Σ ::=∅|Σ,ℓ:𝑇𝑞|Σ,ℓ:𝝁𝑥.𝑇𝑞,𝑥Store Typing {Loc} :={{ℓ}|ℓ∈Loc} Singleton Location Qualifiers P1 :={Var}⊎{ Loc} Singleton Qualifiers Σ(ℓ)=𝑇𝑞𝑞⊆dom(Σ) fv(𝑇)=∅ftv(𝑇)=∅𝑞,ℓ⊆𝜑 [Γ|Σ]𝜑⊢ℓ:Ref[𝑇𝑞]ℓ(t-loc)Σ(ℓ)=𝝁𝑥.𝑇𝑞,𝑥𝑞⊆dom(Σ) fv(𝑇)=∅ftv(𝑇)=∅𝑞,ℓ⊆𝜑 [Γ|Σ]𝜑⊢ℓ:𝝁𝑥.Ref[𝑇𝑞,𝑥]ℓ(t-sloc) [Γ|Σ]𝜑⊢𝑡1:(𝑓(𝑥:𝑇𝑝)→𝑄)𝑞 [Γ|Σ]𝜑⊢𝑣:𝑇𝑝𝑄=𝑈𝑟 𝑟⊆q,𝜑,𝑥,𝑓𝑝∉P1⊎{∅}⇒𝑣≠ℓ [Γ|Σ]𝜑⊢𝑡1𝑣:𝑄[𝑝/𝑥,𝑞/𝑓] (t-app-val)[Γ|Σ]𝜑⊢ℓ:𝝁𝑥.Ref[𝑇𝑞]𝑝,ℓ [Γ|Σ]𝜑⊢𝑡2:𝑇𝑞,ℓq∉𝑞 𝑥∈𝑞 [Γ|Σ]𝜑⊢𝑡1B𝑡2:Unit∅ (t-sassgn-l) Well-Formed Stores Σok ∅ok(st-emp)Σok fv(𝑇)=∅ftv(𝑇)=∅𝑞∈dom(Σ)ℓ∉dom(Σ) Σ, ℓ:𝑇𝑞ok(st-con) Σok fv(𝑇)=∅ftv(𝑇)=∅𝑞∈dom(Σ)ℓ∉dom(Σ) Σ,ℓ:𝝁𝑥.𝑇𝑞,𝑥ok(st-scon) Reduction Contexts, Stores 𝐶::=□|𝐶𝑡|𝑣𝐶|ref𝐶|!𝐶|𝐶:=𝑡|𝑣:=𝐶|𝐶[𝑄]𝜎::=∅|𝜎,ℓ↦→𝑣 Reduction Rules 𝑡|𝜎→𝑡|𝜎 𝐶[(𝜆𝑓(𝑥).𝑡)𝑣]|𝜎→𝐶[𝑡[𝑣/𝑥,(𝜆𝑓(𝑥).𝑡)/𝑓]]|𝜎 (𝛽) 𝐶[ref𝑣]|𝜎→𝐶[ℓ]|(𝜎,ℓ↦→𝑣) ℓ∉dom(𝜎) ( ref) 𝐶[!ℓ]|𝜎→𝐶[𝜎(ℓ)]|𝜎 ℓ ∈dom(𝜎) ( deref) 𝑡𝐶[ℓ:=𝑣]|𝜎→𝐶[unit]|𝜎[ℓ↦→𝑣] ℓ∈dom(𝜎) ( assign) 𝐶[(Λ𝑓(𝑋𝑥).𝑡)𝑄]|𝜎→𝐶[𝑡][𝑄/𝑋𝑥,(Λ𝑓(𝑋𝑥).𝑡)/𝑓]|𝜎 (𝛽𝑇) Fig. 8. Extension with store typings and call-by-value reduction for 𝜆◦<:. Store typing for cyclic references are highlighted in gray boxes . In contrast to Wei et al .[2024], we do not require saturated qualifiers on well-formed stores. t-app applies to non-fresh applications, where the argument’s qualifier is fully observable and explicitly specified. In this case, the function return type can depend on the function argument qualifier, and the application performs a deep, precise substitution on the argument qualifier. To ensure correct deep substitution of qualifiers in the presence of cyclic references, we impose an additional constraint: the argument qualifier must not appear in the return type, unless it belongs to a restricted set of qualifiers – optional singleton qualifiers ( i.e.∈P 1⊎∅) – which permit deep substitution. Page 15: Complete the Cycle: Reachability Types with Expressive Cyclic References 15 If the argument does not appear in the return type, type preservation is trivially maintained since no type-level substitution is required. If the argument qualifier does appear in the return type, it must be an optional singleton to ensure valid deep substitution. Allowing deep substitution of non-singleton qualifiers in function return types could lead to inconsistent typing, violating type preservation (see Section 3.5). This constraint limits expressiveness but is necessary to preserve type soundness. We further justify this limitation in Section 6.2. Deep substitution remains valid under the following cases, where the argument qualifier is: (1) an empty qualifier ( 𝑝∈{∅} ), or (2) a singleton qualifier ( 𝑝∈P 1). Thus, when the argument qualifier is an optional singleton, deep substitution in t-app remains valid because the qualifier is small enough to be directly substituted using the substitution lemma. t-app-fresh extends the constraints of t-app to fresh applications, enforcing the same non- occurrence constraint when the qualifier is not an optional singleton. Additionally, a similar restriction applies to applications involving store locations (see Section 3.3). 3.2.5 Type Polymorphism. t-tapp andt-tapp-fresh extend the type application rule to support type and qualifier polymorphism, where a type abstraction can be typed with t-tabs . Unlike function applications, type applications impose no restrictions on the argument qualifier, as types do not appear on the left-hand side of assignment operations, eliminating concerns about improper substitution. 3.3 Dynamic Typing The𝜆◦ <:-calculus follows standard call-by-value reduction for the 𝜆-calculus with mutable references. A store and a store typing track the values, types, and qualifiers associated with each location. References reduce to fresh locations with their types and qualifiers recorded in the store typing (seet-loc andt-sloc ). Assignment statements evaluate to a unit value while updating the store. Additionally, t-sassgn-l introduces a dynamic typing rule for cyclic assignments, where the assignee is a single location. Function applications reduce to the function body via 𝛽-reduction, replacing occurrences of the function argument with a concrete value. t-app-val extends typing to applications within abstraction bodies at runtime, where an argument variable is substituted with a value. As in t-app , the optional singleton qualifier constraint applies to argument qualifiers. Singleton qualifiers now also extend to singleton location qualifiers (see Figure 8). When the argument qualifier is notan optional singleton, the argument must not be a single location, as demanded by the substitution lemma (see Section 3.5.2). The call-by-value semantics allows us to relax the static typing constraint on the non-occurrence of the argument qualifier in the function’s return type ( i.e.𝑥∉fv(𝑈)), as per t-app . Instead, we impose a weaker requirement: the argument must not be a location value ( i.e.𝑣≠ℓ). This restriction prevents improper substitution by ensuring locations always have their corresponding singleton qualifier when applied to abstractions. In contrast, static typing must impose the non-occurrence constraint because arguments may include arbitrary terms beyond values, and their types may involve type abstractions, which cannot be checked syntactically. Unlike𝜆q,𝜆◦ <:drops the saturation constraint for qualifiers in the store, extending store typing to support both cyclic references and non-cyclic references. 3.4 Precise Transitive Closure Computation In Wei et al .[2024]’s mechanization, the concept of transitive closure is expressed indirectly via a “saturation” predicate, which specifies that a qualifier will reach no more than itself through Page 16: 16 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf the corresponding store. In conjunction with universal quantification, one can approximate the transitive closure of qualifier 𝑝as asaturated superset of a𝑝. We revise this definition by redefining the transitive closure deterministically , using a “fuel” value that is set to the store length to ensure termination and facilitate reasoning, even in the presence of circular pointers in the context and store typing. We argue that this approach is more precise since it pinpoints the exact qualifier instead of specifying a range of qualifiers that is larger than its transitive closure. Although it is possible to make the above definition precise by specify the transitive closure as the smallest saturated superset of a qualifier, it involves second order universal quantification, and can complicate both the specification and the reasoning process. The transitive closure computation is generalized over both the context and the store typing, allowing code reuse in both t-app-fresh and the preservation of separation lemma. We define standard commutativity and distributivity of the transitive closure with respect to other operations on sets and qualifiers ( e.g.splice, substitution, etc.). We show that the computational definition subsumes the saturation by redefining the saturation predicate using the deterministic transitive closure computation. 3.5 Metatheory 3.5.1 Transitive Closure Computation. We define the concept of cardinality on qualifiers to capture the number of variables that is contained in a qualifier (See Section 3). Using cardinality, we establish a mapping between cardinality and qualifier saturation. Lemma 3.1 (Cardinality Monotonicity). If𝑞1⊆𝑞2, then|𝑞1|Γ≤|𝑞2|Γ. Proof. By induction on the typing environment, with case analysis in the inductive case on whether the qualifier contains the top element. □ Lemma 3.2 (Cardinality Max). |𝑞|Γ≤|Γ|. Proof. By induction on the typing environment, with case analysis in the inductive case on whether the qualifier contains the top element. □ Lemma 3.3 (Zero Cardinality Saturated). If|𝑞|Γ=0, Then satΓ𝑞. Proof. By induction on Γ. □ Lemma 3.4 (Cardinality and Sub-qalifier Preservation). If|𝑞1|Γ=|𝑞1∪𝑞2|Γ, then𝑞1{1 Γ ∪𝑞2{1 Γ=𝑞1{1 Γ∪𝑞2. Proof. By Lemma 3.1, we have |𝑞1|Γ≤|𝑞1∪𝑞2|Γ, By induction on the typing environment and with case analysis on whether the qualifiers contain the top element, in each case we either apply the induction hypothesis or derive a contradiction. □ Lemma 3.5 (Transitive Lookup Monotone). 𝑞⊆Γ{𝑞 𝑛. Proof. By induction on 𝑛. □ Lemma 3.6 (Cardinality Increment or Saturation). If𝑞′=𝑞{Γ𝑛, then|𝑞|Γ+𝑛≤|𝑞′|Γor satΓ𝑞′. Proof. We first prove the case for 𝑛=1and then proceed by induction on 𝑛. For the base case, we use Lemma 3.5 and Lemma 3.1 to establish the left disjunct. For the inductive step, we apply the induction hypothesis and then invoke the case for 𝑛=1. □ Lemma 3.7 (Full Transitive Lookup Total). If𝑛≥|Γ|, then𝑞{𝑛 Γ=𝑞{|Γ| Γ. Page 17: Complete the Cycle: Reachability Types with Expressive Cyclic References 17 Proof. Applying Lemma 3.6 to 𝑞with𝑛, we consider two cases: (1) Cardinality is increasing: This contradicts Lemma 3.2. (2)𝑞is saturated: We analyze the cardinality value: •If it is zero, we apply Lemma 3.3. •If it is nonzero, we apply Lemma 3.2 to derive a contradiction. □ 3.5.2 Substitution Lemma. Lemma 3.8 (Substitution preserves transitive lookup). If𝑥:𝑇𝑞∈Γ, and𝑝,𝑞⊆ qdom(Σ), and𝑝∩ q𝜑⊆𝑞, and𝑟{Γ⊆ q𝜑, then under substitution 𝜃=[𝑝/𝑥], 𝑟𝜃{Γ𝜃⊆𝑟{Γ𝜃. Proof. We proceeds by applying transitivity of subtyping, followed by commutativity of transi- tive lookup under substitution, monotonicity of qualifier substitution, and environment weakening properties. The proof concludes by applying subqualifier transitivity and narrowing arguments. □ Lemma 3.9 (Top-Level Term Substitution). Suppose the following typing judgments hold: [𝑥:𝑇𝑞,Γ|Σ]𝜑⊢𝑡:𝑄,[∅|Σ]𝑝⊢𝑣:𝑇𝑝. Additionally, assume: 𝑝,𝑞⊆ qdom(Σ), 𝑝∩ q𝜑⊆𝑞, 𝑞=𝑝∨𝑞= q(𝑝∩𝑟)∨(𝑞=ℓ∨𝑞= q(ℓ∩𝑟))∧𝑇=𝝁𝑥.Ref[𝑈𝑤]𝑝, (∃ℓ,𝑣=ℓ)→𝑝=ℓ. Then, under substitution 𝜃=[𝑝/𝑥], we have: [Γ𝜃|Σ]𝜑𝜃⊢𝑡[𝑣/𝑥]:𝑄𝜃. Proof. We proceed by induction on the derivation [𝑥:𝑇𝑞,Γ|Σ]𝜑⊢𝑡:𝑄. In the case of t-app-fresh , the induction hypothesis requires Lemma 3.8 to establish (𝑝 q∩𝑞)𝜃⊆ 𝑝𝜃 q∩𝑞𝜃. In the case of t-sassgn-v , we perform case analysis on the variable assignee. If the variable is the one being substituted, we use the fact that the substituted value is a reference, allowing us to conclude that it is a location. We then apply t-sassgn-l to complete the case. If the variable is different from the one being substituted, the proof follows directly from the induction hypothesis. Other cases follow straightforwardly from the induction hypothesis. □ The condition 𝑞=𝑝∨𝑞= q(𝑝∩𝑟)∨(𝑞=ℓ∨𝑞= q(ℓ∩𝑟))∧𝑇=𝝁𝑥.Ref[𝑈𝑤]𝑝 captures the four possible cases of substitution: (1)Precise substitution (𝑞=𝑝): The assumed qualifier 𝑞for𝑥matches the value’s qualifier 𝑝. This occurs for function parameters in t-app or for a function’s self-reference 𝑓int-app andt-app-fresh . (2)Growing substitution (𝑞= q(𝑝∩𝑟)): This applies in t-app-fresh , where the argument qualifier𝑝overlaps with the function qualifier 𝑟, growing the result by 𝑝\𝑟{Γ. (3)Precise substitution with a location qualifier (𝑞=ℓ): A single location qualifier can be used similarly to case (1). Page 18: 18 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf (4)Growing substitution with a location qualifier (𝑞= q(ℓ∩𝑟)): Analogous to case (2), but using a location qualifier. Cases (3) and (4) apply only when the argument type is a reference type. Since cyclic assignment ( t-sassgn-v ) can occur inside an abstraction body, if the assigned term’s qualifier contains the function argument qualifier, the latter must be substituted with an optional singleton qualifier to ensure that the cyclic assignment remains well-typed after qualifier substitution. As we consider only top-level, closed values in substitution, this constraint becomes relevant only when the substituted term is a location value ( e.g.ℓ), as it could potentially serve as the assignee in a cyclic assignment operation. This requirement is captured by the premise (∃ℓ,𝑣=ℓ)→𝑝=ℓ. 3.5.3 Main Soundness Result. Theorem 3.10 (Progress). If[∅|Σ]𝜑⊢𝑡:𝑄andΣok, then either 𝑡is a value, or for any store 𝜎where[∅|Σ]𝜑⊢𝜎, there exists a term 𝑡′and store𝜎′such that𝑡|𝜎→𝑡′|𝜎′. Proof. By induction over the derivation [∅|Σ]𝜑⊢𝑡:𝑄. □ Similar to [Wei et al. 2024], reduction preserves types up to qualifier growth: Theorem 3.11 (Preservation). If[∅|Σ]𝜑⊢𝑡:𝑇𝑞, and[∅|Σ]𝜑⊢𝜎, and𝑡|𝜎→𝑡′|𝜎′, andΣok, then there exists Σ′⊇Σ,𝜑′⊇𝜑∪𝑝, and𝑝⊆dom(Σ′\Σ)such that[∅|Σ′]𝜑′⊢𝜎′and [∅|Σ′]𝜑′⊢𝑡′:𝑇𝑞[𝑝/q]. Proof. We proceed by induction on the derivation [∅|Σ]𝜑⊢𝑡:𝑇𝑞. Fort-app , we distinguish two cases: 1. If the argument qualifier is an optional singleton, we apply the substitution lemma directly using the typing derivation from the hypothesis. 2. If the argument qualifier is larger than an optional singleton, we first derive the non-occurrence assumption for the argument qualifier in the function return type. This ensures that the return qualifier remains preserved after stepping. We then construct a separate typing derivation for 𝑡 with a qualifier 𝑤that is more precise than 𝑝. In particular, if 𝑡is a location ℓ, then𝑟=ℓ. Using this refined typing derivation, we apply the substitution lemma (Lemma 3.9), thereby completing the case. □ Corollary 3.12 (Preservation of Separation). Sequential reduction of two terms with disjoint qualifiers preserve types and disjointness: [∅|Σ]dom(Σ)⊢𝑡1:𝑇𝑞1 1𝑡1|𝜎→𝑡′ 1|𝜎′∅|Σ⊢𝜎 Σok [∅|Σ]dom(Σ)⊢𝑡2:𝑇𝑞2 2𝑡2|𝜎′→𝑡′ 2|𝜎′′𝑞1 q∩𝑞2⊆{q} ∃𝑝1𝑝2Σ′Σ′′.[∅|Σ′]dom(Σ′)⊢𝑡′ 1:𝑇𝑝1 1Σ′′⊇Σ′⊇Σ [∅|Σ′′]dom(Σ′′)⊢𝑡′ 2:𝑇𝑝2 2𝑝1 q∩𝑝2⊆{q} Proof. By sequential application of Preservation (Theorem 3.11) and the fact that a reduction step increases the assigned qualifier by at most a fresh new location, thus preserving disjointness. □ The Progress and Preservation in Parallel Reduction corollary is ommitted due to space limitation. Page 19: Complete the Cycle: Reachability Types with Expressive Cyclic References 19 4 Case Study: A Fixed-point Combinator In this section, we present a case study demonstrating how cyclic reference types enable the implementation of a general fixpoint operator, allowing functions to define themselves recursively without explicit recursion. As in system Fq <:, our system supports type polymorphism, allowing functions and references to be parameterized over types while ensuring type safety. We implement a general fixpoint operator through the store, following Kiselyov [2020]. The fixpoint operator is defined as follows: deffix[T] (f: (g: (T -> T)q-> (T -> T)g)) : (T -> T)q= { valc = newRef (x => x) // : 𝝁𝑧.Ref[(T -> T)z]c c := f((n:T) => (!c)(n)) // : (T -> T)c !c } The key idea is to use a reference to hold the function being defined recursively, ensuring that it can be updated as needed. The fixpoint operator is polymorphic over type T, making it applicable to recursive computations on arbitrary data types. The function fis a higher-order function passed as an argument to the fixpoint operator, performing a “one-step” computation, using its first argument g(of type T -> T ) as the function that it refines recursively. Within the function body, we complete the recursive definition by performing the following steps: (1)Initializing the cyclic reference ( c).We create a reference cof typeT -> T , initially holding the identity function (x => x) as a placeholder, ensuring type correctness and that the reference can be safely dereferenced before being updated. (2)Defining the helper function ( f2).The function f2is a wrapper around c, retrieving its current value ( !c) and applying it to the argument n. Sincecwill later be updated to hold the final recursive function, f2essentially acts as a proxy to dynamically retrieve and apply the most up-to-date version of the function. (3)Updating cwith the recursive function. We apply ftof2, allowing fto construct the recursive function by invoking f2as needed. The result of this computation ( f(f2) ) is then stored in c, ensuring f2retrieves the updated definition at the next recursive step. (4)Returning the fixpoint. The fixpoint operator finally returns the dereferenced value of c, which now holds the fully-defined recursive function. Any subsequent calls to the function returned by fixwill now correctly apply the recursively computed function. Unlike explicit recursive definitions, this approach enables recursion through mutable, cyclic references, allowing functions to be defined incrementally. This makes it particularly useful in settings where recursion needs to be established dynamically, such as in languages without native support for recursion or when defining mutually recursive functions. One possible instantiation of the fixpoint operator is an infinite loop. In this case, the fixpoint oper- ator is instantiated with type Unit, and the “one-step” computation is a function that unconditionally applies its first argument to its second argument. defloop_fix[Unit](g: Unit -> Unit): Unit -> Unit = n => g(n) fix[Unit](loop _fix)(()) // infinite loop To demonstrate more practical use cases than infinite loops, we extend the system with integer types and basic arithmetic operations (see Figure 9), enabling us to define a factorial function using the fixpoint operator: deffact_fix(f: Nat -> Nat): Nat -> Nat = x => if(iszero x) then 1 elsex*f (pred x) Page 20: 20 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf Syntax 𝜆◦ N 𝑛 ::= 0|1|··· Numeral Constants 𝑏 ::= true|false Boolean Constants 𝑇 ::=···| Nat|Bool Types 𝑡 ::=···| nat𝑛|succ𝑡|pred𝑡|mul𝑡𝑡|iszero𝑡 |bool𝑏|if𝑡then𝑡else𝑡 Terms Γ ::=... Typing Environments Term Typing Γ𝜑⊢𝑡:𝑄 Γ𝜑⊢𝑛:Nat∅(t-nat) Γ𝜑⊢𝑡:Nat𝑝 Γ𝜑⊢succ𝑡:Nat𝑝(t-succ) Γ𝜑⊢𝑡1:Nat𝑝Γ𝜑⊢𝑡2:Nat𝑞 Γ𝜑⊢mul𝑡1𝑡2:Nat𝑝,𝑞(t-mul)Γ𝜑⊢𝑡:Nat𝑝 Γ𝜑⊢iszero𝑡:Bool∅(t-iszero) Γ𝜑⊢𝑡:Nat𝑝 Γ𝜑⊢pred𝑡:Nat𝑝(t-pred) Γ𝜑⊢𝑏:Bool∅(t-bool) Γ𝜑⊢𝑡1:Bool𝑝Γ𝜑⊢𝑡2:𝑇𝑞Γ𝜑⊢𝑡3:𝑇𝑟 Γ𝜑⊢if𝑡1then𝑡2else𝑡3:𝑇𝑞,𝑟(t-if) Reduction Contexts, Values 𝐶::=□|succ𝐶|pred𝐶|mul𝐶𝑡|mul𝑡𝐶|iszero𝐶|if𝐶then𝑡else𝑡Reduction Contexts 𝑣::=nat𝑛|bool𝑏 Values Reduction Rules 𝑡|𝜎→𝑡|𝜎 𝐶[succ nat𝑛]|𝜎→𝐶[nat(𝑛+1)]|𝜎 (succ) 𝐶[mul nat𝑛1nat𝑛2]|𝜎→𝐶[nat(𝑛1×𝑛2)]|𝜎 (mul) 𝐶[pred nat𝑛]|𝜎→𝐶[nat(max(0,𝑛−1))]|𝜎(pred) 𝐶[iszero nat𝑛]|𝜎→𝐶[bool(𝑛=0)]|𝜎 (iszero) 𝐶[if bool true then 𝑡1else𝑡2]|𝜎→𝐶[𝑡1]|𝜎 (if-true) 𝐶[if bool false then 𝑡1else𝑡2]|𝜎→𝐶[𝑡2]|𝜎 (if-false) Fig. 9. Typing rules, reduction contexts, and reduction rules for natural numbers and boolean expressions in𝜆◦<:. valn : Nat = ... fix[Nat](fact _fix)(n) // compute n! Although in both case studies, we specialize the fixpoint operator with untracked types ( e.g.Unit orNat), the system supports reachability polymorphism, allowing the fixpoint operator to be used with more complex types , including closures. This extends its applicability beyond simple base types to functions that capture references, enabling more advanced recursive computations. All examples in this section are type-checked in Coq, and implemented in Scala. 5 Related Work Reachability Types .RT provide a structured way to track ownership and aliasing in higher- order programs, enabling precise reasoning about resource sharing and separation. Page 21: Complete the Cycle: Reachability Types with Expressive Cyclic References 21 The initial work on RT is presented in Bao et al .[2021], where tracked reachability sets enable ownership-style reasoning for higher-order languages. They demonstrate the system’s ability to integrate with a flow-sensitive effect system and express diverse programming patterns. Polymor- phic Reachability Types [Wei et al .2024] enhance RT by introducing reachability polymorphism, enabling more precise tracking of fresh resources and improving the expressiveness of ownership reasoning in higher-order settings. Based on Wei et al .[2024]’s polymorphic calculus, we introduce cyclic reference types, enabling recursive constructs without built-in mechanisms. Our system extends non-cyclic references to generalize the semantics introduced in Wei et al .[2024], providing additional flexibility for cyclic structures. Unlike previous work which focused on non-cyclic reference tracking, our system introduces cyclic reference types, enabling recursive constructs without modifying the core type system. We also refine the reference introduction rule to increase precision and allow flexible graph structures with nested references (see Section 2.4). Following Dependent Object Types (DOT) [Amin et al .2016; Rompf and Amin 2016], RT functions track their captured variables via self-references, ensuring precise tracking of shared resources. In principle, function self-references could be used within the function body to encode non-terminating recursions ( e.g.def f() = f() ), making recursion a built-in feature. Instead, we explicitly enable cycles through store locations, allowing cyclic references to model recursion without having recursion as a primitive mechanism. Bao et al .[2023] formalize RT using logical relations to prove key properties, including termi- nation even in the presence of higher-order state, which is a key premise for our work to build on. Graph IR [Bračevac et al .2023] integrates RT to improve alias analysis and optimize impure higher-order programs by tracking fine-grained dependencies with an effect system. Jia et al .[2024] address key challenges in self-references within Rust-like systems by proposing an enhanced notion of subtyping and developing a sound and decidable bidirectional typing algorithm for reachability types. Fixed-point Combinator .The origin of the fixed-point combinator can be traced to computabil- ity theory [Rogers 1967; Sangiorgi 2009], which characterizes the computational power of recursive functions. Bekić [1984] formalizes recursion using fixed-point constructions, demonstrating that all definable operations arise as fixed points of monotonic functions. Landin’s Knot [Landin 1964] encodes mutual recursion through self-application using mutable reference cells, a concept that later influenced cyclic references in this work. Goldberg [2005] generalizes Curry’s fixed-point combinator to handle variadic mutually-recursive functions. Kise- lyov [2020] delves into the diverse manifestations and applications of fixed-point combinators in computation. Their approach is particularly relevant to this work, as it provides a structured way to express recursion through a store using cyclic references. Our approach to cyclic references also draws inspiration from Landin’s Knot, and our case studies further explore the deep connection between recursion and fixed-point constructs. While Koronkevich and Bowman [2022] restricts non-termination in higher-order reference systems via environment quantification, our work deliberately enables controlled non-termination, leveraging cyclic references for recursion modeling. Separation .Separation Logic [Reynolds 2002] provides a formal framework for local, spatial reasoning about mutable heap structures, utilizing a separating conjunction operator to enforce memory disjointness. RT [Bao et al .2021; Wei et al .2024] incorporates principles of Separation Logic, particularly in its application type rule ( t-app-fresh ), where the overlap operator ensures disjointness between function and argument qualifiers, maintaining separation guarantees in type reasoning. In this work, we reuse [Wei et al .2024]’s notion of separation expressed by the Page 22: 22 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf overlap operator (see Section 3) in t-app-fresh . Unlike previous approaches that rely on universally quantified saturated upper bounds, we use an algorithmic transitive closure method to compute qualifier overlap, yielding greater precision in qualifier reasoning (see Section 3.4). Ensuring static separation is crucial for safe concurrent programming. Capture Separation Calculus (CSC) [Xu et al .2023, 2024] extends Capture Calculus (CC) [Boruch-Gruszecki et al . 2023] to enforce static separation and data race freedom, ensuring non-interference of concurrently executing threads. De Vilhena and Pottier [2021] extend separation logic with built-in effect handlers to reason about cooperative concurrency and stateful computations, guaranteeing safe access to heap-allocated mutable state. Recursive Types and Existential Types .Alias Types [Smith et al .2000] extends linear types with aliasing to enable efficient and safe memory management, leveraging existential types to abstract specific memory locations. Walker and Morrisett [2000] employ existential types to capture memory shape information, particularly focusing on the typing of recursive data structures through parameterized recursive types that represent circular references. Ahmed et al .[2007] further utilize existential types to abstract memory locations, whereas Grossman et al .[2002] employ them to implement closures, where function pointers are paired with existentially quantified environments to enforce region bounds and ensure region liveness. In contrast, our approach introduces a “quasi-existential” qualifier with a semantics akin to that of recursive self types in DOT [Amin et al .2016; Rompf and Amin 2016], where the identity of the parent reference is retained. We deliberately avoid existential types in the context of cyclic references, as they fail to preserve the identity of the cyclic reference, leading to a loss of precision. For example, dereferencing (see Section 3.2.2) the same cyclic reference modeled by existential types multiple times would produce values that appear separate, even though they originate from the same reference. Regions, Ownership, and Substructural Type Systems .Milano et al .[2022] introduce a system to guarantee separation and safety in concurrent programs, combining linear typing, and region- based memory management. However, while their work focuses on thread-level separation via region types, RT address higher-order functions, providing fine-grained alias tracking at the level of individual resources. Tofte and Talpin [1997] use regions to enforce sound life-time management, proving semantic equivalence between source and target semantics, ensuring the absence of use- after-free error. While their primary goal is a sound region inference algorithm for safe deallocation, our work prioritizes soundness and separation, particularly in the presence of cyclic references and recursive constructs. However, region-based guarantees such as deallocation safety can still be achieved within RT by layering an effect system [Bao et al. 2021]. Haller and Odersky [2010] propose a capability-based system that enforces at-most-once con- sumption of unique references while allowing flexible borrowing. Linear Haskell [Bernardy et al . 2018] extends Haskell’s type system with linear types, providing fine-grained control over resource usage. Capabilities and Path Dependent Types, and Qualified Types .Dependent Object Types (DOT) [Rompf and Amin 2016] is formal model of a subset of the Scala type system with proven soundness guarantee. One analogous feature of DOT with this work is that it uses term-level recursive self types . DOT imposes restriction on dependent application, where arguments are required to be of variable form, similar to t-sassgn-v in this work (see Sections 2.2 and 3.2). However, recursive self types in DOT are used to access member types, while RT use the self- referential variable in cyclic reference for qualifier tracking. Rapoport and Lhoták [2017] extend DOT with mutable reference cells, proving the soundness of their system. However, their types Page 23: Complete the Cycle: Reachability Types with Expressive Cyclic References 23 remain unqualified, making it unsuitable for reachability tracking. Dort and Lhoták [2020] extend Dependent Object Types (DOT) with reference mutability system to enable fine-grained access control on references and provide immutability guarantees. Dort [2024] focuses on side effect free (SEF) function types, ensuring function purity statically. Capturing Types (CT) [Boruch-Gruszecki et al .2023] is a type system implemented in Scala, designed to track captured capabilities. While CT makes use of boxing/unboxing operations, inspired by contextual modal type theory (CMTT) [Nanevski et al .2008], RT’s use of the qmarker eliminates the need of boxing and unboxing, allowing for finer-grained types that precisely model functions returning fresh values. Qualified types have been widely adopted to perform safety analysis such as const qualifier inference in system-level languages [Foster et al .2006], reference immutability in Java [Huang et al . 2012], and polymorphic type systems supporting higher-order functions [Lee and Lhoták 2023]. 6 Limitation and Future Work This section outlines three categories of limitations in our work. First, we discuss the intrinsic limitations ofour solution with respect to its goal of adding expressive cyclic references (Section 6.1). Specifically, we prevent the formation of cyclic structures across multiple “hops”. Second, we highlight limitations that our approach introduced on the base system (Section 6.2). We focus on restrictions in deep substitution for function applications. While these constraints ensure soundness, they limit expressiveness in certain cases. Finally, we examine limitations inherited from prior work (Section 6.3). Particularly, the invariance of reference types restricts the ability of references capturing local resources to escape their scope. While 𝜂-expansion offers a workaround, a more refined subtyping mechanism for escaping self-references remains an open research challenge. 6.1 Limitations of Our Solution One limitation of our solution is that it does not provide a way to construct deeply nested cyclic references that contain multiple “hops” through the store. For example, consider the type 𝝁𝑧.Ref[𝝁𝑥.Ref[𝑇𝑧]] Here, the inner referent’s qualifier refers to the qualifier for its outer parent z, rather than that of its immediate parent x. This kind of multi-hop cycle is uninhabited in our system due to the restricted introduction rule for cyclic reference types. Currently, our introduction rules ensure that self-references must be directly tied to their immediate parent, preventing references from skipping intermediate levels in the store. The challenges involved in supporting deeply nested cyclic references include: (1)Well-formed Condition and Type Soundness : Ensuring that a reference remains well- typed across multiple levels of indirection is nontrivial. A reference must not inadvertently escape its intended scope thus violating well-formedness and soundness. (2)Qualifier Tracking Complexity : When allowing multi-hop cycles, the qualifier tracking mechanism must correctly propagate reachability information across multiple levels. This requires refinements in how qualifier inheritance and upcasting are handled. (3)Assignment Semantics : Enabling assignments to deeply nested cyclic references requires a precise formulation of how reference qualifiers are updated. Without strict control, such assignments could lead to ambiguous or unsound behaviors. Nevertheless, introducing a more expressive introduction form for cyclic reference that supports this form of deeply nested cyclic references would further enhance the expressiveness of the system, and we leave it as a future direction. Page 24: 24 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf 6.2 Limitations Introduced by Our Solution A key limitation introduced by our approach is that deep substitution is no longer fully general in non-fresh function applications ( i.e.t-app ). In prior formulations, deep substitution allowed a function application to substitute its argument deeply within the function body without additional constraints. However, in our system, this behavior is restricted unless the qualifier of the argument is an optional singleton. Specifically, when applying a function in a non-fresh context, we must enforce an additional constraint: the function argument must not appear in the return type of the function. This restriction is similar to the constraint already present in fresh function applications (see Section 3.2.4). The rationale behind this limitation is to ensure consistent qualifier tracking and prevent unintended aliasing, which could otherwise introduce unsound behaviors. Despite this restriction, the practical impact on expressiveness is minimal. Similar to the Depen- dent Object Types (DOT) system [Rompf and Amin 2016], this loss of precision does not significantly hinder usability. In cases where deep substitution is blocked due to this limitation, a straightforward workaround exists: one can introduce an intermediate variable to hold the function argument and then use that variable in the function body to achieve deep substitution. This transformation effectively preserves the intended behavior while maintaining the system’s type safety guarantees. Therefore, while our approach imposes additional constraints on non-fresh function applications, the practical impact is limited, as a simple variable introduction pattern can recover most of the lost flexibility. 6.3 Inherent Limitations from Prior Work Following Wei et al .[2024], reference types in our system are invariant. This invariance implies that once a reference is assigned a qualifier, that qualifier cannot be relaxed or upcasted. A direct consequence of this design is that a reference capturing a local resource cannot escape its original scope, since its qualifier remains tied to the local environment. In contrast, a covariant or con- travariant reference system might allow references to be generalized when escaping their defining scope, but our system enforces strict qualifier tracking to maintain soundness. One possible approach to support escaping references that capture local resources is to introduce a subtyping rule for cyclic references. This rule would allow the inner qualifier to be moved to the outer qualifier, effectively removing the inner qualifier’s local constraints. By doing so, references that originally had local observability constraints could be reinterpreted in a broader context. However, designing a sound and principled subtyping mechanism for self-referential references introduces nontrivial challenges, particularly in ensuring that aliasing constraints and reachability properties remain intact. However, since subtyping of self references upon escape is an orthogonal problem, we leave it as future work. In the meantime, when an escaping reference is required, we reuse the 𝜂-expansion mechanism from Wei et al .[2024].𝜂-expansion allows a reference to be wrapped in an intermediate function that reconstructs the original reference while modifying its qualifier. This technique provides a sound and principled way to simulate reference escape, when subtyping rules for escaping are not available. 7 Conclusion In conclusion, this work presents a variant of the reachability types system that extends its reference typing to allow cyclic references as well as precise, shallow referent qualifier tracking that enable expressive programming patterns such as fixed-point combinators and non-terminating programs. Page 25: Complete the Cycle: Reachability Types with Expressive Cyclic References 25 Acknowledgments References Martín Abadi and Marcelo P. Fiore. 1996. Syntactic Considerations on Recursive Types. In Proceedings, 11th Annual IEEE Symposium on Logic in Computer Science, New Brunswick, New Jersey, USA, July 27-30, 1996 . IEEE Computer Society, 242–252. Amal Ahmed, Matthew Fluet, and Greg Morrisett. 2007. L^3: A Linear Language with Locations. Fundamenta Informaticae 77, 4 (Jan. 2007), 397–449. Nada Amin, Samuel Grütter, Martin Odersky, Tiark Rompf, and Sandro Stucki. 2016. The Essence of Dependent Object Types. In A List of Successes That Can Change the World - Essays Dedicated to Philip Wadler on the Occasion of His 60th Birthday (Lecture Notes in Computer Science, Vol. 9600) , Sam Lindley, Conor McBride, Philip W. Trinder, and Donald Sannella (Eds.). Springer, 249–272. Yuyan Bao, Guannan Wei, Oliver Bračevac, Yuxuan Jiang, Qiyang He, and Tiark Rompf. 2021. Reachability Types: Tracking Aliasing and Separation in Higher-Order Functional Programs. Proc. ACM Program. Lang. 5, OOPSLA (Oct. 2021), 139:1–139:32. Yuyan Bao, Guannan Wei, Oliver Bračevac, and Tiark Rompf. 2023. Modeling Reachability Types with Logical Relations. arXiv:2309.05885 Erik Barendsen and Sjaak Smetsers. 1996. Uniqueness Typing for Functional Languages with Graph Rewriting Semantics. 6, 6 (1996), 579–612. Hans Bekić. 1984. Definable Operations in General Algebras, and the Theory of Automata and Flowcharts. In Programming Languages and Their Definition: H. Bekič (1936–1982) , C. B. Jones (Ed.). Springer, Berlin, Heidelberg, 30–55. Jean-Philippe Bernardy, Mathieu Boespflug, Ryan R. Newton, Simon Peyton Jones, and Arnaud Spiwack. 2018. Linear Haskell: Practical Linearity in a Higher-Order Polymorphic Language. Proc. ACM Program. Lang. 2, POPL (2018), 5:1–5:29. Aleksander Boruch-Gruszecki, Martin Odersky, Edward Lee, Ondřej Lhoták, and Jonathan Brachthäuser. 2023. Capturing Types. ACM Trans. Program. Lang. Syst. 45, 4 (Nov. 2023). Oliver Bračevac, Guannan Wei, Songlin Jia, Supun Abeysinghe, Yuxuan Jiang, Yuyan Bao, and Tiark Rompf. 2023. Graph IRs for Impure Higher-Order Languages: Making Aggressive Optimizations Affordable with Precise Effect Dependencies. Proc. ACM Program. Lang. 7, OOPSLA2 (Oct. 2023), 236:400–236:430. Dave Clarke, Johan Östlund, Ilya Sergey, and Tobias Wrigstad. 2013. Ownership Types: A Survey. In Aliasing in Object- Oriented Programming. Types, Analysis and Verification , Dave Clarke, James Noble, and Tobias Wrigstad (Eds.). Lecture Notes in Computer Science, Vol. 7850. Springer, 15–58. David G. Clarke, James Noble, and John M. Potter. 2001. Simple Ownership Types for Object Containment. In ECOOP 2001 — Object-Oriented Programming , Jørgen Lindskov Knudsen (Ed.). Springer, Berlin, Heidelberg, 53–76. David G. Clarke, John Potter, and James Noble. 1998. Ownership Types for Flexible Alias Protection. In Proceedings of the 1998 ACM SIGPLAN Conference on Object-Oriented Programming Systems, Languages & Applications, OOPSLA 1998, Vancouver, British Columbia, Canada, October 18-22, 1998 , Bjørn N. Freeman-Benson and Craig Chambers (Eds.). ACM, 48–64. Paulo Emílio De Vilhena and François Pottier. 2021. A Separation Logic for Effect Handlers. Proceedings of the ACM on Programming Languages 5, POPL (Jan. 2021), 1–28. Vlastimil Dort. 2024. Pure Methods for roDOT. (2024). Vlastimil Dort and Ondřej Lhoták. 2020. Reference Mutability for DOT. In LIPIcs, Volume 166, ECOOP 2020 , Vol. 166. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 18:1–18:28. Jeffrey S. Foster, Robert Johnson, John Kodumal, and Alex Aiken. 2006. Flow-Insensitive Type Qualifiers. ACM Transactions on Programming Languages and Systems 28, 6 (Nov. 2006), 1035–1087. Jean-Yves Girard. 1987. Linear Logic. Theoretical Computer Science 50 (1987), 1–102. Mayer Goldberg. 2005. A Variadic Extension of Curry’s Fixed-Point Combinator. Higher-Order and Symbolic Computation 18, 3 (Dec. 2005), 371–388. Dan Grossman, Greg Morrisett, Trevor Jim, Michael Hicks, Yanling Wang, and James Cheney. 2002. Region-Based Memory Management in Cyclone. In Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language Design and Implementation (PLDI ’02) . Association for Computing Machinery, New York, NY, USA, 282–293. Philipp Haller and Martin Odersky. 2010. Capabilities for Uniqueness and Borrowing. In ECOOP 2010 – Object-Oriented Programming , Theo D’Hondt (Ed.). Springer, Berlin, Heidelberg, 354–378. John Hogg. 1991. Islands: Aliasing Protection in Object-Oriented Languages. In Proceedings of the Sixth Annual Conference on Object-Oriented Programming Systems, Languages, and Applications, OOPSLA 1991, Phoenix, Arizona, USA, October 6-11, 1991 , Andreas Paepcke (Ed.). ACM, 271–285. Wei Huang, Ana Milanova, Werner Dietl, and Michael D. Ernst. 2012. Reim & ReImInfer: Checking and Inference of Reference Immutability and Method Purity. SIGPLAN Not. 47, 10 (Oct. 2012), 879–896. Page 26: 26 Haotian Deng, Siyuan He, Songlin Jia, Yuyan Bao, and Tiark Rompf Songlin Jia, Guannan Wei, Siyuan He, Yuyan Bao, and Tiark Rompf. 2024. Escape with Your Self: A Solution to the Avoidance Problem with Decidable Bidirectional Typing for Reachability Types. arXiv:2404.08217 [cs] Oleg Kiselyov. 2020. Many Faces of the Fixed-Point Combinator. https://okmij.org/ftp/Computation/fixed-point- combinators.html. Paulette Koronkevich and William J Bowman. 2022. One Weird Trick to Untie Landin’s Knot. (2022). P. J. Landin. 1964. The Mechanical Evaluation of Expressions. Comput. J. 6, 4 (Jan. 1964), 308–320. Edward Lee and Ondřej Lhoták. 2023. Simple Reference Immutability for System F <:.Proceedings of the ACM on Programming Languages 7, OOPSLA2 (Oct. 2023), 857–881. Nicholas D. Matsakis and Felix S. Klock II. 2014. The Rust Language. In Proceedings of the 2014 ACM SIGAda Annual Conference on High Integrity Language Technology, HILT 2014, Portland, Oregon, USA, October 18-21, 2014 , Michael B. Feldman and S. Tucker Taft (Eds.). ACM, 103–104. Mae Milano, Joshua Turcotti, and Andrew C. Myers. 2022. A Flexible Type System for Fearless Concurrency. In PLDI ’22: 43rd ACM SIGPLAN International Conference on Programming Language Design and Implementation, San Diego, CA, USA, June 13 - 17, 2022 , Ranjit Jhala and Isil Dillig (Eds.). ACM, 458–473. Aleksandar Nanevski, Frank Pfenning, and Brigitte Pientka. 2008. Contextual Modal Type Theory. ACM Transactions on Computational Logic 9, 3 (2008), 23:1–23:49. Benjamin C. Pierce. 2002. Types and Programming Languages . MIT Press. Marianna Rapoport and Ondřej Lhoták. 2017. Mutable WadlerFest DOT. Proceedings of the 19th Workshop on Formal Techniques for Java-like Programs (June 2017), 1–6. John C. Reynolds. 2002. Separation Logic: A Logic for Shared Mutable Data Structures. In 17th IEEE Symposium on Logic in Computer Science (LICS 2002), 22-25 July 2002, Copenhagen, Denmark, Proceedings . IEEE Computer Society, 55–74. H. (Hartley) Rogers. 1967. Theory of Recursive Functions and Effective Computability . New York, McGraw-Hill. Tiark Rompf and Nada Amin. 2016. Type Soundness for Dependent Object Types (DOT). SIGPLAN Not. 51, 10 (Oct. 2016), 624–641. Davide Sangiorgi. 2009. On the Origins of Bisimulation and Coinduction. ACM Trans. Program. Lang. Syst. 31, 4 (2009), 15:1–15:41. Frederick Smith, David Walker, and Greg Morrisett. 2000. Alias Types. In Programming Languages and Systems , Gert Smolka (Ed.). Springer, Berlin, Heidelberg, 366–381. Mads Tofte and Jean-Pierre Talpin. 1997. Region-Based Memory Management. Information and Computation 132, 2 (Feb. 1997), 109–176. Philip Wadler. 1990. Linear Types Can Change the World!. In Programming Concepts and Methods: Proceedings of the IFIP Working Group 2.2, 2.3 Working Conference on Programming Concepts and Methods, Sea of Galilee, Israel, 2-5 April, 1990 , Manfred Broy and Cliff B. Jones (Eds.). North-Holland, 561. David Walker and J. Gregory Morrisett. 2000. Alias Types for Recursive Data Structures. In Types in Compilation (Lecture Notes in Computer Science, Vol. 2071) . Springer, 177–206. Guannan Wei, Oliver Bračevac, Songlin Jia, Yuyan Bao, and Tiark Rompf. 2024. Polymorphic Reachability Types: Tracking Freshness, Aliasing, and Separation in Higher-Order Generic Programs. Proceedings of the ACM on Programming Languages 8, POPL (Jan. 2024), 393–424. Yichen Xu, Aleksander Boruch-Gruszecki, and Martin Odersky. 2023. Degrees of Separation: A Flexible Type System for Data Race Prevention. IWACO (2023). Yichen Xu, Aleksander Boruch-Gruszecki, and Martin Odersky. 2024. Degrees of Separation: A Flexible Type System for Safe Concurrency. Proc. ACM Program. Lang. 8, OOPSLA1 (April 2024), 136:1181–136:1207.

---