[rust-dev] Why doesn't rust require "mut" param prefix at call site?

Palmer Cox palmercox at gmail.com
Wed Jan 1 21:13:55 PST 2014


I could be pretty wrong, so if I am, I apologize and please ignore. Anyway,
I thought I once read somewhere that when you call a function defined like:

fn foo(a: &mut int) { ... }

with code that looks like

fn bar(b: &mut int) {
    foo(b);
}

that despite what it looks like, you aren't really passing the value b into
the function foo(). My understanding, is that when you pass a reference to
foo(), that it takes ownership of that reference making it inaccessible to
any following code. Since this is generally not what anyone wants, Rust
silently re-borrows b and passes that re-borrowed version of the reference
to foo() which takes ownership of it. Since b wasn't actually passed to
foo(), code after the call to foo() can continue to use b since bar() still
owns b.

Anyway, if that is all correct, and I'm not sure how likely that is all to
be correct, it feels like what this email thread really boils down to is a
proposal to eliminate automatic re-borrowing of a &mut to &mut when
invoking a function. I'm may be wrong, but, I'm also under the impression
that manually re-borrowing would look something like:

foo(&mut (*b))

which is extremely unpleasant, so, I'd imagine that the 2nd part of the
proposal is to make some sort of nicer syntax for that.

To me, this doesn't sound as much like a proposal for a change in syntax as
a proposal to remove a bit of magic that Rust is currently doing. I don't
know that I'm necessarily in favor or that though, since it would certainly
make code more wordy. That wordiness might be nice, however, if it makes it
clearer where variables might be mutated (eg: imagine that foo() is
originally defined to take a & ,so bar() assumed that the variable won't be
mutated. However foo() is later redefined to take a &mut which silently
breaks bar()'s assumption about foo()).

-Palmer Cox





On Wed, Jan 1, 2014 at 11:41 PM, Vadim <vadimcn at gmail.com> wrote:

> I think the real answer is "at this point nobody wants to tweak basic Rust
> syntax yet again".   See the other thread about Rust roadmap, etc.  Oh
> well...
>
>
> On Wed, Jan 1, 2014 at 3:49 PM, Martin Olsson <martin at minimum.se> wrote:
>
>> Short version of my question:
>>
>> Why doesn't rust require "mut" param prefix at call sites? i.e. to avoid
>> "non-const ref badness" that C++ has?
>>
>>
>>
>> Longer version of my question:
>>
>> Since this question was asked recently by vadim and not really answered
>> clearly (imo), I'm also including this longer verbose version of my
>> question.
>>
>> For example in C the call "f(a,&b);" might modify "b" but not "a" so the
>> "&" token acts as a "call site heads-up flag" when reading the code. In C#
>> the "out/ref" keywords are mandatory at the call site if the callee uses
>> them in its param declaration so there you also get a little in hint when
>> reading the code near the call site. C++ of course has non-const references
>> so "f(a,&b);" might modify both "a" and "b" so the hint is missing and I
>> really have to look up the code for "f()" to be sure. If some function
>> foo() passes "a" to a bunch of functions then I have to find each such
>> function and check if "a" can be modified or not, so potentially I have to
>> open a bunch of files and read code there before I can fully understand the
>> code near the call sites.
>>
>> Because of this many large C++ projects have coding styles that disallow
>> non-const refs. See for example the google C++ coding style guide:
>> http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=
>> Reference_Arguments#Reference_Arguments
>>
>> Right now, it seems that rust works similar to C++ in this regard,
>> meaning that there is no hint at the call site that a parameter may or may
>> not be modified by the function.
>>
>> In the snippet below, if I'm reading foo() in main.rs and I wonder which
>> lines in foo() could possibly change the value of "i", then I have to open
>> up 4 additional files and find the relevant source locations to double
>> check which functions might mutate their arguments.
>>
>> Why isn't it a good idea to require some parameter prefix like "mut" at
>> the call site so that when I read main.rs I immediately will know which
>> lines among the calls to funcA()..funcD() that might change the value of
>> "i" ?
>>
>>
>> // ---[ funcA.rs ]-----------------------
>> fn funcA(i: &int) -> int{
>>     return 2**i;
>> }
>> // ---[ funcB.rs ]-----------------------
>> fn funcB(i: &mut int) -> int {
>>     *i += 1;
>>     return 0;
>> }
>> // ---[ funcC.rs ]-----------------------
>> fn funcC(i: &int) -> int {
>>     return 3**i;
>> }
>> // ---[ funcD.rs ]-----------------------
>> fn funcD(i: &int) -> int{
>>     return 2**i;
>> }
>> // ---[ main.rs ]-----------------------
>> fn foo(i: &mut int) {
>>     *i += 1;
>>     funcA(i);
>>     funcB(i); // no mut!
>>     funcC(i);
>>     funcD(i);
>> }
>> fn main() {
>>     let mut i: int = 0;
>>     foo(&mut i);
>>     println!("{}", i);
>> }
>>
>>
>>
>>                 Martin
>> _______________________________________________
>> Rust-dev mailing list
>> Rust-dev at mozilla.org
>> https://mail.mozilla.org/listinfo/rust-dev
>>
>
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140102/5f3c7026/attachment-0001.html>


More information about the Rust-dev mailing list