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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃殌 existential impl Trait allows lifetimes that would not be allowed by abstract type #46541

Closed
nikomatsakis opened this Issue Dec 6, 2017 · 5 comments

Comments

Projects
None yet
3 participants
@nikomatsakis
Copy link
Contributor

nikomatsakis commented Dec 6, 2017

Consider this curious case:

#![allow(dead_code)]
#![feature(conservative_impl_trait)]
#![feature(in_band_lifetimes)]

use std::cell::Cell;

trait Trait<'a> { }

impl Trait<'b> for Cell<&'a u32> { }

fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
where 'x: 'y
{
    x
}

fn main() { }

Here, the value we are returning is of type Cell<&'x u32>, but the return type ought only to be able to mention 'y. In other words, we are inferring something like

abstract type Foo<'z>: Trait<'z> = Cell<&'x u32>

which is clearly malformed. We allow this because the current code has regionck bound all lifetimes with 'y and considers that sufficient to ensure that nothing is "leaking" that shouldn't -- but, as can be seen here, that's not always true.

I don't think we should accept this -- at least for now. However, I also could not find an obvious way to weaponize it. There may not be one. Consider that this variant, using Box<dyn Trait<'y> + 'y> in place of impl Trait<'y>, type-checks and ought to be sound (afaik). (In part, though, this relies on the fact that we expand impl Trait<'y> to impl Trait<'y> + 'y internally, but it seems like impl Trait<'y> must outlive 'y just by construction, since it could not name any other lifetime.)

One could imagine permitting the example via some sort of subtyping relation on abstract types -- that is, perhaps we might determine a variance for Foo with respect to its type parameters based on the traits that it implements. Not sure if that would be sound, but you could imagine it. Until we have such a justification, though, I think we should not accept the example.

I'll probably fix this en passane while doing some refactoring to support impl Trait in the NLL code.

cc #34511

@nikomatsakis

This comment has been minimized.

Copy link
Contributor Author

nikomatsakis commented Jan 18, 2018

removing from WG-compiler-nll since I don't think it's that related

@aturon

This comment has been minimized.

Copy link
Member

aturon commented Feb 22, 2018

Ping on this -- is this blocking impl Trait stabilization?

@nikomatsakis

This comment has been minimized.

Copy link
Contributor Author

nikomatsakis commented Feb 22, 2018

@aturon yep, I think it's a blocker.

@aturon

This comment has been minimized.

Copy link
Member

aturon commented Feb 22, 2018

We're shooting for stabilization within this cycle, are we on track?

@nikomatsakis

This comment has been minimized.

Copy link
Contributor Author

nikomatsakis commented Feb 22, 2018

I don't know. We should figure that out. I'll try to prep a "stabilization check-in" before lang mtg. (I was already hoping to do this)

@nikomatsakis nikomatsakis changed the title existential impl Trait allows lifetimes that would not be allowed by abstract type 馃殌 existential impl Trait allows lifetimes that would not be allowed by abstract type Feb 25, 2018

@Aaronepower Aaronepower added the C-bug label Feb 26, 2018

bors added a commit that referenced this issue Mar 22, 2018

Auto merge of #49041 - nikomatsakis:issue-46541-impl-trait-hidden-lif鈥
鈥times, r=cramertj

Detect illegal hidden lifetimes in `impl Trait`

This branch fixes #46541 -- however, it presently doesn't build because it also *breaks* a number of existing usages of impl Trait. I'm opening it as a WIP for now, just because we want to move on impl Trait, but I'll try to fix the problem in a bit.

~~(The problem is due to the fact that we apparently infer stricter lifetimes in closures that we need to; for example, if you capture a variable of type `&'a &'b u32`, we will put *precisely* those lifetimes into the closure, even if the closure would be happy with `&'a &'a u32`. This causes the present chance to affect things that are not invariant.)~~ fixed

r? @cramertj

@bors bors closed this in #49041 Mar 22, 2018

@alexreg alexreg referenced this issue Nov 20, 2018

Open

Tracking issue for `Captures` trait #56046

0 of 3 tasks complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment