These are chat archives for rust-lang/rust

11th
Mar 2018
Ingvar Stepanyan
@RReverser
Mar 11 2018 00:23
Oh yeah that would work if you don't need to compare actual Vec<Value>
And better for storage too (avoiding tag on each element)
But I thought you still need to compare Vec<Value> at least in ComplexValue case?
kristopher tate
@kristate
Mar 11 2018 00:55

hey, any way to tell liballoc that the program will exit?

background: so I'm linking a statically compiled rust library into a C program, but when I use println!("hello");some temporary values get stored on the heap.

Moggers
@Moggers
Mar 11 2018 03:06
If I have a type Mutex<Option<u32>>
is it possible to do a match mutex.lock() { Ok(Some(num)) => {}, Err(_) => {}}
Yuji Kanagawa
@kngwyu
Mar 11 2018 04:23
@Moggers
mutex.lock() returns Result<MutexGuard, PoisonError<MutexGuard>> so it's impossible to match Ok(Some(..).
We can't use type coercion by Deref in match statement.
Moggers
@Moggers
Mar 11 2018 04:24
yeah thats what I figured ._.
Zachary Neely
@zrneely
Mar 11 2018 07:12
I'm writing a function that wraps a call to Iterator::filter. Why do I need a where for <'r> F: FnMut(&'r &T) -> bool clause instead of a where F: FnMut(&T) -> bool clause?
Zakarum
@omni-viral
Mar 11 2018 07:13
@zrneely Because your Iterator::Item is already a reference. Probably
Note that FnMut(&T) -> bool is equivalent to for<'r> FnMut(&'r T) -> bool
But you need FnMut(&&'a T) -> bool when your Iterator::Item is &'a T
Zachary Neely
@zrneely
Mar 11 2018 07:15
Hmm, so maybe I just need &&T?
Zakarum
@omni-viral
Mar 11 2018 07:15
Yeap.
Zachary Neely
@zrneely
Mar 11 2018 07:15
It would be nice if the compiler suggested that instead of the weird for clause :/
Zakarum
@omni-viral
Mar 11 2018 07:16
@zrneely compiler uses verbose syntax
They are almost equivalent
Michal 'vorner' Vaner
@vorner
Mar 11 2018 08:30
Hello. I'm wondering, let's say I have a text that I read line by line from a file, or something (I don't store the whole text in RAM). I want to compute a histogram of „words“ (log messages, actually, and there are limited set of them in the file). So I take HashMap<String, u64> and then after extracting each one, I do something like *map.entry(word.to_owned()).or_insert(0) += 1. I understand why entry needs owned version, because it might need to insert it. But most of the times it will have the entry already there, so the cloned instance will be dropped immediately after. That sounds like a waste. Is there a way to clone it lazily, only if it is actually needed? I haven't found a way, but maybe there's a trick/common pattern I'm missing.
Andrew Gaspar
@AndrewGaspar
Mar 11 2018 09:00
Is there any way to get rustc to print out which libraries are required to be linked on Windows for std? I would prefer to pull this information from the compiler if available - right now I'm hard coding advapi32 kernel32 shell32 userenv ws2_32 on all builds,msvcrtd on debug builds, and msvcrt on release builds.
Michal 'vorner' Vaner
@vorner
Mar 11 2018 09:02
I don't think the compiler can answer that, the linker may. But it should be possible to read it from the resulting binary (it is on Linux, with ldd). After all, when it starts, something must know what libraries to load for it.
Andrew Gaspar
@AndrewGaspar
Mar 11 2018 09:12
Unfortunately, this isn't for a PE, but for a staticlib. I'm using Cargo to build a staticlib and then linking it with other objects built from C++ source files
I think ldd can only tell you about dynamic library requirements
Ah, I found it. :) cargo rustc -- --print=native-static-libs
Niranjan A Kartha
@n-kartha
Mar 11 2018 09:22
Oh, speaking of static libs, do dynamic libs (dylib) even compile anymore?
cargo build just gets stuck whenever I try
Denis Lisov
@tanriol
Mar 11 2018 09:38
@vorner There were some suggestions about that (rust-lang/rust#35463, rust-lang/rfcs#1203, RFC rust-lang/rfcs#1533 and the most recent RFC rust-lang/rfcs#1769 ), but nothing accepted yet.
redtankd
@redtankd
Mar 11 2018 14:00
Could I use for loop to call flat_map repeatedly?
let p = vec![(Vec::new(), (1..10).collect::<Vec<u32>>())];
    let p_iter = p.into_iter();
    let b= p_iter    
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) })
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) })
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) })
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) })
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) })
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) })
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) })
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) })
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) });
Niranjan A Kartha
@n-kartha
Mar 11 2018 14:01
Yeah
Store b in a mut
And update it in a for loop
redtankd
@redtankd
Mar 11 2018 14:14
It doesn't work
let p = vec![(Vec::new(), (1..10).collect::<Vec<u32>>())];
    let p_iter = p.into_iter();
    let mut b= p_iter    
        .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) });

