Hi, happy to hear from you! Our code are getting more similar and I find it satisfying because it might prove that we are going in the right direction.
As for the status on my project, I improved my API significantly to very basic and modular primitives, along with a few other soundness issues. No change on the basic ideas, though.
I brought my code to action and polyfilled the API of safer_owning_ref using my self-referential type and safe code: oyakodon/polyfills/owning_ref at main · sshockwave/oyakodon · GitHub
My first attempt was actually owning_ref and my API was incapable to implement that. It took me hours to figure out the reason I can't implement it with my API is that it is unsound from its root LOL. I also tried yoke, but yoke has unsafe everywhere in its API and I don't think it is possible to deal with it using safe code. I plan to polyfill self_cell for the next steps.
I would like to share some soundness issues I came across so that you don't have to go over them again:
- I once tried to "can" or "seal" the view to disable access to them instead of forcing them to drop before owner, but I forgot that the view can access the owner in their drop function.
- Extra care on implicit bounds since current Rust would sometimes allow widening the
for<'a> guarantees from [lo, hi] to something larger: HRTB on subtrait unsoundly provides HTRB on supertrait with weaker implied bounds · Issue #84591 · rust-lang/rust · GitHub
- Owner access can be given if and only if there is no mutable reference to the owner. The simplest option would be of course don't give access to the owner, but
safer_owning_ref allows it, so, yeah, it would be feature incomplete.
I forgot to mention my best discovery in these days. We can express higher kinded type inline now, like this:
dyn for<'b> View<'b, Output = (&'a String, &'b String)>
It works very robustly, unlike dyn for<'a> Fn(&'a ())->&'a String which sometimes have the wrong inferred lifetime.
I need some time to deep dive into your current work as you mentioned
As the author, it's no longer difficult for me to understand how this crate works, but I assume that it'd be difficult for others to learn.
I have the exact same feeling for my crate.
I just can’t help but be suspicious of any clever tricks involving higher-ranked dyn trait objects used for implied bounds or sneaking in an extra lifetime parameter.
E.g., I’m not sure if it’s settled/stable behavior that dyn Trait will be permitted, in all future compiler versions, to not implement Trait: You can instantiate a dyn Trait that doesn't implement Trait · Issue #88904 · rust-lang/rust · GitHub
I feel like there was another related issue I’m thinking of, but I couldn’t find it yet… instead I also found this worse problem: higher-ranked `dyn Trait`, fn pointers, and closures allow normalizing to non-wf type · Issue #152489 · rust-lang/rust · GitHub
…once we’re done with our projects, we should probably have theemathas/Helix look over them to check for compiler bugs.
No way...Are you saying that dyn Fn(&i32) -> &i32 also won't work in the future because it is dyn and HRTB? I would say that it is a bug, not a delibrate design. Anyway, it's only a syntax sugar and my library is not depending on it. Users can always fallback to creating a new type that implements View.
I actually encountered the issue you linked, in other forms. trait A: B{} indicates A requires B at the impl site, which is the definition. The problem is at the use site. I would say A should imply B, but sometimes it is not true, in which case A requires B. This is very inconvenient as I can't pack the bounds into one single trait, and I still consider this as a limitation, not a feature.
I knew there is an unsoundness problem about HRTB and implicit bounds but didn't expect it to be so severely exploited. WOW.
I also had a closer look on your current work. If I understand it correctly, your focus is on defining an unsafe contract, while mine skips this layer and trying to embed all requirements into the type system directly at the self-referential struct API level. Would like to see your design once attached-ref is finished.
AFAIK dyn Fn(&i32) -> &i32 is well-formed, but what about dyn Fn(&'static &i32)? Where 'b is some random lifetime parameter in scope (which does not necessarily outlive 'static), what about dyn Fn(&'static &&'b i32) -> &'static i32? That last one, which is currently accepted by the compiler, can (together with other(?) compiler bugs) result in a segfault.
Until those compiler bugs are fixed, I'm not confident about what's intentional and what's buggy. I could think long and hard about whether my code is correct, or I could just avoid higher-ranked dyn objects until the next-gen trait solver is stabilized.
Technically, "semver, backwards-compatibility, yadda yadda". But yes, I want more implied where-bounds too.
On a slightly different topic, for most of today, I've been trying to see if I can use compiler diagnostics to tell me the implied bounds in a higher-ranked trait bound. That way, ideally, I don't need to carefully examine the exact trait bounds I use to determine where and what the implied bounds are, since, surely, the compiler needs to know what those implied bounds are.

The compiler does not in fact know what those implied bounds are. (It knows the implied bounds of non-higher-ranked trait bounds, though.)
Now I'm trying to enable parts of the next-gen trait solver, since, surely, part of the purpose of the next-gen trait solver is to finally fix unsoundnesses in the trait solver, and that will surely require proper tracking of the implied bounds in HRTBs. Alas.... I haven't had luck on this front either, yet.