These are chat archives for rust-lang/rust

8th
Aug 2018
qq00
@qq00
Aug 08 2018 03:52

(context: I'm trying to understand low level internals of Rust)

Is there a way to write a function

fn foo<T> (t: T) -> [u8]

where foo takes an object of type T and convert it to (size_of<T>()) u8's

qq00
@qq00
Aug 08 2018 04:15
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
    ::std::slice::from_raw_parts(
        (p as *const T) as *const u8,
        ::std::mem::size_of::<T>(),
    )
}
(above is from stack overflow) -- is there a easy way to extend this to &Vec<T> ?/
Alexandre Bury
@gyscos
Aug 08 2018 04:28
@qq00 You want to convert &Vec<T> into &[u8]?
It's a bit risky, as alignment may cause some uninitialized bytes to be present between each value
Though it's already the case with this function
Ah neverminds it seems mem::size_of already take that into account. So you could do:
unsafe fn vec_to_bytes<T: Sized>(p: &Vec<T>) -> &[u8] {
    ::std::slice::from_raw_parts(
        p.as_ptr() as *const u8,
        ::std::mem::size_of::<T>() * p.len(),
    )
}
Alexandre Bury
@gyscos
Aug 08 2018 04:35
It's not that unsafe actually - I think uninitialized bytes caused by alignment is the only source of unsafety here.
Tim McNamara 🐍🦀
@timClicks_twitter
Aug 08 2018 07:21
@gyscos would the padding bytes
Be at the end of the Vec<>
Because std::memory::size_of() should take care of that
Tim McNamara 🐍🦀
@timClicks_twitter
Aug 08 2018 07:28
@qq00 You may wish to shrink your input vec to to its capacity with the shrink_to_fit() method
mnivoliez
@mnivoliez
Aug 08 2018 09:08

Hello everyone! I'm kind of stuck with the following piece of code:

pub fn persist_verbs_to_db(conn: &Connection, verbs: &[Verb]) -> Result<(), Box<Error + 'static>> {
    for item in verbs {
        println!("{:?}", item)
    }
    let user_registrations = verbs.into_iter().filter(|x| {
        if let Verb::RegisterUser { hash, year, sexe } = x {
            true
        } else {
            false
        }
    }).collect();
    persist_user_registrations(conn, user_registrations)?;
    //persist_session_creations(conn, verbs.filter(Verb::CreateSession).collect())?;
    Ok(())
}

It gives me that error:

error[E0277]: the trait bound `&[parser::verb::Verb]: std::iter::FromIterator<&parser::verb::Verb>` is not satisfied
  --> src\persistance.rs:16:8
   |
16 |     }).collect();
   |        ^^^^^^^ a collection of type `&[parser::verb::Verb]` cannot be built from an iterator over elements of type `&parser::verb::Verb`
   |
   = help: the trait `std::iter::FromIterator<&parser::verb::Verb>` is not implemented for `&[parser::verb::Verb]`

Any hint could really help me

