These are chat archives for rust-lang/rust

5th
Mar 2018
Daniel Bischof
@dbischof90
Mar 05 2018 10:18
note: arm-openwrt-linux-muslgnueabi-g++.bin: fatal error: -fuse-linker-plugin, but liblto_plugin.so not found
During cross-compilation. Any ideas? :worried:
Denis Lisov
@tanriol
Mar 05 2018 12:02
Disable LTO?
Daniel Bischof
@dbischof90
Mar 05 2018 12:06
That did the trick 😊
kristopher tate
@kristate
Mar 05 2018 12:56

hey, is there a good way (any way) to use a generic type/trait inside of an enum? For example, only accept structs that implement the Hash trait.

pub enum MyEnum {
  HashableState(std::hash::Hash),
}

I am getting

the trait bound `std::hash::Hash + 'static: std::marker::Sized` is not satisfied

to which, I have tried various work arounds and it would be great to know if anyone has done anything of this sort.

Aleksey Kladov
@matklad
Mar 05 2018 12:57
@kristate you probably want enum MyEnum<H: ::std::hash::Hash> { HashableState(H), }
kristopher tate
@kristate
Mar 05 2018 13:00
@matklad Thanks, yeah -- I want H to be generic, that is not to define MyEnum<HashableStruct>, but instead use MyEnum::HashableState(HashableStruct) -- is this possible?
Aleksey Kladov
@matklad
Mar 05 2018 13:01
@kristate not sure I understand :( Could you crate a small example at https://play.rust-lang.org/, which shows what are you trying to achieve?
kristopher tate
@kristate
Mar 05 2018 13:02
The use would be something like:
pub enum MyEnum {
  HashableState(std::hash::Hash),
}
MyEnum::HashableState(HashableStruct)
@matklad Thanks, I will write-up a small example
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash};

#[derive(Hash)]
pub struct HashableStruct {
    answer: u32,
}

pub enum MyEnum {
  HashableState(Hash),
}

fn main() {
  let hashable_obj = HashableStruct{answer: 42};
  let item = MyEnum::HashableState( hashable_obj );

  match item {
    MyEnum::HashableState(hashable) => {
        let mut s = DefaultHasher::new();
        hashable.hash(&mut s);
        println!("{:?}", s.finish());
    }
  }
}
kristopher tate
@kristate
Mar 05 2018 13:13
@matklad Thanks, so I am passing around the MyEnum, so let me update the playground
Denis Lisov
@tanriol
Mar 05 2018 13:14
@kristate Do you need it to work for any hasher or for some particular one?
kristopher tate
@kristate
Mar 05 2018 13:17
@tanriol Yes, any hasher (thanks)
@matklad updated the playground here:
https://play.rust-lang.org/?gist=a3041f8f33d313cc82fbfa0df5021421&version=stable
Denis Lisov
@tanriol
Mar 05 2018 13:22
@kristate Ok, let's ask the other way: would it be ok if it worked with a custom trait that hashes with DefaultHasher only? Alternatively, do you expect this to be a performance critical part of your software?
kristopher tate
@kristate
Mar 05 2018 13:24
@tanriol Thanks, yes performance critical: will sit inside of a network event loop.
Could possibly be okay to tie the type to DefaultHasher or another custom trait
Aleksey Kladov
@matklad
Mar 05 2018 13:26
@kristate would it be possible to modify usage like this: https://play.rust-lang.org/?gist=61367a58a10b59651ad05d72eab9bbfa&version=stable?
Denis Lisov
@tanriol
Mar 05 2018 13:28
One option could be like this
kristopher tate
@kristate
Mar 05 2018 13:28
@matklad Yes, but it seems very unergonomic
@tanriol Yeah, this seems more like it.. hmmmm
Denis Lisov
@tanriol
Mar 05 2018 13:29
However, it can be slower due to heap allocation and I'm not sure whether that matters.
kristopher tate
@kristate
Mar 05 2018 13:32
Big thanks to both @matklad and @tanriol -- I got two ways to do the same thing and a little insight, as well.
That said, @matklad 's code seems very unergonomic (not @matklad 's fault :) )
Aleksey Kladov
@matklad
Mar 05 2018 13:35
@kristate yeah, if you make something generic, than all the users of this something need to be aware of it. Dynamic dispatch is an alternative, but it's also not always ergonomic, and has run-time costs.
kristopher tate
@kristate
Mar 05 2018 13:36
@matklad Yes, the Boxes aren't so hot, either...
kristopher tate
@kristate
Mar 05 2018 13:42
@matklad @tanriol I wonder if there would be any want to create a new type out of MyEnum<H> where H: Hash ?
Sort of like a type alias
David McGillicuddy
@djmcgill
Mar 05 2018 14:11

