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

slice of static lifetime elements, contains() requires operand to have static lifetime too #18214

Closed
mikedilger opened this issue Oct 21, 2014 · 9 comments

Comments

@mikedilger
Copy link
Contributor

I'm not sure if this is a bug, or if it is already known, or if I'm just too dense to grok this stuff, but it seems to me that the lifetime of my needn't be any longer than the contains() call itself. Yet we have the lifetime error.

fn words() -> Vec<&'static str>
{
    vec!["these","are","my","words"]
}

fn main() {
    let my = "my".into_string();
    if words().contains(&my.as_slice()) {
        println!("Its in there!");
    }
    else {
        println!("Word not found");
    }
}
demo.rs:9:26: 9:28 error: `my` does not live long enough
demo.rs:9     if words().contains(&my.as_slice()) {
                                   ^~
note: reference must be valid for the static lifetime...
demo.rs:7:11: 15:2 note: ...but borrowed value is only valid for the block at 7:10
demo.rs:7 fn main() {
demo.rs:8     let my = "my".into_string();
demo.rs:9     if words().contains(&my.as_slice()) {
demo.rs:10         println!("Its in there!");
demo.rs:11     }
demo.rs:12     else {
           ...
error: aborting due to previous error
@bkoropoff
Copy link
Contributor

This works:

fn words<'a>() -> Vec<&'a str>
{
    vec!["these","are","my","words"]
}

fn main() {
    let my = "my".into_string();
    if words().contains(&my.as_slice()) {
        println!("Its in there!");
    }
    else {
        println!("Word not found");
    }
}

I wonder if there is a way to make region inference figure this out itself.

@mikedilger
Copy link
Contributor Author

Yes using a non-specific lifetime like 'a makes the compiler happy. But it still seems like the lifetime checker isn't quite there.

Vec defines contains() like

impl<T: PartialEq> Vec<T> {
  fn contains(&self, x: &T) -> bool;
}

with no explicit lifetime references. The compiler is matching "&'static str" for "T" and therefore x must be a &'static str. But in reality, the vector must live "at least as long as" the parameter x... not the reverse, nor that the lifetimes are equal. But how do you express such a thing? It seems to me that lifetime annotation is either insufficient, or that (more likely) I still don't have a solid understanding of what lifetime annotation really means.

@mikedilger
Copy link
Contributor Author

And something is weird about the compiler penalizing you for supplying information more specific than it needs.

@bkoropoff
Copy link
Contributor

Another datapoint:

#[deriving(PartialEq, Show)]
struct Foo<T>(T);

fn hello() -> &'static str { "hello" }
fn foo() -> Foo<&'static str> { Foo(hello()) }
fn tup() -> (&'static str,) { (hello(),) }

fn main() {
    let a = "hello".to_string();
    // Works
    assert_eq!(Foo(a.as_slice()), Foo(hello()));
    // Works
    assert_eq!((a.as_slice(),), tup());
    // Fails to compile
    //assert_eq!(Foo(a.as_slice()), foo());
}

The fact that this works for a tuple but not a tuple struct makes it smell like a bug to me. cc @nikomatsakis

@nikomatsakis
Copy link
Contributor

I don't think that the initial example, at least, is a bug. contains() is being invoked on a vector where the type T=&'static str. It requires a &T as argument. It is perhaps plausible we could enhance the type system to accept this, but this would definitely be an enhancement.

@bkoropoff your example falls under the category of #3598 (infer of permit variance). I've been slowly moving a branch along fixing #3598 -- it's more-or-less functional now, so I should submit a refined RFC to try and land it.

@bkoropoff
Copy link
Contributor

Hmm, well, the original example has since started working: http://is.gd/H2r3Hp

This matches my intuition that when instantiating Vec<T>::contains, we can instantiate T to &'a str and infer an 'a that works rather than just picking 'static

I guess the bug can be closed.

@mikedilger
Copy link
Contributor Author

Yeah it works now. Closing.

@nikomatsakis
Copy link
Contributor

Actually, now that I think about it a bit more, all of these examples would compile if the compiler permitted variance (and in fact the original example does compile on my branch).

@nikomatsakis
Copy link
Contributor

Oh, and I see the original compiles on master too :)

Well, @bkoropoff's example still requires my branch, at least ;) I imagine the original example was fixed by the new type inference algorithm inserting more region variables. Might be worth looking into...

lnicola pushed a commit to lnicola/rust that referenced this issue Oct 17, 2024
…eykril

fix: Comment out cast checks for unknown ptr kind

Just like we don't check for types containing unknown.

Fixes rust-lang#18214.

See also https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer/topic/Another.20case.20of.20.2318064.3F.
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