Also, Verb is an enum where each variant is defined as
#[derive(Debug, PartialEq)]
pub enum Verb {
    RegisterUser {
        hash: String,
        year: u16,
        sexe: Sexe,
    },
    CreateSession {
        hash_player: String,
        hash: String,
        timestamp: u64,
        is_alone: bool,
    },
...
I got the feeling that I miss some reference other element
Denis Lisov
@tanriol
Aug 08 2018 09:22
@mnivoliez Try let user_registrations: Vec<_> = ... and persist_user_registrations(conn, &user_registrations)?;
mnivoliez
@mnivoliez
Aug 08 2018 09:26
I finnaly ended up with
pub fn persist_verbs_to_db(conn: &Connection, verbs: &[Verb]) -> Result<(), Box<Error + 'static>> {
    for item in verbs {
        println!("{:?}", item)
    }
    let user_registrations: Vec<_> = verbs
        .iter()
        .filter(|x| {
            if let Verb::RegisterUser { .. } = x {
                true
            } else {
                false
            }
        })
        .cloned()
        .collect();
    persist_user_registrations(conn, &user_registrations)?;
    //persist_session_creations(conn, verbs.filter(Verb::CreateSession).collect())?;
    Ok(())
}
Vesa Kaihlavirta
@vegai
Aug 08 2018 09:27
is that if in the filter actually needed?
Verb::RegisterUser { .. } == x wouldn’t work?
mnivoliez
@mnivoliez
Aug 08 2018 09:27
let me try
it seems not
Vesa Kaihlavirta
@vegai
Aug 08 2018 09:28
ok :)
mnivoliez
@mnivoliez
Aug 08 2018 09:28
but if you got another way to get rid of that if, I'm all ears
Vesa Kaihlavirta
@vegai
Aug 08 2018 09:29
if clauses with just “true” and “false” in each block always smell like they should be simplified somehow
but perhaps the "if let” phrase makes this a bit different
Denis Lisov
@tanriol
Aug 08 2018 09:29
@qq00 I'd really suggest you reconsider what you're doing. Exposing uninitialized data for Rust is not "just" unsafety, but undefined behavior and the compiler can do lots of tricks you would not expect it to do. For example, if you have a loop that reads that data and saves it somewhere, the compiler is allowed to reason "this loop would save uninitialized data, which is UB, so this loop can be deleted". If you have an if/else comparing an uninitialized byte with 0, it can execute both if and else(!). Pretty sure you don't want to deal with this, do you?
mnivoliez
@mnivoliez
Aug 08 2018 09:29
I'm not fan of the if true { true } either
Denis Lisov
@tanriol
Aug 08 2018 09:31
Maybe rewriting it with match would actually be less confusing...
mnivoliez
@mnivoliez
Aug 08 2018 09:31
@tanriol @qq00 out of curiosity, what does it mean when the '::' (turbo fish I assume) when use in first (like ::std::bla::bla::bla)?
@tanriol yeah but it will looks like match x { Verb::RegisterUser { .. } => true, _=> false, }
Denis Lisov
@tanriol
Aug 08 2018 09:33
Leading :: means it's an absolute path (from the crate root)
mnivoliez
@mnivoliez
Aug 08 2018 09:33
@tanriol thanks :)
@tanriol it seems nicer with match indeed:
pub fn persist_verbs_to_db(conn: &Connection, verbs: &[Verb]) -> Result<(), Box<Error + 'static>> {
    for item in verbs {
        println!("{:?}", item)
    }
    let user_registrations: Vec<_> = verbs
        .iter()
        .filter(|x| match x {
            Verb::RegisterUser { .. } => true,
            _ => false,
        })
        .cloned()
        .collect();
    persist_user_registrations(conn, &user_registrations)?;
    //persist_session_creations(conn, verbs.filter(Verb::CreateSession).collect())?;
    Ok(())
}
mnivoliez
@mnivoliez
Aug 08 2018 09:42

that being said, I falling into the following sictuation:

pub fn persist_verbs_to_db(conn: &Connection, verbs: &[Verb]) -> Result<(), Box<Error + 'static>> {
    for item in verbs {
        println!("{:?}", item)
    }
    let user_registrations: Vec<_> = verbs
        .iter()
        .filter(|x| match x {
            Verb::RegisterUser { .. } => true,
            _ => false,
        })
        .cloned()
        .collect();
    persist_user_registrations(conn, &user_registrations)?;
    let session_creations: Vec<_> = verbs
        .iter()
        .filter(|x| match x {
            Verb::CreateSession { .. } => true,
            _ => false,
        })
        .cloned()
        .collect();
    persist_session_creations(conn, &session_creations)?;
    Ok(())
}

As the enum got 10 possible value (for now) I wonder if there is another way to do that.

