One thing I haven't touched on is recursive imports, e.g. use self.foo::bar; use self.bar::baz
. Or, more succinctly, use self.foo.bar::{self, baz}
.
I think we may want to disallow or at least discourage them via lint.
One thing I haven't touched on is recursive imports, e.g. use self.foo::bar; use self.bar::baz
. Or, more succinctly, use self.foo.bar::{self, baz}
.
I think we may want to disallow or at least discourage them via lint.
Would it be possible to delegate fields in the same manner? e.g.
pub use self.pets.cats
where
cats
is a field of pets
.
Here, you'd be able to borrow cats
without knowing about the internal structure, i.e. that it's in an internal substructure named pets
. That'd be an implementation detail, not revealed in the pub API.
Yes, but as I wrote above, we may want to discourage this, as it's usually bad design to reach into inner objects.
I don't agree with such a general statement. In the example provided self
and pets
might be defined in the same module. Using delegation in this way is no different that delegating a function. The point of such delegation is to present a pub API that doesn't reveal deeper structural relations than necessary.
Why? What keeps you from delegating the methods you want to use from your field and using them? With the appropriate visibility there's no publicly visible difference and you gain higher locality.
True about the better locality of reasoning. From a traditional OOP-perspective accessor methods are strongly encouraged, but they can also be considered needless ceremony in many cases.
Delegating fields can hide the internal structure while serving as a means of (or the counterpart of) "field inheritance" in Rust, where composition is the preferred style.
I find this an important point. Since Rust does not support inheritance, and in particular, structural inheritance, the providing a clean/easy/clear/declarative way of delegating fields AND methods would provide the best experience (Opinion obviously, but, one formed from 25+ years of development across many languages, industries, and development styles).
This looks cool. My only concern is about expanding the use
keyword for code generation cases, and if I understand this correctly, the suggestion is to generate code. So far, use
has only been utilized for arranging export/import namespaces.
The code generation is an implementation detail. You still bring method from elsewhere into this scope, albeit not from another module but from one of your fields (or receiver-only methods).
Looking at how this was solved elsewhere, here is how it's done in Lombok for Java: https://projectlombok.org/features/Delegate.html
The annotation is provided a reference to a dummy interface which it extracts the function signatures from and then implements them. This wouldn't work exactly for Rust, because implementations of a method need to be specific to which trait they are attached to as opposed to all being part of the same class declaration.
It could be done by explicitly duplicating the signatures from the trait in the call to the macro, but that is probably undesirable.
Kotlin uses the by
keyword for delegation. See documentation.
As a Java programmer and lombok user, I was aware of its delegation facility, though I haven't used it in my code yet.
I think the effort for this in Java is greatly reduced by the proliferation of IDEs that autocomplete function signatures. Those don't work quite as well for Rust yet, so we'd be well advised to invest in better user experience from the language itself for this case.
One thing I'm interested in discussing is potential interactions with other features, e.g. async fns, generics, lifetimes etc.
There is the ::inheritance
, which in hindsight I should named delegation
.
It is still fairly limited since it's "just" proc-macro-based, but with access to compiler internals it would allow to easily get something along these lines:
#[derive(DelegationImpls)]
struct MyIter<'a, T>(
#[delegate_impl(Iterator where T : Sync)]
std::slice::Iter<'a, T>,
);
There is already an active rfc for delegation but from what I can read so far it is not very clear to me :
In fact this rfc is partially based on an even older one of mine that already proposed to reuse the use
keyword.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.