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

Borrowing issue with impl Trait leads to unergonomic verbosity #37790

Closed
Boscop opened this issue Nov 15, 2016 · 4 comments
Closed

Borrowing issue with impl Trait leads to unergonomic verbosity #37790

Boscop opened this issue Nov 15, 2016 · 4 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-enhancement Category: An issue proposing an enhancement or a PR with one.

Comments

@Boscop
Copy link

Boscop commented Nov 15, 2016

#![feature(conservative_impl_trait)]

struct A {
    v: Vec<usize>
}
impl A {
	fn foo<'a>(&'a self) -> impl Iterator<Item=usize> + 'a {
		(0..self.v.len()).map(move |i| self.v[i])
	}
}

fn bar() -> A {
    A { v: vec![] }
}

fn baz() -> Vec<usize> {
    /* doesn't work:
    bar().foo().collect::<Vec<_>>()
    */
    
    /* also doesn't work:
    let x = bar();
    x.foo().collect::<Vec<_>>()
    */
    
    // you have to do this:
    let x = bar();
    let x = x.foo();
    x.collect::<Vec<_>>()
}

fn main() {}
error: borrowed value does not live long enough
  --> <anon>:18:5
   |
18 |     bar().foo().collect::<Vec<_>>()
   |     ^^^^^ temporary value created here
...
30 | }
   | - temporary value dropped before borrower
   |
   = note: values in a scope are dropped in the opposite order they are created

error: aborting due to previous error

Here on rust playground

@arielb1
Copy link
Contributor

arielb1 commented Nov 15, 2016

The destructors for temporaries in tail expressions run when the containing block ends. The intent is to make braces "transparent". We need good examples for that.

@jimblandy
Copy link
Contributor

jimblandy commented Feb 7, 2017

I think this is the same problem that we discussed in the user forum a while back.

I believe the error message is incorrect. It is simply not true that the temporary value bar() is dropped before its borrower bar().foo(). If "values in a scope are dropped in the opposite order they are created", then since bar().foo() is necessarily created after bar(), the temporary holding bar().foo() should be dropped before the temporary holding bar(). So the ordering of the drops ought to be fine.

The actual motivation for the error is that, for types that implement Drop, Rust doesn't consider it sufficient for borrowers to be dropped before the values they borrow. The lifetime of the latter must be strictly larger than that of the former. Rust considers the two temporaries holding bar() and bar().foo() to have identical lifetimes, hence the error.

Note that if you change the types to be things without Drop impls, the temporaries' lifetimes are no problem:

struct S(i32);
struct T<'a>(&'a S);

// Uncomment this impl, and the program fails to compile.
// impl<'a> Drop for T<'a> { fn drop(&mut self) { } }

fn foo() -> S { S(42) }

impl S {
    fn bar(&self) -> T { T(self) }
}

impl<'a> T<'a> {
    fn get(&self) -> i32 { (self.0).0 }
}

fn main() {
    let _x = foo().bar().get();
}

@Mark-Simulacrum Mark-Simulacrum added A-diagnostics Area: Messages for errors, warnings, and lints A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. labels Jun 23, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 26, 2017
@estebank
Copy link
Contributor

estebank commented Mar 6, 2019

Triage: no change.

@estebank
Copy link
Contributor

All of these cases now compile successfully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-enhancement Category: An issue proposing an enhancement or a PR with one.
Projects
None yet
Development

No branches or pull requests

5 participants