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

Lifetime inference inconsistency with borrowed pointer fields #8845

Closed
sfackler opened this issue Aug 29, 2013 · 4 comments
Closed

Lifetime inference inconsistency with borrowed pointer fields #8845

sfackler opened this issue Aug 29, 2013 · 4 comments

Comments

@sfackler
Copy link
Member

use std::cell::Cell;

struct Foo<'self> {
    f: Cell<&'self fn()>
}

struct Bar<'self> {
    f: &'self Foo<'self>
}

impl<'self> Foo<'self> {
    fn foo<'a>(&'a self) -> Bar<'a> {
        Bar { f: self }
    }
}

fails to compile with

test.rs:13:8: 13:11 error: cannot infer an appropriate lifetime due to conflicting requirements
test.rs:13         Bar { f: self }
                   ^~~
test.rs:12:36: 14:5 note: first, the lifetime cannot outlive the lifetime &'a  as defined on the block at 12:36...
test.rs:12     fn foo<'a>(&'a self) -> Bar<'a> {
test.rs:13         Bar { f: self }
test.rs:14     }
test.rs:13:8: 13:11 note: ...due to the following expression
test.rs:13         Bar { f: self }
                   ^~~
test.rs:12:36: 14:5 note: but, the lifetime must be valid for the lifetime &'self  as defined on the block at 12:36...
test.rs:12     fn foo<'a>(&'a self) -> Bar<'a> {
test.rs:13         Bar { f: self }
test.rs:14     }
test.rs:13:17: 13:23 note: ...due to the following expression
test.rs:13         Bar { f: self }
                            ^~~~~~
error: aborting due to previous error

but removing the Cell compiles correctly:

struct Foo<'self> {
    f: &'self fn()
}

struct Bar<'self> {
    f: &'self Foo<'self>
}

impl<'self> Foo<'self> {
    fn foo<'a>(&'a self) -> Bar<'a> {
        Bar { f: self }
    }
}

It turns out that using 'self instead of 'a fixes the problem:

use std::cell::Cell;

struct Foo<'self> {
    f: Cell<&'self fn()>
}

struct Bar<'self> {
    f: &'self Foo<'self>
}

impl<'self> Foo<'self> {
    fn foo(&'self self) -> Bar<'self> {
        Bar { f: self }
    }
}

I would think that all three examples should compile, since the lifetime bounds of 'a and 'self should intersect properly.

cc @nikomatsakis

@sfackler
Copy link
Member Author

Interestingly, the issue seems to persist through multiple levels of borrowed pointers. This fails to compile as well:

use std::cell::Cell;

struct Foo<'self> {
    f: Option<&'self fn()>
}

struct Bar<'self> {
    f: &'self Foo<'self>
}

struct Baz<'self> {
    b: &'self Bar<'self>
}

impl<'self> Foo<'self> {
    fn foo(&'self self) -> Bar<'self> {
        Bar { f: self }
    }
}

impl<'self> Bar<'self> {
    fn bar<'a>(&'a self) -> Baz<'a> {
        Baz { b: self }
    }
}

With

test.rs:23:8: 23:11 error: cannot infer an appropriate lifetime due to conflicting requirements
test.rs:23         Baz { b: self }
                   ^~~
test.rs:22:36: 24:5 note: first, the lifetime cannot outlive the lifetime &'a  as defined on the block at 22:36...
test.rs:22     fn bar<'a>(&'a self) -> Baz<'a> {
test.rs:23         Baz { b: self }
test.rs:24     }
test.rs:23:8: 23:11 note: ...due to the following expression
test.rs:23         Baz { b: self }
                   ^~~
test.rs:22:36: 24:5 note: but, the lifetime must be valid for the lifetime &'self  as defined on the block at 22:36...
test.rs:22     fn bar<'a>(&'a self) -> Baz<'a> {
test.rs:23         Baz { b: self }
test.rs:24     }
test.rs:23:17: 23:23 note: ...due to the following expression
test.rs:23         Baz { b: self }
                            ^~~~~~
error: aborting due to previous error

But works fine either removing the box around the &'self fn() or changing the 'as to 'selfs.

@nikomatsakis
Copy link
Contributor

I believe that the compiler is acting correctly. The Cell type is
mutable. Therefore, it is not enough for there to be a lifetime
intersection, but rather the lifetimes must be exactly the same.
(in type system terms, the types Foo and Bar are invariant with
respect to the lifetime parameter 'self, wikipedia has an article
about it
).

Unfortunately, as #3598 has not been fixed, all types are currently
considered invariant with respect to their type parameters, so the
results will be the same even if Cell had no mutable methods.

@alexcrichton
Copy link
Member

This code appears to compile today:

struct Foo<'a> {
    f: 'a ||
}

struct Bar<'a> {
    f: &'a Foo<'a>
}

struct Baz<'a> {
    b: &'a Bar<'a>
}

impl<'a> Foo<'a> {
    fn foo(&'a self) -> Bar<'a> {
        Bar { f: self }
    }
}

impl<'a> Bar<'a> {
    fn bar<'a>(&'a self) -> Baz<'a> {
        Baz { b: self }
    }
}

It doesn't have the Option<&'a fn()> because sadly Option<'a ||> doesn't parse today. That being said this (updated) code doesn't compile:

use std::cell::RefCell;

struct Foo<'a> {
    f: RefCell<&'a 'a ||>
}

struct Bar<'a> {
    f: &'a Foo<'a>
}

impl<'a> Foo<'a> {
    fn foo<'a>(&'a self) -> Bar<'a> {
        Bar { f: self }
    }
}

while this code does

use std::cell::RefCell;

struct Foo<'a> {
    f: RefCell<&'a 'a ||>
}

struct Bar<'a> {
    f: &'a Foo<'a>
}

impl<'a> Foo<'a> {
    fn foo(&'a self) -> Bar<'a> {
        Bar { f: self }
    }
}

(note the missing <'a> on fn foo). I think that the problem here may have been something along the lines of 'self not equal to 'a in the original example, but from these examples it sounds like it was just a mismatch in lifetimes that are handled much better today.

I'm tempted to close this as working, but I'm not sure I understand whow #3598 interacts here.

@nikomatsakis
Copy link
Contributor

Closing. There is some interaction with #3598 in the sense that Option<&'short T> should (ideally) be a subtype of Option<&'static T>, but that's... just #3598.

flip1995 pushed a commit to flip1995/rust that referenced this issue Jun 4, 2022
…ts, r=Alexendoo

Fix `[use_self]` false negative with on struct and tuple struct patterns

fixes rust-lang#8845

changelog: Triggered the warning for ``[`use_self`]`` on `TupleStruct` and `Struct` patterns, whereas currently it's only triggered for `Path` patterns
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants