These are chat archives for rust-lang/rust

11th
Nov 2018
melbourne2991
@melbourne2991
Nov 11 2018 03:19

Hi all, i've run into a bit of a blocker.

I'm getting a "cannot move out of borrowed content" error for self.lexer in my parse method. I've tried a number of things, and have been able to get rid of that error but then I get other errors coming up instead.

pub struct Parser<L: Iterator<Item = (TokenType, TokenMetadata)>> {
  lexer: L,
}

impl<L: Iterator<Item = (TokenType, TokenMetadata)>> Parser<L> {
  pub fn new(lexer: L) -> Parser<L> {
    let parser = Parser { lexer: lexer };

    parser
  }

  pub fn parse(&mut self) {
    for (token, metadata) in self.lexer {
      match token {
        TokenType::Unexpected => {
          println!("Unexpected token!");
          break;
        }
        _ => {
          println!("{:?}", metadata);
          println!("{:?}", token);
        }
      }
    }
  }
}
matrixbot
@matrixbot
Nov 11 2018 03:20
bspeice melbourne2991 (Gitter):
bspeice melbourne2991 (Gitter): Sorry about that, had issues typing. Presumably there are issues using &self.lexer?
melbourne2991
@melbourne2991
Nov 11 2018 03:22
Yeah I believe I tried that before as well, I get:
help: the trait `std::iter::Iterator` is not implemented for `&L`
matrixbot
@matrixbot
Nov 11 2018 03:23
bspeice Give me a second to play around, I have a couple ideas.
melbourne2991
@melbourne2991
Nov 11 2018 03:24
Sure :)
matrixbot
@matrixbot
Nov 11 2018 03:28
bspeice So, a couple thoughts: First, this is trivially fixable by using a while let loop: https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=928f33b0e713fff02ee6a6088b1c18c9
bspeice Second - the idiomatic approach is usually to have L implement IntoIterator rather than Iterator directly. With that, it should be safe to do self.lexer.into_iter() and loop over that.
melbourne2991
@melbourne2991
Nov 11 2018 03:33
Ok thanks. I was looking at into iterator but a bit unsure of how to actually implement it
mm interesting that while let works as it's also accessing the iterator?
Also, perhaps worth noting - the iterator works fine when in my main.rs, that for loop was copy pasted from there. So it has something to do with the fact that lexer is passed into parser I suppose
matrixbot
@matrixbot
Nov 11 2018 03:38
bspeice Correct. The for loop moves the iterator object itself, whereas while let accesses the iterator, and then moves the object being return.
bspeice *returned.
bspeice And given that you declared &mut self, moving anything out of self is a compilation error. Moving things the iterator generates is totally fine though.
melbourne2991
@melbourne2991
Nov 11 2018 03:40
Right ok, what does the for loop move the iterator object to exactly? - Not sure if that question even makes sense...still getting my head around borrowing concepts.
is the for loop trying to take ownership of the iterator object, whereas while let doesn't?
matrixbot
@matrixbot
Nov 11 2018 03:42
bspeice Absolutely correct. Consider as a separate example:
fn does_drop(another: &SomeObject) {
  let x = another.x;
}
bspeice This won't compile because you're moving/taking ownership of content you don't own. The for loop is doing the same thing, it just doesn't bind the self.lexer object to anywhere you can use later.
melbourne2991
@melbourne2991
Nov 11 2018 03:43
Ah I see... ok this is making more sense now
Mm definitely gives me some things to think about. Thanks for that, much appreciated.
melbourne2991
@melbourne2991
Nov 11 2018 04:02
@bspeice It looks like this works (adding &mut) as well - are then any implications to this approach i'm not aware of though:
    for (token, metadata) in &mut self.lexer {
      match token {
        TokenType::Unexpected => {
          println!("Unexpected token!");
          break;
        }
        _ => {
          println!("{:?}", metadata);
          println!("{:?}", token);
        }
      }
    }
Denis Lisov
@tanriol
Nov 11 2018 08:28
@melbourne2991 Do you want to add other functions to the Parser? For now we see only new and parse, and it looks like a free function would work better.
zolkko
@zolkko
Nov 11 2018 10:35

Hi! Could someone explain it to me? When I add a trait bound TheTrait to the DoNothing, the program stops compiling,

the method `do_nothing` exists but the following trait bounds were not satisfied:
           `std::boxed::Box<dyn TheTrait> : DoNothing`
           `&std::boxed::Box<dyn TheTrait> : DoNothing`
           `&mut std::boxed::Box<dyn TheTrait> : DoNothing`
           `dyn TheTrait : DoNothing`
           `&dyn TheTrait : DoNothing`
           `&mut dyn TheTrait : DoNothing`

despite that TheTrait is clearly implemented for both Box<T> and dyn TheTrait.

trait TheTrait {
    fn test(&self) { println!("{:p}", self); }
}

impl<T> TheTrait for Box<T> { }

struct SomeStruct(usize);

impl TheTrait for SomeStruct { }

trait DoNothing { fn do_nothing(self) -> Self; }

impl<T> DoNothing for T
// Uncomment me =]
// where T: TheTrait
{
    fn do_nothing(self) -> Self { self }
}

fn main() {
    let value1 = SomeStruct(123);
    value1.test();

    let value2: SomeStruct = value1.do_nothing();
    value2.test();

    let value3: Box<dyn TheTrait> = Box::new(value2);
    value3.test();

    let value4: Box<dyn TheTrait> = value3.do_nothing();
    value4.test();

    let _ = value4.do_nothing();
}
red75prime
@red75prime
Nov 11 2018 11:29
Use impl<T: ?Sized> TheTrait for Box<T> { }
zolkko
@zolkko
Nov 11 2018 11:56
@red75prime Cool! It works, but I'm not sure why.
red75prime
@red75prime
Nov 11 2018 12:03
dyn TheTrait is a dynamically sized type (it isn't Sized). impl<T> uses T: Sized bound by default. https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
zolkko
@zolkko
Nov 11 2018 12:03
I mean, I thought that impl<T> TheTrait for Box<T> { } implements TheTrait for all the Ts both sized and unsized.
zolkko
@zolkko
Nov 11 2018 12:12
And that is why I am able to call value3.test();. @red75prime thanks for the link. I should think about it a bit more =]
red75prime
@red75prime
Nov 11 2018 12:23
value3.test() works because . (dot operator) dereferences left-hand side as needed. It desugars to <dyn TheTrait as TheTrait>::test(&*value3);, that is it uses TheTrait implementation for dyn TheTrait, not for Box<dyn TheTrait>
zolkko
@zolkko
Nov 11 2018 12:27
Got it. Now it all crystal clear for me =]
Akos Vandra
@axos88
Nov 11 2018 14:38

Hi,

I recently upgraded from 1.28 to 1.30, and OUT_DIR seems to have stopped being defined:

src/routes/statics.rs:

  include!(concat!(env!("OUT_DIR"), "/data.rs"));
error: couldn't read "src/routes/false/data.rs": No such file or directory (os error 2)
  --> src/routes/statics.rs:11:1
   |
11 | include!(concat!(env!("OUT_DIR"), "/data.rs"));
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
any idea why?
the file is being generated and updated
$ find . -name data.rs
./target/arm-unknown-linux-gnueabihf/debug/build/rust-angular-5121d155d2df7f5/out/data.rs
./target/debug/build/rust-angular-66683cf9bc17b7b/out/data.rs
./target/debug/build/rust-angular-2faa36bb832fed9/out/data.rs
one of those was updated today