Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new scoping rules for safe dtors may benefit from variance on type params #21198

Closed
pnkfelix opened this issue Jan 15, 2015 · 7 comments
Closed
Labels
A-typesystem Area: The type system

Comments

@pnkfelix
Copy link
Member

Spawned off of #21022, #21972.

As discussed on this commit pnkfelix@8ee3c94

there are example programs (both artificial and in the wild) that have to change under the current implementation of the new scoping rules, but might not require such change if we add support for variance of type parameters: rust-lang/rfcs#281


An easy example of this, taken from the discussion on the above commit, is the following:

fn main() {
    let x = 3u8;
    let p = Option::Some(&x); // call the implicit lifetime here `&'_#1 x`
    let y = 4u8;
    constraints(p, &y); // call the implicit lifetime here `&'_#2 y`
}

fn constraints<'a> (px: Option<&'a u8>, py: &'a u8)
{
    loop  { }
}

Under the region inference constraints (regardless of which scoping rules have been adopted), '_#1 has to outlive p, while '_#2 cannot outlive y, and the call to constraints is trying to find a 'a compatible with '_#1 and '_#2.

Under the old scoping rules, p and y had the same scope, so the constraint set is satisfiable.

Under the new scoping rules, the scope of y is strictly less than that of p, so the constraint set is no longer satisfiable.


The solution adopted in #21022 is to move the binding of y up above the binding of p.

But an alternative solution is this: If RFC Issue 281 rust-lang/rfcs#281 leads to type parameter variance being implemented, then cases like this might be directly expressible (because the lifetime '_#1 will continue to outlive p, but the occurrence of p in the call to constraints would use variance to assign the scope of y (a sublifetime of '_#1) as the new lifetime embedded within the type of p.

This ticket is to mark cases that we should revisit if/when type parameter variance is implemented.

@kmcallister kmcallister added the A-typesystem Area: The type system label Jan 16, 2015
@pnkfelix pnkfelix changed the title new scoping rules for safe dtors would benefit from variance on type params new scoping rules for safe dtors may benefit from variance on type params Jan 20, 2015
@pnkfelix
Copy link
Member Author

It is now a little more questionable whether the variance changes suggested would suffice. At least, I tried a local hack of making Vec<T>/Box<T>/Rc<T> all covariant in T, as @nikomatsakis told me that might fix my problem.

However, I still cannot bootstrap in that case.

Here is a gist of a semi-reduced case that I made from my attempt to compile librustc_driver (so we can get fairly far along in the bootstrapping), along with the transcript of build errors when attempting to bootstrap atop https://github.com/pnkfelix/rust/tree/new-dtor-semantics-5-chkpt :

https://gist.github.com/pnkfelix/7b9f0dde7acd8b4f84fe

(I am going to try to further reduce the test case so that it stands entirely alone; the one in the gist is still pulling in the syntax and rustc crates.)

@pnkfelix
Copy link
Member Author

(discussed the previous comment with @nikomatsakis ; he pointed out that our use of TypedArena<T> is probably the culprit, as it is invariant with respect to T, and needs to be under its current API, we think. Then we brainstormed and he came up with a solution: wrap the TypedArena in a trait that provides an impoverished API that is covariant with respect to T.)

@pnkfelix
Copy link
Member Author

(followup to the previous comment: We were mistaken, there is no wrapper trait for TypedArena that is both covariant with respect to T while also providing the functionality needed. I believe such a trait is not expressible in Rust today, but I have discussed some ideas with @nikomatsakis for future extensions to the language that could allow such a trait to be encoded.)

@steveklabnik
Copy link
Member

Triage: too in the weeds for me.

@Mark-Simulacrum
Copy link
Member

This is also going over my head. The example in the original issue does compile successfully today, but I can't get an old enough nightly to install with rustup to verify if it did back in 2015. Can anyone comment on this to say if it's still relevant?

@pnkfelix
Copy link
Member Author

pnkfelix commented May 2, 2017

So if I understand what I wrote (back two years ago), I think that this ticket was meant to track parts of the code that might be improved if we added variance of types (with respect to particular type parameters).

We at this point do have variance. (Which presumably would explain why the example in the description does compile.)

So if there was a big list of instances in the code base that could be improved based on the addition of variance, then I would say we should work our way down that list to clean things up. However, there is no such big list.

Therefore, I'm just going to close this ticket. (As far as I can tell there are no references to #21198 in the source tree, and even if there were, the discussion already present here should suffice to provide context about what those references mean.)

@pnkfelix pnkfelix closed this as completed May 2, 2017
@pnkfelix
Copy link
Member Author

pnkfelix commented Nov 30, 2017

Earlier I wrote:

... there is no wrapper trait for TypedArena that is both covariant with respect to T while also providing the functionality needed. I believe such a trait is not expressible in Rust today, but I have [...] ideas ...

On IRC Sharp asked for more details on the problem and the ideas for a solution. Here is the summary as best I have been able to reconstruct in short order (transcribed from aforementioned IRC log):

  1. TypedArena<T> drops all of its contents when the TypedArena itself is dropped
  2. So if it were covariant, then A <: B would imply TypedArena<A> <: TypedArena<B>
  3. then you could instantiate A and B with types with lifetimes 'a and 'b where 'a outlives 'b, and pass the arena for holding A's into a context expecting an arena of B's
  4. then start throwing in objects whose Drop impls dereference data of lifetime 'b
  5. but now they outlive that scope
  6. so the destructor executions on those instances of B are now unsound

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system
Projects
None yet
Development

No branches or pull requests

4 participants