These are chat archives for rust-lang/rust

2nd
Mar 2018
Karthik Ravikanti
@plumenator
Mar 02 2018 02:11
What does &* mean and why would it ever be needed?
Steve Klabnik
@steveklabnik
Mar 02 2018 02:18
derefernece then create a reference
this would make the Deref impl fire
so for example, a String, when &*, gives a &str
*String triggers Deref, String Derefs to str
& means &str
Karthik Ravikanti
@plumenator
Mar 02 2018 02:19
Ah I see. As opposed to &String?
Steve Klabnik
@steveklabnik
Mar 02 2018 02:19
yeah
Karthik Ravikanti
@plumenator
Mar 02 2018 02:19
Thanks!
Steve Klabnik
@steveklabnik
Mar 02 2018 02:19
np!
xliiv
@xliiv
Mar 02 2018 11:37

I'm looking at this and i'm wondering if

#[derive(Debug,Serialize,Deserialize)]
struct Record<'a> {
    name: &'a str,
    surname: &'a str,
    city: &'a str,
    country: &'a str,
}

couldnt be automatiacally elided to

#[derive(Debug,Serialize,Deserialize)]
struct Record {
    name: &str,
    surname: &str,
    city: &str,
    country: &str,
}

or to:

#[derive(Debug,Serialize,Deserialize)]
struct Record {
    name: str,
    surname: str,
    city: str,
    country: str,
}
i mean in future
maybe even in very long future
:)
Ingvar Stepanyan
@RReverser
Mar 02 2018 11:38
Definitely not the last one since it's a very different type
I mean str vs &str
xliiv
@xliiv
Mar 02 2018 11:39
@RReverser what's the detailed difference?
Ingvar Stepanyan
@RReverser
Mar 02 2018 11:40
That particular struct would be invalid, but something like pub struct MyStrWrapper { length: usize, data: str } is a valid DST struct even today, and has different semantics than pub struct MyStrWrapper<'a> { length: usize, data: &'a str }
Ingvar Stepanyan
@RReverser
Mar 02 2018 11:40
It's useful to think of str as a special alias for [u8]saying "this holds valid UTF-8"
So the difference between str / &str / Box<str> is pretty much the same as between [u8] / &[u8] / Box<[u8]>
as in "unsized data" / "slice to some data" / "heap-allocated data"
xliiv
@xliiv
Mar 02 2018 11:43
ok, what about eliding lifetime?
Ingvar Stepanyan
@RReverser
Mar 02 2018 11:44
That would be nice, yeah
Although maybe Rust will always prefer one to be explicit in this case
Michal 'vorner' Vaner
@vorner
Mar 02 2018 11:45
I haven't seen anybody pushing for that. And it would be counter-intuitive a bit. Because if you have fn x(a: &str, b: &str), then these lifetimes are different. What you want to say here is that they are all the same.
Ingvar Stepanyan
@RReverser
Mar 02 2018 11:45
But I also wanted it many times, similarly to functions
@vorner They're different but all have minimal lifetime of the function call
Same could apply to structs - all these references live at least as long as the struct
Michal 'vorner' Vaner
@vorner
Mar 02 2018 11:46
So if there was elision on structures, I'd be for this meaning Record<'a, 'b, 'c, 'd> { … }
Ingvar Stepanyan
@RReverser
Mar 02 2018 11:47
I'm wondering - what difference would you see on practice? All the type's lifetimes have to live at least as long as type itself anyway (that's why PhantomData thing works to force types live as long as whatever lifetime it holds).
In function case they're different to force you to choose lifetime for the return type when you have several args, but for structs this shouldn't be necessary as there is no return lifetime
Or rather there is a single one (associated with struct itself)
Michal 'vorner' Vaner
@vorner
Mar 02 2018 11:50
Well, with the struct, you can take it apart and put the parts into different structs, for example. You just don't know what anyone will do with these lifetimes. With the function, you can only call it. So, in other words, there are many more lifetime equations around.
No, you're wrong there. You can return the struct, take it apart, build other structs out of the parts, etc.
xliiv
@xliiv
Mar 02 2018 11:50
for me it's more .. "common" or it woudl be more "reasonable".. to assume that not specifying lifetimes means all lifetimes are the same... but since function elasion works like assigning all different types its done and consistency is more importnat
Michal 'vorner' Vaner
@vorner
Mar 02 2018 11:52
And, considering what everything you can do with structs, I myself prefer to see it written there explicitly. Especially if you can bundle some more structs inside, which themselves have lifetime parameters.
xliiv
@xliiv
Mar 02 2018 11:54
ok so answer is no, cool it's always nice to ask :)
Michal 'vorner' Vaner
@vorner
Mar 02 2018 11:55
Well, my answer is I don't like it. But I'm not responsible for decision ‒ if enough people prefer to have the elision, then I guess someone will just write the RFC and it'll get through.
xliiv
@xliiv
Mar 02 2018 11:58
so should i ask on irc/github/https://internals.rust-lang.org ?
or here is enough
Michal 'vorner' Vaner
@vorner
Mar 02 2018 11:59
Well, it doesn't exist now. If you want to push for it, then you can try the other places to see if it has support. Or searching there, maybe there was a discussion about that topic already.
Zakarum
@omni-viral
Mar 02 2018 12:05
I got unexpected compiller panic on nightly
https://travis-ci.org/omni-viral/xfg-rs/builds/347479876
Does anyone know what it might be?
Apparently it's regex crate
Ingvar Stepanyan
@RReverser
Mar 02 2018 12:08
I'd suggest to set allow_failures for nightly to true on Travis
Unexpected errors on nightly are not that unexpected (well, unusual) :)
I'm periodically (~every 1-2 months or so) getting some SIGSEGVs on nightly in deallocators etc.
Denis Lisov
@tanriol
Mar 02 2018 12:26
@xliiv Note that there was a change in the opposite direction in RFC 2115: today you can have Wrapper<'a> and elide the lifetime (fn wrap(s: &str) -> Wrapper), but this will be linted against in favour of explicit -> Wrapper<'_>.
xliiv
@xliiv
Mar 02 2018 12:33
@tanriol i'm not sure how these two are connected
Denis Lisov
@tanriol
Mar 02 2018 12:38
Well, there's no direct connection, but general direction... you've suggested eliding struct Record<'a> to struct Record, which may be not a good idea - it becomes much less obvious that there's any borrowing at all.
xliiv
@xliiv
Mar 02 2018 12:51
@tanriol i think & means borrowing.. and the proposition includes them
to be exact it means reference which is borrowing.. but still.. borrowing
nvm
:)
Denis Lisov
@tanriol
Mar 02 2018 12:54

