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 rules are overly restricted in 1.65 nightly / beta #102029

Closed
haohui opened this issue Sep 19, 2022 · 6 comments
Closed

lifetime rules are overly restricted in 1.65 nightly / beta #102029

haohui opened this issue Sep 19, 2022 · 6 comments
Labels
A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. regression-from-stable-to-beta Performance or correctness regression from stable to beta.

Comments

@haohui
Copy link

haohui commented Sep 19, 2022

I tried this code:

type Result<T> = std::result::Result<T, std::io::Error>;

pub(crate) struct Foo<'a> {
    pub(crate) kernels: Vec<&'a str>,
}

impl<'a> Foo<'a> {
    fn parse(buf: &'a [u8]) -> Result<Foo> {
        let p = &mut StreamParser::new(buf);
        let (m, p) = p.read_map()?;
        m.try_foreach(p, |b| {
            let b0 = Self::broke(b)?;
            Ok(b0)
        })?;
        Ok(Foo {
            kernels: Vec::new(),
        })
    }

    fn broke<'b: 'a>(p: &'b mut StreamParser<'a>) -> Result<&'b mut StreamParser<'a>> {
        Ok(p)
    }
}

#[derive(Copy, Clone)]
pub(crate) struct StreamParser<'a> {
    bytes: &'a [u8],
    current_position: usize,
}

#[derive(Copy, Clone, Debug)]
pub(crate) struct Seq {
    num_entries: usize,
}

impl Seq {
    pub(crate) fn try_foreach<'a, 'b, F>(
        &self,
        p: &'b mut StreamParser<'a>,
        mut f: F
    ) -> Result<&'b mut StreamParser<'a>>
        where F: FnMut(&'b mut StreamParser<'a>) -> Result<&'b mut StreamParser<'a>>
    {
        (0..self.num_entries).try_fold(p, |p, _| (f)(p))
    }
}

impl<'a> StreamParser<'a> {
    pub(crate) fn new(bytes: &'a [u8]) -> StreamParser<'a> {
        StreamParser {
            bytes,
            current_position: 0,
        }
    }

    pub(crate) fn read_map(&mut self) -> Result<(Seq, &mut Self)> {
        let c = self.read_u8()?;
        Ok((
            Seq {
                num_entries: c as usize,
            },
            self,
        ))
    }

    fn read_u8(&mut self) -> Result<u8> {
        let r = self.bytes[self.current_position];
        self.current_position += 1;
        Ok(r)
    }
}

The rustc in 1.63 compiles the code successfully while rustc 1.65.0-nightly (cf9ed0d 2022-09-15) fails to compile it:

7  | impl<'a> Foo<'a> {
   |      -- lifetime `'a` defined here
8  |     fn parse(buf: &'a [u8]) -> Result<Foo> {
9  |         let p = &mut StreamParser::new(buf);
   |                      ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
10 |         let (m, p) = p.read_map()?;
   |                      ------------ argument requires that borrow lasts for `'a`
...
18 |     }

Are there any changes in the language specifications that have tighten the lifetime rules?

@haohui haohui added the C-bug Category: This is a bug. label Sep 19, 2022
@mejrs
Copy link
Contributor

mejrs commented Sep 19, 2022

@rustbot label +regression-untriaged, +regression-from-stable-to-beta +A-lifetimes

@rustbot rustbot added A-lifetimes Area: Lifetimes / regions regression-from-stable-to-beta Performance or correctness regression from stable to beta. regression-untriaged Untriaged performance or correctness regression. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Sep 19, 2022
@haohui
Copy link
Author

haohui commented Sep 19, 2022

@ehuss
Copy link
Contributor

ehuss commented Sep 19, 2022

Thanks for the report! Sorry you're running into that situation. This was a correctness fix, intentionally changed as part of #98835. Closing as a duplicate of #100544.

@ehuss ehuss closed this as not planned Won't fix, can't repro, duplicate, stale Sep 19, 2022
@jackh726
Copy link
Member

Indeed this was changed due to a correctness fix.

For clarity, you code can be fixed by changing let b0 = Self::broke(b)?; to let b0 = Foo::broke(b)?;

@haohui
Copy link
Author

haohui commented Sep 20, 2022

I thought Self is just a syntactic sugar. Just curious how does it affect the binding of lifetime?

@jackh726
Copy link
Member

Self here is Foo<'a>, whereas Foo is Foo<'_>. So in the former, the closure captures the 'a lifetime, where in the latter, it captures some lifetime '_

@inquisitivecrystal inquisitivecrystal removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. regression-untriaged Untriaged performance or correctness regression. labels Sep 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. regression-from-stable-to-beta Performance or correctness regression from stable to beta.
Projects
None yet
Development

No branches or pull requests

6 participants