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

Borrow checking with loops, safe uninitailized variables, and conditional breaks. #19433

Closed
Ericson2314 opened this issue Dec 1, 2014 · 6 comments
Labels
A-borrow-checker Area: The borrow checker A-typesystem Area: The type system

Comments

@Ericson2314
Copy link
Contributor

I have some code that compiles like this:

pub struct ViewIter<'a> {
  expected_seq: u32,
  tagged_iter:  Peekable<&'a Tagged, dlist::Items<'a, Tagged>>,
}

impl<'a> Iterator<u8> for ViewIter<'a>
{
  #[inline]
  fn next(&mut self) -> Option<u8>
  {
    loop {
      {
        let next = match self.tagged_iter.peek() {
          None    => return None,
          Some(s) => s,
        };

        let cond = self.expected_seq == next.tail() ||
          next.tail().is_clockwise(&self.expected_seq, &next.head());

        if cond
        {
          let tagged = next;

          let ret = Some(tagged.as_slice()[(self.expected_seq - tagged.tail()) as uint]);
          self.expected_seq += 1;

          return ret;
        }
      };

      self.tagged_iter.next();
    }
  }
}

I would like to change the method so it is instead

impl<'a> Iterator<u8> for ViewIter<'a>
{
  #[inline]
  fn next(&mut self) -> Option<u8>
  {
    let tagged;
    loop {
      {
        let next = match self.tagged_iter.peek() {
          None    => return None,
          Some(s) => s,
        };

        let cond = self.expected_seq == next.tail() ||
          next.tail().is_clockwise(&self.expected_seq, &next.head());

        if cond
        {
          tagged = next;
          break;
        }
      };

      self.tagged_iter.next();
    }

    let ret = Some(tagged.as_slice()[(self.expected_seq - tagged.tail()) as uint]);
    self.expected_seq += 1;

    ret
  }
}

But the borrow checker rejects this. Not that if if cond is commented, it is accepted.

I understand that the borrow checker is already doing a lot of magic regarding loops, conditional breaks, and uninitialized variables, but thought I'd report this in case I am hitting an unintended restriction.

head, tail, is_clockwise, are invariant with respect to lifetimes. Everything else is I believe from the standard library or countravariant.

@kmcallister kmcallister added the A-typesystem Area: The type system label Jan 25, 2015
@huonw
Copy link
Member

huonw commented Feb 3, 2015

I suspect this is a dupe of #12147 and hence of #6393 transitively. cc @nikomatsakis

@huonw huonw added the A-borrow-checker Area: The borrow checker label Feb 3, 2015
@Ericson2314
Copy link
Contributor Author

@nikomatsakis
Copy link
Contributor

It's hard to be sure without digging in more deeply, but I don't believe this is a dup of #6393. I suspect it is a dup of #10520 though.

@nwin
Copy link
Contributor

nwin commented Apr 21, 2015

I might be wrong but I think my current problem (more minimal example) falls under the same class:

struct Foo;

impl Foo {
    fn borrow_mut(&mut self) -> Option<&str> {
        Some("Hello World")
    }
}

fn main() {
    let mut foo = Foo;
    let mut retval = None;
    while retval.is_none() {
        retval = foo.borrow_mut()
    };
}

It should pass the borrow checker because the loop will be terminated after the assignment. Same issue occurs on early returns in the loop. I don’t think that it is a dupe of #10520 but indeed a dupe of #12147.

@steveklabnik
Copy link
Member

Triage: it seems that this issue boils down to non-lexiacal lifetimes, so I'm going to give it a close in favor of that. Thanks all!

@Ericson2314
Copy link
Contributor Author

Heh, I got about 1/3 through getting my net stack to compile this summer. I'll make a definitive report on this someday!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-borrow-checker Area: The borrow checker A-typesystem Area: The type system
Projects
None yet
Development

No branches or pull requests

6 participants