Hi I'm having a little trouble with calling a function of type:

fn use_migrations<T: AsRef<[Box<Migratable>]>>(&mut self, migrations: T) -> Result<&mut Self>

Specifically I'm trying to put that into a static variable so that I can access it from unit tests (I have no problem specifying it inline).
I've tried (where EmbeddedMigration implements Migratable)

lazy_static! {
    static ref MIGRATIONS: Vec<Box<Migratable>> = vec![
            EmbeddedMigration::with_tag("001-baseline")
             .up(include_str!("sql/migrations/001_baseline.sql")).boxed(),

But that gives

error[E0277]: the trait bound `migrant_lib::Migratable + 'static: std::marker::Sync` is not satisfied

Which I think is because things in lazy statics need to be sync? So I tried the more concrete

static ref MIGRATIONS: [EmbeddedMigration; 2]

But had trouble converting that into a form that AsRef would take. What would be the best way to set up my static so I can put it into this function?

David McGillicuddy
@djmcgill
Mar 05 2018 14:31
In the end I got it working with
lazy_static! {
    static ref MIGRATIONS: [EmbeddedMigration; 1] = [...];}

fn foo() {
        let migrations: Vec<Box<Migratable>> =
            (&MIGRATIONS).iter().map(|c: &EmbeddedMigration| Box::new(c.clone()) as Box<Migratable>).collect::<Vec<Box<Migratable>>>();
        bar.use_migrations(
            migrations
        )?;
}
Is there a better way?
David McGillicuddy
@djmcgill
Mar 05 2018 14:36
Seems odd to methat it's AsRef<[Box<Migratable>]>> - would AsRef<[&Migratable]> work?
David McGillicuddy
@djmcgill
Mar 05 2018 14:50
As soon as I try to have the static trait object I get
   = help: the trait `std::marker::Sync` is not implemented for `migrant_lib::Migratable + 'static`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<migrant_lib::Migratable + 'static>`
   = note: required because it appears within the type `std::boxed::Box<migrant_lib::Migratable + 'static>`
Casey Allred
@sbditto85
Mar 05 2018 15:10
is there an easy way to convert a futures::AndThen to a futures::FutureResult? (i'm a newb)
Denis Lisov
@tanriol
Mar 05 2018 15:11
@sbditto85 In general, no. By the way, https://gitter.im/tokio-rs/tokio may be a better place to ask :-)
Casey Allred
@sbditto85
Mar 05 2018 15:13
oh! thanks
Dylan DPC
@Dylan-DPC
Mar 05 2018 15:32
@sbditto85 or you can ask on the users forum
Casey Allred
@sbditto85
Mar 05 2018 15:35
awesome thanks
Dylan DPC
@Dylan-DPC
Mar 05 2018 15:56
gitter channel will be my first option though
Ryan Levick
@rylev
Mar 05 2018 17:02
Hello. Can I use an external crate only in tests that are in the same file as my lib code?
Denis Lisov
@tanriol
Mar 05 2018 17:04
Sure you can, what's the problem? :-)
Ryan Levick
@rylev
Mar 05 2018 17:05
@tanriol I can't seem to get it to work. I need to include extern crate EXTERN_CRATE_NAME at the top level of my crate, but I don't want it to be included unless tests are run
can I use #[cfg(test)] somehow?
ousado
@ousado
Mar 05 2018 17:07
yes, you can open a module inside a file
Ryan Levick
@rylev
Mar 05 2018 17:08
I ended up doing:
#[cfg(test)]
#[macro_use]
extern crate CRATE_NAME;
ousado
@ousado
Mar 05 2018 17:08
#[cfg(test)] mod tests { ... }
Ryan Levick
@rylev
Mar 05 2018 17:09
@ousado I'm asking about using an external crate inside of my tests. I already have a test module like that
Denis Lisov
@tanriol
Mar 05 2018 17:13
@rylev You can put the extern crate in the test module, but it will be slightly inconvenient to work with it.
Ryan Levick
@rylev
Mar 05 2018 17:13
How? I get an error when I try that
Denis Lisov
@tanriol
Mar 05 2018 17:20
Something like this. There are some exceptions, mostly related to custom derives.
Roman Proskuryakov
@kpp
Mar 05 2018 17:37
If there are more then 1 test mod, you may want to
#[cfg(test)]
extern crate serde_json;
Ryan Levick
@rylev
Mar 05 2018 17:37
Yea that's what I ended up doing
Maciej Gorywoda
@makingthematrix
Mar 05 2018 19:44
Hi. A quick question. I know that type aliases are only that, aliases, but is there a macro, or another way, to check in the compile time if I don't use one alias instead of the other?
ousado
@ousado
Mar 05 2018 20:04
@makingthematrix do you want to prevent unification?
Maciej Gorywoda
@makingthematrix
Mar 05 2018 20:09
@ousado I have some identifiers, all of them usize, but some of them are used by one type of data, and others by another type. I want to avoid the possibility to ask for a data structure using an identifier of the wrong type.
Denis Lisov
@tanriol
Mar 05 2018 20:12
Use newtypes instead of aliases
ousado
@ousado
Mar 05 2018 20:13
Maciej Gorywoda
@makingthematrix
Mar 05 2018 20:21
I use newtypes elsewhere, but in this case I'd prefer them to stay usizes. Much less boilerplate needed.
is it not possible to, let's say, get the type alias' name as a string in a macro? so then I can check if the integer I'm dealing with is provided as the given type alias? And then it's compiled away? :)
ousado
@ousado
Mar 05 2018 20:25
declarative macros run too early for that, I think
Maciej Gorywoda
@makingthematrix
Mar 05 2018 20:37
I've found something, but sadly it works only if types have different memory sizes, so not in my case ;)
struct Foo { … }
const SIZE_OF_FOO: usize = 32;
fn _static_assert() { std::mem::transmute::<Foo, [u8; SIZE_OF_FOO]>(panic!()) }
Denis Lisov
@tanriol
Mar 05 2018 20:38
@makingthematrix What kind of boilerplate do you mean?
ousado
@ousado
Mar 05 2018 20:40
@makingthematrix https://docs.rs/newtype_derive/0.1.6/newtype_derive/ <-- looks like you might want that
Maciej Gorywoda
@makingthematrix
Mar 05 2018 20:45
Guys, I really don't want newtypes here :) This one idea of checking compatibility is not enough to go away from simple usize.
Maciej Gorywoda
@makingthematrix
Mar 05 2018 20:52
@tanriol Later on I use these identifiers in set operations. I have functions which rely on that these ids are integers, so certain operations may be optimized. With newtypes, I would have to keep derefencing them, or implement traits which would tell these functions that they can be really treated as integers, etc. Generally, it's all possible, and maybe I will refactor it to use newtypes at some point, but in the moment it seems unnecessary.
I would only want to have compiler errors where the type aliases are mixed up, that's all.
but thanks for the link to newtype_derive, @ousado. It will help me :)
Tropic
@TropicSapling
Mar 05 2018 21:24
Is there any way to extend a lifetime beyond a scope?
Like if I define a variable inside of a function, is there any way to make it live outside the function as well or do I have to create it outside the function?
fn function() -> T {
   let x = ...;
   &x // x doesn't live long enough for this to work
}

let y = function();
Tropic
@TropicSapling
Mar 05 2018 21:29
Is there any other way to make it work other than doing this?:
fn function(x: &T) {
   ...
}

let x = ...;
function(&x);
This message was deleted
Tropic
@TropicSapling
Mar 05 2018 21:34
This message was deleted
Ingvar Stepanyan
@RReverser
Mar 05 2018 23:38
you have to create it outside of function
the reason lifetimes are tied to scopes is that they are pretty close to scopes. that let x inside of your function is indeed holding data inside of function's temporary area of stack, so you can't just return a reference to it outside, because as soon as you return from function, that area is dead
(one could follow this with "well actually" but I'd rather not go into details :) )
easier to think of that area as really allocated just for the lifetime of function call