These are chat archives for rust-lang/rust

25th
Feb 2019
moondaddi
@mattdamon108
Feb 25 16:42
Hi, Rustaceans!
verilog15
@verilog15
Feb 25 19:06
image.png
Hi guys, I was trying to learn slices. I saw the following explanation, but the code on the bottom compiles for me and does not end up with an error.
The code:
fn main() {
    let mut stry = String::from("hello, world!");
    let s = &stry[0..5];
    stry.insert_str(0, "matan: ");
}
Zakarum
@omni-viral
Feb 25 19:07
Because you don't use s
Ingvar Stepanyan
@RReverser
Feb 25 19:07
your code is different though - you're not using println!
so s is unused, and mutable borrow can start earlier in modern versions of Rust
Denis Lisov
@tanriol
Feb 25 19:08

This explanation is slightly outdated. If you add to the bottom one line

println!("{}", s);

you should see the error.

verilog15
@verilog15
Feb 25 19:09
Oh I see now. What have changed?
Ingvar Stepanyan
@RReverser
Feb 25 19:10
Rust got support for non-lexical lifetimes - basically, a feature that allows it to be less restrictive in regards to borrowing.
verilog15
@verilog15
Feb 25 19:11
Can you please point to me when was it added and where I can read about it? I'll PM the author to update the slides.
Ingvar Stepanyan
@RReverser
Feb 25 19:12
The slide looks correct
If you check the error message, it points to the full code which does have println! in the end
verilog15
@verilog15
Feb 25 19:13
It misses the "print" part no? before supporting non-lexical lifetimes it failed at that line.
Ingvar Stepanyan
@RReverser
Feb 25 19:13
No, see above - it's there in the end
verilog15
@verilog15
Feb 25 19:14
Oh right, my mistake. So why does it work? I'd expect it to fail on the insert_str line. What are the benefits of the non-lexical lifetimes?
Ingvar Stepanyan
@RReverser
Feb 25 19:15

So why does it work?

Do you mean in your example without println!? Because s is not used anymore.

Before non-lexical lifetimes were implemented, it would still fail because s is still in scope, but nowadays Rust is smarter and actually checks if you're still using the value.
But, either way, full code on the slide should error both in old and new versions as expected.
verilog15
@verilog15
Feb 25 19:17
Isn't it passes over the ownership rules?
Ingvar Stepanyan
@RReverser
Feb 25 19:17
No, why?
Zakarum
@omni-viral
Feb 25 19:18
non-lexical lifetimes allow rustc to figure out lifetimes not tied to scopes
verilog15
@verilog15
Feb 25 19:18
I'm just wondering what the benefits of not failed on the insert_str (without talking about the slide).
Zakarum
@omni-viral
Feb 25 19:19
Imagine you want to read from collection and then write to
let a = collection.read();
collection.write(data);
this will fail without NLL because a borrows collection
Ingvar Stepanyan
@RReverser
Feb 25 19:19
In this particular example - not much, but there are plenty of other cases that were annoying in Rust before.
verilog15
@verilog15
Feb 25 19:27
@omni-viral I think I'm getting it. Is it possible to expend the example?
Sam Johnson
@sam0x17
Feb 25 21:25
I'm a little stuck adding this lifetime parameter -- it's saying it expects a ":" where the mut is:
    pub fn new() -> Stream {
        Stream {
            targets: Vec::new(),
            limit_handler: & 'static mut DummyLimitHandler::new()
        }
    }
}
I'm trying to initialize limit_handler to be a mutable reference to a new DummyLimitHandler
Denis Lisov
@tanriol
Feb 25 21:29
IIUC, you can have a lifetime in a reference type, but not when actually taking the reference.
What does DummyLimitHandler::new() return?
Sam Johnson
@sam0x17
Feb 25 21:30
impl DummyLimitHandler {
    pub fn new() -> DummyLimitHandler { DummyLimitHandler{} }
}
Denis Lisov
@tanriol
Feb 25 21:30
If it returns a DummyLimitHandler, you cannot just take a 'static reference to it without thinking about who owns the handler itself.
Sam Johnson
@sam0x17
Feb 25 21:30
I didn't even want lifetime parameters I've just been following compile error messages to try to get this to compile XD
Denis Lisov
@tanriol
Feb 25 21:31
Why is the limit_handler a reference and not a DummyLimitHandler?
Sam Johnson
@sam0x17
Feb 25 21:31
because limit_handler is of type LimitHandler which is a trait
and its size cannot be known at compile time
and DummyLimitHandler is just a blank struct that implements the trait so I can have a default value and not have to deal with Some() crap
Denis Lisov
@tanriol
Feb 25 21:32
Ok, then why not Box<dyn LimitHandler>?
Sam Johnson
@sam0x17
Feb 25 21:33
that's probably what I want then
what is the difference?
I've never understood the difference between Box and regular references
is it a heap / stack thing?
Denis Lisov
@tanriol
Feb 25 21:34
A Box owns the value (i.e. it's responsible for freeing it when the Box is gone). Regular references don't own their values, they just borrow them.
Sam Johnson
@sam0x17
Feb 25 21:35
ok, that helps a bit I think
thanks
Denis Lisov
@tanriol
Feb 25 21:35
The contents of the Box always live in the heap, while references are not limited to heap.
Sam Johnson
@sam0x17
Feb 25 21:37
how do I initialize the box?
Ichoran
@Ichoran
Feb 25 21:43
Box::new?
Sam Johnson
@sam0x17
Feb 25 21:44
yeah I'm stupid thanks
I kept trying to give it a type parameter
Ichoran
@Ichoran
Feb 25 21:45
It'll figure it out based on whatever you put into it.
Sam Johnson
@sam0x17
Feb 25 21:45
yup, thanks guys IT COMPILES!!!!!! <3
when I call Vec::new() is that automatically boxed?
Brian Knapp
@knappador
Feb 25 22:20
No