Denis Lisov
@tanriol
Aug 08 2018 10:27
Create the vectors and then, in a single loop, match the verb to the vector and push it into the vector?
mnivoliez
@mnivoliez
Aug 08 2018 11:06
I could do.
A Dinesh
@dineshadepu
Aug 08 2018 13:02
Hello guys, what's the meaning of <AtomicUsize> in here https://doc.rust-lang.org/std/sync/atomic/constant.ATOMIC_USIZE_INIT.html
I don't understand the syntax of <SOMETING>
Zakarum
@omni-viral
Aug 08 2018 13:02
@dineshadepu <T> is same as T but disambiguated for the context
T::X can be ambigous. if T has X associated item and T implements trait Y that has associated item X
In this case <T>::X is the X from T and <T as Y>::X is the X from Y implementation
<T> on it's own doesn't make any sense
It's always <T>::X
or <T as Y>::X
A Dinesh
@dineshadepu
Aug 08 2018 15:01
Sorry for late reply. I lost my connection @omni-viral . Can I get some simple example, or some documentation? Thank you.
Zakarum
@omni-viral
Aug 08 2018 15:04
Are you familiar with <X as Y>::Z syntax?
A Dinesh
@dineshadepu
Aug 08 2018 15:04
No
Sort of
Zakarum
@omni-viral
Aug 08 2018 15:05
Ok. Here
A Dinesh
@dineshadepu
Aug 08 2018 15:05
I think X is a struct, and X implements trait Y, so when we call Z function , we convert get a reference of our struct as that trait and call that Z function
Zakarum
@omni-viral
Aug 08 2018 15:05
struct X;
trait Y { type Z; }
impl Y for X { type Z = u32; }
Conider you have this code
How to access associated type Z of X
Simple. Write X::Z
But what it X implements something else with associated type Z?
trait U { type Z; }
impl U for X { type Z = u64; }
A Dinesh
@dineshadepu
Aug 08 2018 15:07
OK
Zakarum
@omni-viral
Aug 08 2018 15:16
So what the type of X::Z?
It's ambigous
A Dinesh
@dineshadepu
Aug 08 2018 15:17
Yes
Zakarum
@omni-viral
Aug 08 2018 15:17
But you can write <X as Y>::Z or <X as U>::Z to disambiguate
A Dinesh
@dineshadepu
Aug 08 2018 15:17
So <X as U> gives us u64
Zakarum
@omni-viral
Aug 08 2018 15:17
Yeap
Finally if you have impl X { type Z = u128; } you also have <X>::Z that is u128
A Dinesh
@dineshadepu
Aug 08 2018 15:18
Ohh. So it's self type
Zakarum
@omni-viral
Aug 08 2018 15:18
Although X::Z is not ambigous in case <X>::Z exists
A Dinesh
@dineshadepu
Aug 08 2018 15:19
I think to understand trait type I should complete advanced traits section?
Zakarum
@omni-viral
Aug 08 2018 15:19
This works the same for associated type, associated constants and methods. Any item that can be defined inside impl block
You should read the book til the last page :smile:
A Dinesh
@dineshadepu
Aug 08 2018 15:20
Got it.
A Dinesh
@dineshadepu
Aug 08 2018 17:02
Can some one explain me this?
thread_local!(static IDX: usize = CNT.fetch_add(1, Ordering::SeqCst));
static CNT: AtomicUsize = ATOMIC_USIZE_INIT;
what does thread_local! do
I got it. Thanks
qq00
@qq00
Aug 08 2018 21:09
I am trying to understad "?" in the context of error handling. Is the basic idea that (.... expr .... )? mean:
  1. .... expr .... has type Result
  2. if it is an error, we do a return immediately
  3. if it's good, we pass it through
Denis Lisov
@tanriol
Aug 08 2018 21:10
Not necessarily a Result, but in most cases so.
qq00
@qq00
Aug 08 2018 22:39
In Rust, is it more idiomatic to:
  1. throw exceptions or
  2. return Result<good_type, error_type>
Ichoran
@Ichoran
Aug 08 2018 22:47
2.
Rust doesn't have exceptions, which means all you can do is panic and kill the thread. You should only do that in case of disastrous unrecoverable unreportable failure.
Even in an exception-friendly language like Scala, you should favor a result-type for cases where an operation can be expected to fail sometime.
(And all the .unwrap() stuff makes for good examples, but mostly in robust code you should have some result type and be using ? instead.)