for _ in 1..3 {
          b = b
            .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) });
    };
the error message
error[E0308]: mismatched types
  --> src/bin/00032.rs:42:15
   |
42 |             b = b
   |  _______________^
43 | |             .flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) });
   | |________________________________________________________________________^ expected struct `std::vec::IntoIter`, found struct `std::iter::FlatMap`
   |
   = note: expected type `std::iter::FlatMap<std::vec::IntoIter<_>, _, [closure@src/bin/00032.rs:23:19: 23:68]>`
              found type `std::iter::FlatMap<std::iter::FlatMap<std::vec::IntoIter<_>, impl std::iter::Iterator, [closure@src/bin/00032.rs:23:19: 23:68]>, _, [closure@src/bin/00032.rs:43:23: 43:72]>`
Niranjan A Kartha
@n-kartha
Mar 11 2018 14:17
@redtankd Try this:
let mut b: std::iter::FlatMap<std::vec::IntoIter<_> = p_iter.flat_map(|(drawn, to_draw)| { draw_digit(drawn, to_draw) });
I'm not sure it will work, though
Ingvar Stepanyan
@RReverser
Mar 11 2018 14:20
You can't w/o collect because flat_map returns type that says what was the source and what was the closure
So first time you call it, it would be FlatMap<Src, ..>, second time FlatMap<FlatMap<Src, ..>, ..>, and so on nesting previous result
And you can't use iteration to construct values of different types each time
Niranjan A Kartha
@n-kartha
Mar 11 2018 14:22
@RReverser My bad :P I'm kinda new
Ingvar Stepanyan
@RReverser
Mar 11 2018 14:23
@redtankd What are you trying to do though?
Or rather, why do you need repetitive flat_map?
redtankd
@redtankd
Mar 11 2018 14:48
@RReverser I just program the permutation of 1 to 9. A personal study.
Ingvar Stepanyan
@RReverser
Mar 11 2018 14:51
It's better to make it a recursive function then (assuming you don't want to use one of existing crates for permutations)
redtankd
@redtankd
Mar 11 2018 15:18
yes. thank you!
bspeice
@bspeice
Mar 11 2018 17:50
Does rust have a specific rule for naming the test binary?
bspeice
@bspeice
Mar 11 2018 18:03
I can debug through <project_name>-<some_hash> but I don't know how (or if) to figure out the <some_hash> part.
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 18:52
@bspeice I think rustc has a --test option, but i dunno how to use it.
I don't think cargo test builds are very predictable, but is that an issue? Because I would expect to run cargo test to run the tests.
bspeice
@bspeice
Mar 11 2018 18:58
I'm trying to figure out if there's a good way to debug through the tests.
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 18:58
ah, with gdb or... the other one I forget the name.
bspeice
@bspeice
Mar 11 2018 18:58
lldb.
But more the issue is that debug configs in VS Code need the program they're actually debugging for, which is difficult because it always has a weird name.
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 19:05
well it looks like cargo does tell you what binary it runs for the test. So at the least you can put that in to the VS debugger manually
but I think VS Code may need to support it directly? I dunno.
bspeice
@bspeice
Mar 11 2018 19:12
Maybe figure out a way of creating a new launch config? Don't know either, but how does one go about figuring out what the binary is?
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 19:12
when I run cargo test it just says it
   Compiling difference-of-squares v1.2.0 (file:///home/alex/exercism/rust/difference-of-squares)
    Finished dev [unoptimized + debuginfo] target(s) in 0.74 secs
     Running target/debug/deps/difference_of_squares-b00656f83c7d40e7
Daniel Chao
@bioball
Mar 11 2018 19:17
is it possible to implement an Index that returns references with lifetimes?
am getting this error:
error[E0308]: method not compatible with trait
   --> src/lib.rs:145:5
    |
145 | /     fn index(&self, index: usize) -> &'a T {
146 | |         if index >= self.len() {
147 | |             panic!("Index OOB");
148 | |         }
149 | |         &self.storage[index]
150 | |     }
    | |_____^ lifetime mismatch
    |
    = note: expected type `fn(&StackVec<'a, T>, usize) -> &T`
               found type `fn(&StackVec<'a, T>, usize) -> &'a T`
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 19:18
the returned lifetime has to reference the lifetime of an argument,
bspeice
@bspeice
Mar 11 2018 19:18
@Ghoughpteighbteau - Fair, but it still has to run the tests.
Denis Lisov
@tanriol
Mar 11 2018 19:19
@bioball The reference returned borrows from self
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 19:20
@bspeice yah, but then I can run that binary directly with gdb and do the debugging there. The binary doesn't get cleared out, so you should be able to manually specify it. I admit this isn't a great workflow for VSCode...
Daniel Chao
@bioball
Mar 11 2018 19:20
@tanriol what's wrong with that?
Denis Lisov
@tanriol
Mar 11 2018 19:25
The returned lifetime for Index::index matches the lifetime of &self.
Daniel Chao
@bioball
Mar 11 2018 19:27
hm. ok, so basically i can't return &'a T out of Index::index
?
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 19:28
OK, so I'm still pretty green here, but my understanding is that label 'a is there to refer to a lifetime somewhere else in the function signature, it can't be on its own.
I think @tanriol is trying to say that you shouldn't need to specify the lifetime of 'a because it should have the lifetime of &self
but if you do want to specify a lifetime, then 'a should refer to an argument in the signature somewhere.
Daniel Chao
@bioball
Mar 11 2018 19:30
it's in the impl
impl<'a, T> Index<usize> for StackVec<'a, T> {
    type Output = T;
    fn index(&self, index: usize) -> &T {
        if index >= self.len() {
            panic!("Index OOB");
        }
        &self.storage[index]
    }
}
that above example compiles. but maybe i have a deeper misunderstanding of lifetimes then
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 19:31
maybe I'm wrong here but I think these lifetime specifiers are particular to where they are declared, I think if you want to use 'a in fn index you need to specify that you're using it like this: fn longest<'a>(x: &'a str, y: &'a str) -> &'a str
fn index<'a> (&'a self, index: usize) ->&'aT { specifically. I think.
Daniel Chao
@bioball
Mar 11 2018 19:33
mm you can specify lifetime bounds at impl
this compiles just fine too:
impl<'a, T> Index<usize> for StackVec<'a, T> {
    type Output = T;
    fn index<'b>(&'b self, index: usize) -> &'b T {
        if index >= self.len() {
            panic!("Index OOB");
        }
        &self.storage[index]
    }
}
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 19:36
My understanding is that if things are compiling, then you shouldn't need to go out of your way to specify any lifetimes. The only reason we add lifetimes is to make compilation faster and errors more local. Rust could theoretically work the lifetimes out on its own, it's just expecting you to do it when it's slightly ambiguous.
Daniel Chao
@bioball
Mar 11 2018 19:36
what i wanted to say was "the returned value has the same lifetime as StackVec's lifetime parameter"
ok
Daniel Chao
@bioball
Mar 11 2018 20:20
more on this:
impl<'a, T> Iterator for StackIterator<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        if self.next >= self._vec.len() {
            return None
        }
        let item = &self._vec[self.next];
        self.next += 1;
        Some(item)
    }
}
i'm getting this error:
   Compiling stack-vec v0.1.0 (file:///Users/danielchao/code/cs140e/1-shell/stack-vec)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
   --> src/lib.rs:172:21
    |
172 |         let item = &self._vec[self.next];
    |                     ^^^^^^^^^^^^^^^^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 168:5...
   --> src/lib.rs:168:5
    |
168 | /     fn next(&mut self) -> Option<&'a T> {
169 | |         if self.next >= self._vec.len() {
170 | |             return None
171 | |         }
...   |
174 | |         Some(item)
175 | |     }
    | |_____^
note: ...so that reference does not outlive borrowed content
   --> src/lib.rs:172:21
    |
172 |         let item = &self._vec[self.next];
    |                     ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 166:1...
   --> src/lib.rs:166:1
    |
166 | / impl<'a, T> Iterator for StackIterator<'a, T> {
167 | |     type Item = &'a T;
168 | |     fn next(&mut self) -> Option<&'a T> {
169 | |         if self.next >= self._vec.len() {
...   |
175 | |     }
176 | | }
    | |_^
note: ...so that expression is assignable (expected core::option::Option<&'a T>, found core::option::Option<&T>)
   --> src/lib.rs:174:9
    |
174 |         Some(item)
    |         ^^^^^^^^^^
so... what's wrong here?
i've also tried annotating the type:
impl<'a, T> Iterator for StackIterator<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        if self.next >= self._vec.len() {
            return None
        }
        let item: &'a T = &self._vec[self.next];
        self.next += 1;
        Some(item)
    }
}
and i'm getting the same error
Denis Lisov
@tanriol
Mar 11 2018 20:42
What's the type of self._vec?
Daniel Chao
@bioball
Mar 11 2018 20:43
StackVec<'a, T>
here's the struct:
pub struct StackIterator<'a, T: 'a> {
    _vec: StackVec<'a, T>,
    next: usize,
}
bspeice
@bspeice
Mar 11 2018 20:43
@Ghoughpteighbteau Ultimate resolution for VSCode - you can create an extension, register a command there, and use that command to look up the target binary. So theoretically could create task configuration that auto-finds the test binary, and runs that, allowing you to have automatic debug.
So... It's complicated.
bspeice
@bspeice
Mar 11 2018 20:56
Alternately, I could probably just write a shell script that whenever you "build," it updates a symlink, and just trigger off that.
Denis Lisov
@tanriol
Mar 11 2018 20:56
@bioball I'm pretty sure this cannot be done in safe code as it would be unsound. Consider something like this
let vec: StackVec<_, _> = ...;
let it: StackIterator<_, _> = vec.into_iter();
let first_item = it.next();
// I assume we're in the same module where `StackIterator` is defined
let StackIterator { _vec: extracted_vec, next: _ } = it; // we can do this if `it` is not borrowed, which your return type indicates
extracted_vec.clear(); // here we drop all the items, including the one pointed to by `first_item`
println!("{:?}", first_item); // OOPS!
Daniel Chao
@bioball
Mar 11 2018 20:57
hm. gotcha. so i should be returning cloned items then?
Denis Lisov
@tanriol
Mar 11 2018 20:59
You have multiple options...
...the most basic is probably to return Option<&T> so that it borrows from the iterator itself.
Daniel Chao
@bioball
Mar 11 2018 21:05
i tried doing that
impl<'a, T> Iterator for StackIterator<'a, T> {
    type Item = &T;
    fn next(&mut self) -> Option<&T> {
        if self.next >= self._vec.len() {
            return None
        }
        let item = &self._vec[self.next];
        self.next += 1;
        Some(item)
    }
}
but, am getting this error:
   Compiling stack-vec v0.1.0 (file:///Users/danielchao/code/cs140e/1-shell/stack-vec)
error[E0106]: missing lifetime specifier
   --> src/lib.rs:167:17
    |
167 |     type Item = &T;
    |                 ^ expected lifetime parameter
Denis Lisov
@tanriol
Mar 11 2018 21:06
Hmm... not sure of the correct way, I'll try something like this now :-)
Daniel Chao
@bioball
Mar 11 2018 21:07
hah ok, thanks
Dylan DPC
@Dylan-DPC
Mar 11 2018 21:08

@bioball i think you have to do

type Item = &'a T;

as the error suggests. Try doing it. Not sure if that works

Daniel Chao
@bioball
Mar 11 2018 21:09
@Dylan-DPC yup, that's what i had initially
Dylan DPC
@Dylan-DPC
Mar 11 2018 21:10
and?
Daniel Chao
@bioball
Mar 11 2018 21:10
scroll a little bit above to see the error i'm trying to debug right now
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 21:12
well. you were specifying the Option<&'a T> type remember? other than that it's the same <.<
Denis Lisov
@tanriol
Mar 11 2018 21:14
Ok, so this article seems to answer the question we're asking :-(
Daniel Chao
@bioball
Mar 11 2018 21:14
@Ghoughpteighbteau huh?
Ghoughpteighbteau
@Ghoughpteighbteau
Mar 11 2018 21:16
Daniel Chao
@bioball
Mar 11 2018 21:24
i'm confused. where did that second snippet come from?
are you saying that's diff is what i should be doing?
@tanriol just read through that article. thanks!
still not sure how it fixes my problem though..
Dylan DPC
@Dylan-DPC
Mar 11 2018 21:29
sounds odd but maybe you need a &'a mut self as the param? not sure if that works
Daniel Chao
@bioball
Mar 11 2018 21:31
just tried that, got this error:
    = note: expected type `fn(&mut StackIterator<'a, T>) -> core::option::Option<&T>`
               found type `fn(&'a mut StackIterator<'a, T>) -> core::option::Option<&'a T>`
Dylan DPC
@Dylan-DPC
Mar 11 2018 21:32
guessed so :D
maybe it should be:
let item = &self._vec[&self.next]; ?
Daniel Chao
@bioball
Mar 11 2018 21:38
nope.. doesn't work
Denis Lisov
@tanriol
Mar 11 2018 21:41
@bioball Take a look at an iterator for slices
The point here is that the data is not stored inside the iterator
Daniel Chao
@bioball
Mar 11 2018 21:57
ok, hm
i think the issue is around the fact that my StackVec is backed by a mutable array
if you take out the mut in storage: &'a mut [T], the program compiles
Daniel Chao
@bioball
Mar 11 2018 22:06
i'm still not sure why it doesn't compile though.
Denis Lisov
@tanriol
Mar 11 2018 23:15
@bioball I'm not sure too, but _vec: &'a StackVec<'a, T>, makes it compile too