These are chat archives for rust-lang/rust

4th
Feb 2018
Matt
@someguynamedmatt
Feb 04 2018 00:11
Is it possible to pull via the rust git2 library? I don't see anything about pulling explicitly in the docs.
Joseph Musser
@jnm2
Feb 04 2018 04:41
Is there a way to pass a closure as a function pointer (https://docs.rs/winapi/*/x86_64-pc-windows-msvc/winapi/um/winuser/type.WNDPROC.html)?
Joseph Musser
@jnm2
Feb 04 2018 04:42
let window_proc = |hwnd, msg, wParam, lParam| {
    // My own stuff

    DefWindowProcW(hwnd, msg, wParam, lParam)
};

let class = WNDCLASSW {
    style: CS_HREDRAW | CS_VREDRAW,
    lpfnWndProc: Some(window_proc),

Gives:

expected unsafe fn, found normal fn
note: expected type unsafe extern "system" fn(*mut winapi::shared::windef::HWND__, u32, usize, isize) -> isize
found type [closure@src\main.rs:33:31: 35:14]

@kinggoesgaming Thanks! Fixed.
What I really want to do is use a struct method as the wndproc, but I am in the process of figuring out how.
Seems a closure is the only way to capture the struct's &self? I just need to end up with something I can pass as a WNDPROC function pointer.
Joseph Musser
@jnm2
Feb 04 2018 04:48
I'm used to C# where I can create a delegate to an object's instance method and marshal the delegate as a function pointer. So maybe I'm not thinking of it the Rust way?
Hmm, looks like there really is no way to do this. https://stackoverflow.com/a/44743241
Joseph Musser
@jnm2
Feb 04 2018 04:57
What's the idiomatic Rust way to layer user-defined WndProc handling (such as drawing code) on top of default WndProc handling (such as setting the cursor on WM_MOUSEMOVE or calling DefWindowProc)?
Joseph Musser
@jnm2
Feb 04 2018 05:22
At this point, I don't even know how to make a WNDPROC (function pointer) that responds to WM_MOUSEMOVE by setting a cursor chosen at runtime.
Joseph Musser
@jnm2
Feb 04 2018 05:34
https://aatch.github.io/blog/2015/01/17/unboxed-closures-and-ffi-callbacks/ - I suppose I could store the user data pointer as custom window data via SetWindowLongPtr.
Still to me it seems very weird that Rust can't generate new function pointers on the fly which are attached to certain closures. Can someone help me understand why this lack makes sense?
Restioson
@Restioson
Feb 04 2018 08:28
You could probably cast Fn.call or whatever its called to an extern "rust-call" func pointet
It's better style to take a closure than a fn pointer
Closures capture their environment so it's more complex
Be aware that you can defyine inline functions too
Christopher Andronikos
@candronikos
Feb 04 2018 08:45

Hi All,

I'm having an issue with supertraits and a the trait cannot use ``Self`` as a type parameter in the supertraits or where-clauses error

I believe it's related to object safety but it stops be from doing this: pub trait HVal: PartialEq on a HashTrieMap

I don't understand this fully but I get an error when trying to create a container of objects with that trait:
error[E0038]: the trait `obj::h_val::HVal` cannot be made into an object
  --> lib/obj/h_dict.rs:21:41
   |
21 | pub struct HDict(HashTrieMap<String, Box<HVal>>);
   |                                         ^^^^ the trait `obj::h_val::HVal` cannot be made into an object
   |
   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
Denis Lisov
@tanriol
Feb 04 2018 08:54
@candronikos Please show your trait
Christopher Andronikos
@candronikos
Feb 04 2018 08:57
//#![feature(get_type_id)]

use std::fmt::Debug;
use std::any::{Any,TypeId};

//pub trait HVal: Any + Sync + Send + Debug + PartialEq {
pub trait HVal: Any + Debug + PartialEq {
    fn to_zinc(&self) -> String;

    fn to_string(&self) -> String {
        self.to_zinc()
    }

    /*
    fn get_type_id(&self) -> TypeId; {
        TypeId::of::<Self>()
    }
    */
}
I get further when I don't include PartialEq in the supertrait list but the equality test will fail
Also yes, I've tried implementing PartialEq for HDict too. But it won't compile unless the trait HVal has PartialEq for it. Catch 22s are always fun :)
Denis Lisov
@tanriol
Feb 04 2018 09:06
Yeah, you can't do this. The problem is that the PartialEq impl for every type you implement HVal for is actually PartialEq<Rhs=Self>, and there are no impls to compare values of different types that have HVal implemented for them.
Christopher Andronikos
@candronikos
Feb 04 2018 09:07
Is there a work around for this? And what do I have to read to fully understand PartialEq<Rhs=Self>? Specifically, the syntax of <Rhs=Self> is confusing
Denis Lisov
@tanriol
Feb 04 2018 09:09
I'd first ask myself whether an enum would go :-)
Christopher Andronikos
@candronikos
Feb 04 2018 09:10
What if I wanted to allow for calling libraries to implement custom types?
I moved away from enums for that reason
Christopher Andronikos
@candronikos
Feb 04 2018 09:16
I'll add that my plan was to compare the TypeId of each type and then compare the data itself so I believe it's possible in theory, but getting the compiler to agree with me is the tricky bit!
Denis Lisov
@tanriol
Feb 04 2018 09:17
Syntax: PartialEq is actually implemented not for a type, but for a pair of types -- "how to compare Type to Rhs". Usually Rhs=Self, which means "how to compare with itself", but that's not required.
Christopher Andronikos
@candronikos
Feb 04 2018 09:19
Could I implement PartialEq for a trait as opposed to a type?
Or are you making no distinction between the two here?
red75prime
@red75prime
Feb 04 2018 09:22
You can implement it for trait-object. impl PartialEq for HVal means implementaion of PartialEq for trait-object HVal.
Denis Lisov
@tanriol
Feb 04 2018 09:24
...the question would be how to implement it :-)
red75prime
@red75prime
Feb 04 2018 09:33
Christopher Andronikos
@candronikos
Feb 04 2018 10:09

Thank you all for your feedback! Just saw your suggestion @red75prime and I'm going through it now.

Here's what I did:

use std::fmt::Debug;
use std::any::{Any,TypeId};

//pub trait HVal: Any + Sync + Send + Debug + PartialEq {
pub trait HVal: Any + Debug {
    fn to_zinc(&self) -> String;

    fn to_string(&self) -> String {
        self.to_zinc()
    }

    fn _get_type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

impl Eq for HVal {}

impl PartialEq for HVal {
    fn eq(&self, other: &Self) -> bool {
        match self._get_type_id() == other._get_type_id() {
            true => self == other,
            false => false
        }
    }
}

And I implemented PartialEq separately for HDict

I am now getting signal: 11, SIGSEGV: invalid memory reference but I believe that is a separate issue
red75prime
@red75prime
Feb 04 2018 10:12
You don't really need TypeId there. as_any() -> &Any will do better
@candronikos true => self == other,will recurse infinitely, I think. Is there a compiler warning?
red75prime
@red75prime
Feb 04 2018 10:19
tr_eq in my code should be right_hand_trait_object_eq, but that's a bit long
Christopher Andronikos
@candronikos
Feb 04 2018 10:21
Funnily enough I don't see a compiler warning
I thought it might too but tried it anyway
But it may be that a lack of warning here is a bug
Denis Lisov
@tanriol
Feb 04 2018 10:24
Why exactly should there be a warning? Do you expect the compiler to look deep inside and understand that the match will always be true as nothing changes?
Christopher Andronikos
@candronikos
Feb 04 2018 10:25
I would expect a warning if there is an infinite recursion at least?
red75prime
@red75prime
Feb 04 2018 10:27
I've got compiler warnings in similar situations, but I cannot remember the details of code.
Denis Lisov
@tanriol
Feb 04 2018 10:29
The question probably is whether the recursion is obviously infinite... looks like in this case this is not obvious to the compiler.
Christopher Andronikos
@candronikos
Feb 04 2018 10:30
Maybe it isn't. Do you think what could explain the signal: 11, SIGSEGV: invalid memory reference error I mentioned earlier?
Denis Lisov
@tanriol
Feb 04 2018 10:32
Maybe it's the stack overflow, although it feels to me there was a special error message for stack overflow...
Christopher Andronikos
@candronikos
Feb 04 2018 10:32
Not sure what you mean?
Ah right, I thought you were referring me to stackoverflow.com and I was searching for questions related to this
Michal 'vorner' Vaner
@vorner
Feb 04 2018 12:31
I don't know about which exact version of rustc, but I'm sure I've seen a stack overflow to lead to SIGSEGV. Rust places an empty page just at the end of the stack and forbids writes and reads from it. If anything tries to access it, it segfaults ‒ which looks scary, but is quite well defined crash (unless you do something stupid, like register your own segfault handler or decide to ignore the signal).
David Harvey-Macaulay
@alteous
Feb 04 2018 15:54
Although this compiles and works as intended, is there any chance this could be undefined behaviour? Playground link.
macro_rules! offset_of {
    ($ty:ident::$field:ident) => {
        {
            let zero = 0 as *const $ty;
            let offset = unsafe { &(*zero).$field as *const _ };
            offset as usize
        }
    };
}

#[repr(C)]
struct Foo {
    bar: i8,
    baz: [i32; 5],
    qux: i64,
}

fn main() {
    println!("bar: {}", offset_of!(Foo::bar));
    println!("baz: {}", offset_of!(Foo::baz));
    println!("qux: {}", offset_of!(Foo::qux));
}
Kelly Thomas Kline
@kellytk
Feb 04 2018 23:18
What is the correct means of identifying the full path to the currently running program? The first arg of std::env::args doesn't provide it
poilynx
@poilynx
Feb 04 2018 23:34
can i send