[rust-dev] ref binding for parameters of functions?

Alex Crichton alex at crichton.co
Wed Jul 2 09:21:24 PDT 2014


Binding by ref is subtly different that the function still owns the
argument. For example, this may go awry with "ref:T"

struct Foo;
impl Drop for Foo {
    fn drop(&mut self) { println!("dropping"); }
}

fn foo(ref _param: Foo) {}

fn main() {
    let f1: fn(ref:Foo) = foo;
    let f2: fn(Foo) = foo;
    let f3: fn(&Foo) = foo;

    f1(Foo);
    f2(Foo);
    f3(&Foo);
}

In that program, how many times is `dropping` printed? It should be
three, but I believe it will print four times due to f3 not
understanding that the value has already been dropped.

On Wed, Jul 2, 2014 at 11:49 AM, Sebastian Gesemann
<s.gesemann at gmail.com> wrote:
> So far I knew that `ref` could be used in `let` and `match`
> expressions. But I just tried using it for a function's parameter to
> see what happens and it actually compiled! :)
>
>     fn foo(ref p: int) -> int {
>         *p + 1
>     }
>
>     fn main() {
>         let x = 1729i;
>         let y = foo(x);
>         println!("{}",y);
>     }
>
> What I was wondering then was: What is the type of foo and what does
> it mean for how the parameter is passed exactly?
>
> After adding
>
>         let bar: fn(int)->int = foo;
>
> to the main function, I realized that the reference called p probably
> refers to a function-local temporary int. A part of me hoped for p
> referring to main's x thus saving a copy/move. But in that case, the
> function's type would have to be different, right?
>
> So, for a brief moment I thought that Rust already supports
> auto-referencing for non-self parameters just like C++ does for "const
> T&". The reason I'm mentioning this is that I noticed an RFC PR for a
> feature like this.
>
> So, what do you think about what kind of semantic you want for such a
> function? Should its p refer to main's x in this case? Should its type
> be fn(ref:int)->int which would be ABI-compatible with fn(&T)->int?
> Due to ABI compatibility one could even be allowed to convert one
> function pointer to another:
>
>    let f = foo; // fn(ref:int)->int with auto-referencing
>    let g = f as fn(&int)->int; // no auto-referencing anymore
>
> The parameter "type" ref:T could be useful for getting rid of some
> explicit borrows one would otherwise need at the invocation site:
>
>     fn show_vec(ref v: Vec<int>) {...}
>
>     fn main() {
>         let x = vec!(1,2,3i);
>         show_vec(x);
>     }
>
> Comments? Opinions? Maybe this could be useful. And maybe this is a
> bad idea. I don't know. What I *don't* like about it is that "ref:T"
> is not really a type and this could compose badly in generic code.
>
> Cheers!
> sg
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev


More information about the Rust-dev mailing list