Static path-dependent types and deferred borrows

You're right, they're not completely the same thing as path-based polymorphism, but they do overlap with the paper. I'm really thinking about two kinds of self-references: heap based or stack/field based. The former is usually pretty similar or the same as path-based types, depending on the pitch. The latter are not type constraints, but they are a form of deferred borrows. And both do overlap in what they require the compiler to track (reference provenance that persists across API boundaries).

For example, the desire for self-referential structs is often presented as something like:

struct MyType {
    // Heap based
    data: Vec<Widget>,
    current: &'data Widget, // or sometimes `&'self` as well
    // And/or field/stack based
    other_field: DooDad,
    and_another: DooDad,
    some_doodad_field: &'self DooDad,
}

Where &'self or some other special lifetime or annotation indicates some new kind of reference/type/"lifetime" that is associated in some way with the rest of the containing data structure.

One common requirement with both kinds of self-references and the paper is that you need to track the provenance of the reference to ensure that it isn't invalidated. In particular this tracking and validity proving needs to cover the existence of the reference, and not just a scope of local analysis. I.e. it needs to cross boundaries such as function calls.

In the case of heap based self-references, the tracking is often based on the path (field name) that owns the referenced data. In this case, the special self-referential type is a path-based type. (Although another possibility is somehow tracking the heap allocation itself, which could conceivably move between fields.)

The stack/field self-references are different in that the path is dynamic (or what's the point), and not a static type constraint like in the paper. However, they are still related to the paper. In particular, one likely implementation is to store the self-reference as an offset relative to the struct, and utilizing the self-reference would be a form of deferred borrowing: the actual reference would be computed from the offset at the use site (which can differ per use site, e.g. when you call a by-value function and move the struct).

Here's a recent thread where both heap and stack based self-references are mentioned.