Hi,
Currently, Rust has C#-like implicit variance - actually it's even more
implicit then C#, being inferred automatically - which is nice in being
boilerplate-light.
However, in some cases more explicit variance would be desired, as in this
example:
Say Library A has a mutable AContext, and Library B, which depends on
Library A, has a BContext which depends on the AContext.
We could type this as follows:
struct AContext {
priv state: RefCell<AInternalState>,
...
}
fn create_acontext() -> AContext;
struct BContext<'a> {
acontext: &'a AContext,
...
}
fn create_bcontext<'a>(&'a AContext) -> BContext<'a>;
And use it like:
let acontext = create_acontext()
let bcontext = create_bcontext_(&acontext)
(Note that acontext: ~AContext won't work, because Library B objects may
have a reference to a subobject of the AContext, and besides, the user may
like to use the AContext themselves)
However, this forces the user of Library B to interact with its
dependencies, and if Library B depends on half a dozen other libraries and
the user creates ten contexts in his tests, we have a problem.
We would like to create a function that creates a BContext and an AContext
together - however, someone needs to manage the ownership of the AContext
and make sure it goes with the BContext.
A potential solution is to use Rc<AContext>, but this creates Rc pollution
when the lifetime is static - now objects with a pointer to part of
AInternalState need to use an Rc.
Note that the lifetime of the inner AContext is completely static here - it
goes with the BContext. We could have something like this:
struct BContextHolder {
priv acontext: ~AContext,
ctx: BContext<'something>
}
fn create_bcontext() -> BContextHolder {
let actx = ~create_acontext()
BContextHolder {acontext: actx, ctx: create_bcontext_(&actx))
}
However, this isn't legal rust - we can't find a good lifetime for
'something - and besides, acontext isn't burrowed so people can free it.
I think I found a way to solve this - allow struct fields to have burrows
into *other fields of the same struct*:
A (bad) syntax for this is
struct BContextHolder {
priv &'a acontext: ~AContext,
ctx: BContext<'a>
}
Which means that the field acontext is borrowed in the lifetime 'a, which
is also the lifetime of ctx.
I didn't formalise this, but from where I looked we essentially need to:
1) Make sure that people accessing acontext see it as burrowed
2) Make sure you can't just change acontext
3) Make sure the burrow relationships are not strengthened when
structuring/destructuring.
This post is getting tl;dr already so I'll end it here.
--
Ariel Ben-Yehuda
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev