These are chat archives for rust-lang/rust

28th
Feb 2019
Michal 'vorner' Vaner
@vorner
Feb 28 13:15
AFAIK there should be a rust release today (1.33.0). Does anyone have an idea at what time it usually happens?
Sylwester Rąpała
@xoac
Feb 28 14:12
because u want to iterate over all items and format is already iterator. For example if u iterate over Vec u create a new instance that takes or borrow Vec and iterate over that new instance see here https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator. I make your code compile: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5fb32f50c895b31e728ef5cb3a5056bc
I have also added & in read_bitmap() function before self.
@thedrow
Omer Katz
@thedrow
Feb 28 14:13
If I clone it the problem goes away
But I don't really wanna do that
Sylwester Rąpała
@xoac
Feb 28 14:13
@thedrow If u clone you move cloned instance not that one used in your struct.
Omer Katz
@thedrow
Feb 28 14:14
I know
Sylwester Rąpała
@xoac
Feb 28 14:14
so what u wanna do?
Omer Katz
@thedrow
Feb 28 14:14
Iterate over format
Sylwester Rąpała
@xoac
Feb 28 14:18
but without moving or modifying format? The clone is one of solution. The second is change format to &str and then call chars() at it. I don't know why are u using Chars in this structure.
Omer Katz
@thedrow
Feb 28 14:19
Because I get a String to begin with
Sylwester Rąpała
@xoac
Feb 28 14:20
so u can iterate over String
btw what is wrong with my solution with while loop or with solution with clone?
Omer Katz
@thedrow
Feb 28 14:21
clone is inefficient
std::iter::iterator is not implemented for std::string
Sylwester Rąpała
@xoac
Feb 28 14:24
did u read error?
std::string::String` is not an iterator; try calling `.chars()` or `.bytes()
did u try?
Omer Katz
@thedrow
Feb 28 14:24
I am calling chars()
In the constructor
Denis Lisov
@tanriol
Feb 28 14:25
What are you trying to do?
Sylwester Rąpała
@xoac
Feb 28 14:25
I don't get what u want to do. Call clone is cheap at this situation :)
Ingvar Stepanyan
@RReverser
Feb 28 14:25
It's not and it's not necessary here... The code above compiles, why do you need cloning?

I make your code compile: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5fb32f50c895b31e728ef5cb3a5056bc

this one seems to have solved the problem already?

Omer Katz
@thedrow
Feb 28 14:26
I only need cloning because I wanted to use for?
That doesn't make sense
Ingvar Stepanyan
@RReverser
Feb 28 14:26
Except .chars() can be hidden into the constructor, but anyway you don't need any cloning here
Omer Katz
@thedrow
Feb 28 14:27
Well the fact is that the code fails to compile without it
Ingvar Stepanyan
@RReverser
Feb 28 14:27
Which code?
Ingvar Stepanyan
@RReverser
Feb 28 14:27
Without what?
Omer Katz
@thedrow
Feb 28 14:27
Without clone()
Sylwester Rąpała
@xoac
Feb 28 14:28
you misunderstand concepts. It's good that it fail without clone.
Omer Katz
@thedrow
Feb 28 14:28
Why?
a for loop is just a syntactic sugar for a while loop
Sylwester Rąpała
@xoac
Feb 28 14:30
Chars<'a> is an iterator. It store information to underlying "string" (at this point to &str) and actual position. When iterator go to the end it will be empty, nothing more to return.
@RReverser why clone of Chars<'a> is not cheap? I think it's only a reference to &str and actual position in this? + borrow at compile time. Am I wrong?
Ingvar Stepanyan
@RReverser
Feb 28 14:32
If it's clone of Chars then your iterator won't properly advance
Likely not what you want
(After you finish iteration, the iterator in structure will be unmodified)
Omer Katz
@thedrow
Feb 28 14:32
So I have to use a while loop?
I don't need to change anything
I just need to iterate over the characters of the string
Ingvar Stepanyan
@RReverser
Feb 28 14:33
Like above, yeah. But it depends on what you want to do with each char. If you don't really need &selfin read_bitmap, you can use for too
but with &mut self.format to avoid moving
Denis Lisov
@tanriol
Feb 28 14:33
Does read_bitmap access self.format?
Omer Katz
@thedrow
Feb 28 14:33
no
@RReverser This is a test case.
I do need &self.
No one accesses self.format but that loop
Ingvar Stepanyan
@RReverser
Feb 28 14:34
Then you should be able to do for p in &mut self.format { /* do something withp*/ }
just don't use a separate function that takes &self because that will confuse borrow checker
or you can do the same with your original for ... in self.format if you really want to take self by value, just, again, don't use a separate function
Omer Katz
@thedrow
Feb 28 14:36
cannot borrow*selfas mutable more than once at a time - your first suggestion
Ingvar Stepanyan
@RReverser
Feb 28 14:37
did you read second part?
as I said, remove a call to separate function
e.g. this works
impl<'a> S<'a> {
    fn deserialize(mut self) -> () {
        for p in self.format {
            /* do something with `p` */
            ()
        }

        ()
    }
}
Omer Katz
@thedrow
Feb 28 14:46
But I want to make this function as short as possible
Ingvar Stepanyan
@RReverser
Feb 28 14:47
It should be short
Omer Katz
@thedrow
Feb 28 14:47
It has a huge match clause
Ingvar Stepanyan
@RReverser
Feb 28 14:47
You can still use a separate helper for read_bitmap, just don't take S
I suppose it only needs the current character?
It would help if you'd post the full example
Omer Katz
@thedrow
Feb 28 14:48
It needs to mutate a cursor
I'm about to do so now.
Ingvar Stepanyan
@RReverser
Feb 28 14:48
You can pass the cursor too
As usual in Rust, just need to cleanly separate responsibilities / data being shared
Omer Katz
@thedrow
Feb 28 14:48
It's held in the struct
Why do I need to pass it around
It's bad API
Ingvar Stepanyan
@RReverser
Feb 28 14:49
Not really, it's usually better to split responsibilities into own structs than mix things up
Anyway, just post an example, let's see what can be done
Ingvar Stepanyan
@RReverser
Feb 28 14:58
Wait, so deserialize is the only one that accesses the chars and just reads it fully?
Omer Katz
@thedrow
Feb 28 14:58
Yes
Ingvar Stepanyan
@RReverser
Feb 28 14:59
Then you don't need to store Chars on the structure, just store &str and call .chars() inside the function
No mutation of the structure == no problem
Omer Katz
@thedrow
Feb 28 15:00
That works
Denis Lisov
@tanriol
Feb 28 15:01
How is this struct actually supposed to be used?
Omer Katz
@thedrow
Feb 28 15:01
We initialize it with a buffer and format, it deserializes it and no one uses it again
Denis Lisov
@tanriol
Feb 28 15:03
I'm not sure whether this should be a struct at all :-) why not just fn deserialize(format: &str, buffer: &str)?
Omer Katz
@thedrow
Feb 28 15:03
Because it's a really long method which maintains state
when you read the bitmaps it has to mutate the bits and whatnot
and every other deserialized type except a byte array resets the bitmap
The code is long as it is now
Ingvar Stepanyan
@RReverser
Feb 28 15:04
It's probably a good idea to hide this structure still, and expose a function that uses it internally
Omer Katz
@thedrow
Feb 28 15:04
I am doing so
I mean it's exported to Python :)
as a function
Ingvar Stepanyan
@RReverser
Feb 28 15:05
Great, sounds like your problem is solved then :)
Omer Katz
@thedrow
Feb 28 15:05
Yeh. Thanks.
Denis Lisov
@tanriol
Feb 28 15:07
I'd probably just make this deserialize method a function instead (and wrap it directly) as it is already short, no?
However, these are just personal preferences :-)
Omer Katz
@thedrow
Feb 28 15:09
A function should be about 10 or so lines
Anything larger than that is huge imo
Denis Lisov
@tanriol
Feb 28 15:17
I hope no one has to call it like Deserializer::new(format, buffer).deserialize() :-)
Omer Katz
@thedrow
Feb 28 15:17
Nope. You have raise python exceptions somehow
Which I will do later
Omer Katz
@thedrow
Feb 28 15:40
What's the equivalent of Python's exponential operator (**) in Rust?
Ingvar Stepanyan
@RReverser
Feb 28 15:41
.pow(...)
Omer Katz
@thedrow
Feb 28 15:41
Hmm
    fn read_decimal(&mut self) -> io::Result<PyObject> {
        let d = self.cursor.read_u8()?;
        let n = self.cursor.read_i32()?;

        let d = DECIMAL_CLASS.call(
            *self.py,
            (d,),
            None
        )?;
        let n = DECIMAL_CLASS.call(
            *self.py,
            (10_i32.pow(n),),
            None
        )?;

        Ok(self.py.None())
    }
So I have this thingy (which will obviously not return None later). the types are incompatible and I'm afraid to cast it the wrong way. Any pointers?
pow() expects u32.
Ingvar Stepanyan
@RReverser
Feb 28 15:45
Well yeah because with negative exponent you would get a floating result (it becomes a root instead)
So it's up to you to know whether n can be negative and what you want to do then
Omer Katz
@thedrow
Feb 28 15:45
But the protocol apparently decodes it as a long integer
Strange choice.
Ingvar Stepanyan
@RReverser
Feb 28 15:46
Yeah. I guess you can read it as u32 instead? Or cast assuming it's always >=0? Only you (or someone else familiar with the protocol) can answer that question :)
Omer Katz
@thedrow
Feb 28 15:47
Decimal values are not intended to support floating point values, but rather fixed-point business values such as currency rates and amounts. They are encoded as an octet representing the number of places followed by a long signed integer. The 'decimals' octet is not signed.
That's from the AMQP standard.
Ingvar Stepanyan
@RReverser
Feb 28 15:48

The 'decimals' octet is not signed.

Well I guess this answers your question

Omer Katz
@thedrow
Feb 28 15:48
Essentially what we do is divide d with n afterwards
I'm not sure I am reading this correctly.
Ingvar Stepanyan
@RReverser
Feb 28 15:48
Ah wait, that's about the first part
So yeah, apparently what they're saying is that this is an encoding for sort-of floats. I suppose you either need to use a custom structure or, well, convert each argument to float with a risk of losing precision.
Omer Katz
@thedrow
Feb 28 15:50
Oh
I got it backwards LOL
val = Decimal(n) / Decimal(10 ** d)
That's the python version
Omer Katz
@thedrow
Feb 28 15:57
How do you guys debug rust?
Sylwester Rąpała
@xoac
Feb 28 15:57
I use prettyenvlogger and log crate
Ingvar Stepanyan
@RReverser
Feb 28 15:57
With VSCode
Zakarum
@omni-viral
Feb 28 15:58
Debug? What is it?
Omer Katz
@thedrow
Feb 28 15:58
I'm not even getting a stack trace from Rust because Python crashes
So I'm assuming one of my calls to CPython failed.
Sylwester Rąpała
@xoac
Feb 28 15:59
I don't use debugger. If sth panic I write test for it and use RUST_BACKTRACE=full to see what I should tested.
Omer Katz
@thedrow
Feb 28 16:00
I have tests. But they are written in Python.
Zakarum
@omni-viral
Feb 28 16:00
multilanguage applications are always hard to debug
Omer Katz
@thedrow
Feb 28 16:00
I'm commenting stuff out :P
Sylwester Rąpała
@xoac
Feb 28 16:01
U asked how we debug rust. I just tell u my way and I write only Rust at this moment :)
Zakarum
@omni-viral
Feb 28 16:01
Doesn't CPython have some asserts to validate your arguments before crashing?
Omer Katz
@thedrow
Feb 28 16:02
Yeh but I'm not sure what's going on...
Michal 'vorner' Vaner
@vorner
Feb 28 16:02
Mostly, I debug by thinking hard, guessing which part is responsible and reading the code. It works quite well, but takes time to learn.
Omer Katz
@thedrow
Feb 28 16:02
I guess I meant which debugger you use
Michal 'vorner' Vaner
@vorner
Feb 28 16:03
But logging or a stack trace (from gdb or whatever) is a nice help, as it points to the part to read faster than guessing.
Ingvar Stepanyan
@RReverser
Feb 28 16:04
@thedrow If you're on Mac / Linux, VSCode + CodeLLDB are really nice and have Cargo integration etc.
But generally any native debugger would do
Ichoran
@Ichoran
Feb 28 17:51
I mostly debug with thinking + println!
Then if possible write a test to make sure the behavior doesn't fail in that way again.
Brian Knapp
@knappador
Feb 28 19:04
The new !dbgmacro is handy
Ichoran
@Ichoran
Feb 28 19:21
I'm looking forward to using it. I haven't had to debug anything since dbg! went into stable :joy:
uncotion
@uncotion
Feb 28 20:13

I’m was reading a library’s manual that uses + operators between traits, what's the meaning of this?

impl<S, T, U> Service for FramedService<S, T, U> where
    T: AsyncRead + AsyncWrite,
    U: Decoder + Encoder,
    S: NewService<Request = <U as Decoder>::Item, Response = <U as Encoder>::Item>,
    <<S as NewService>::Service as Service>::Future: 'static,
    <<S as NewService>::Service as Service>::Error: 'static,
    <U as Encoder>::Item: 'static,
    <U as Encoder>::Error: 'static,

Another one that uses between a trait and lifetime !

impl<'a, S> Service for &'a mut S where
    S: 'a + Service,
Ichoran
@Ichoran
Feb 28 20:20
It means both things are true of the type.
Brian Knapp
@knappador
Feb 28 20:40
No such thing as a static block? Noticed about a third of my deps are using lazy_static
I'd like a static Mutex to avoid depending on fs2 for file locking. Not switching to single threaded tests over one contention case.
uncotion
@uncotion
Feb 28 20:41
@Ichoran thanks . 🙏
Denis Lisov
@tanriol
Feb 28 20:52
@knappador How about just copying the file to be locked to a temporary directory per-test?