Yeah, until you have

struct Wrapper<'a> {
    field: Ref<'a>,
}

where Ref contains a reference, but is not a reference itself.

Michal 'vorner' Vaner
@vorner
Mar 02 2018 12:56
Hmm. I can attest to the fact I got confused about the -> Wrapper thing and had to look into the source code of library, not only the documentation, because of that. Though having rustdoc add the lifetime there would have been enough for me at the time.
Ingvar Stepanyan
@RReverser
Mar 02 2018 14:01
@tanriol Nooooooo :(
Scott J Maddox
@scottjmaddox
Mar 02 2018 16:26
Hi everyone! I'm running into some strange behaviour in a package I'm writing, that I think might point to a compiler bug. Depending on enum member ordering, I get either perfectly working code, or a segfault. And the ordering required for working code is the opposite between macOS and windows... Is there anyone that would be willing to take a look at it?

To reproduce the segfault:

git clone https://github.com/scottjmaddox/rust-memory-arena
cd rust-memory-arena/
cargo run --example list-segfault

But running the same example with swapped enum order works just fine:

cargo run --example list
Scott J Maddox
@scottjmaddox
Mar 02 2018 16:32
I've isolated the root cause to a particular line of code (in arena.rs line 113), which implicitly (and incorrectly) calls drop_in_place, but I'm not sure how to debug the underlying compiler code, or identify a workaround.
Scott J Maddox
@scottjmaddox
Mar 02 2018 17:13
Nevermind! I figured it out! I just had to switch to using core::ptr::write() in order to get rid of the spurious drop call.
Steve Klabnik
@steveklabnik
Mar 02 2018 17:27
dont forget that enums don't have a defined ordering
so you can't rely on it
i am not sure if that specifically has to do with your problem
but, without a repr attribute, the layout of enums and structs is not defined
Scott J Maddox
@scottjmaddox
Mar 02 2018 17:35
Yeah, I'm aware of the ordering not being defined. I just happened to try swapping the field order and it fixed the segfault, which I thought was odd. I'm still not sure why the order mattered, but the root cause was really having a spurious drop call in the MIR, which I was able to get rid of by using ptr::write(p, x) instead of *p = x
Ingvar Stepanyan
@RReverser
Mar 02 2018 20:01
So when you do *p = x; it's assumed that p already holds value of type T and it has to be dropped before assigning new one
But when you do ptr::write(p, x) it simply writes your value into destination without dropping whatever is there already
So if you had uninitialised memory pointed to by that pointer before writing x, it tried to drop it and failed
Maciej Gorywoda
@makingthematrix
Mar 02 2018 20:23
but doesn't it mean that Scott uses ptr::write to write to an unallocated place?
Ingvar Stepanyan
@RReverser
Mar 02 2018 21:01
no, not necessarily
he allocates it in both cases
but if p is just allocated but not initialised to correct value of T and you use *p = ..., then it will try to read that previous value (which is actually just random junk), interpret it as T and call Drop implementations for entire hierarchy of types
which obviously might lead to very bad things