Pre-RFC: Disallow using assignment in a function call in Rust 2018 (disallow `f(a=b)`)

I’d like to see Struct { a: b = c } disallowed too, for the same reason; the current struct assigment is a wart.

Meh. That looks less nice exactly for the reason this does: it’s more noisy.

I wrote that in my (now edited) first post as well. However, I don’t think that there is a conflict.

Disallowing it probably won’t hurt, though.

More noisy? You mean you’re not used to it. It’s not noisy by any definition.

1 Like

I am used to it, I’ve been programming in C for 9 years, and C has the same syntax (except that it also requires a leading . before field names). I’m still glad Rust didn’t make that choice.

1 Like

I’ve been working with JavaScript for just as long. It uses the : as well. This doesn’t mean that it makes sense though. It’s an assignment.

In any case, you’re right with one thing: Struct construction and the syntax for named params (if we ever get them) should use the same notation. Be it : or =.

1 Like

You can look at it as an assignment. But you can also look at it as a name-value pair (which it is), and in that case it makes perfect sense. Spelling both as : also has the additional advantage of requiring one less breaking change.

This has been presented as one of the alternatives, though the conflict with type ascription is quite unfortunate.


I don't see how disallowing Struct { a: b = c } is related to enabling Struct { a = c }. The latter is already invalid syntax today AFAIK.

1 Like

MyStruct { a: 7 } could just be deprecated very gently (no breaking change) and rustfix could update existing code very quickly to MyStruct { a = 7 }. It'd make usage of type ascription (e.g. MyStruct { a = 7: u64 } in struct construction possible. Not bad if you ask me. (Edit: Although it's probably worthless because the struct is already typed :D)

That said, this RFC has minimal impact and it keeps the door open for both ways. Whatever the choice I'd prefer consistency between these two notations.

1 Like

I wasn’t even aware this was possible and can’t really see any use for it so I would support disallowing it, as well as in struct if it’s currently allowed. I doubt that anyone is using that “feature” on purpose?!

1 Like

@Keats a = b is an expression like any other. That’s why you can use it in situations like

match expr {
    pat => a = b,
}

It’s just that, since it has type (), it’s not a very useful expression. Banning it in certain situations would complicate Rust’s syntax though, it could break macros for instance.

This makes me wonder whether a = b should be an expression at all. Maybe match arms like that should require a block to be written:

match expr {
    pat => { a = b; },
}

Alternatively, make match the special case and have an extra syntax rule for => a = b (are there any other places where assignment-as-an-expression is useful?).

Edit: Also +1 to changing the struct expression syntax to MyStruct { x = y } in the new edition.

6 Likes

The = for struct construction seems very interesting. I’ll create a new thread for this.

1 Like

Changing the type ascription syntax feels like a bad type of judgement :wink:

Personally I hope we don't; but I have nothing against future proofing :+1:

If y'all want to change the struct initialization syntax to field = expr or at least not allow field: value and field: binding, then you need to at minimum crater run this to see the extent of the breakage. My hunch is that the breakage extent makes it wildly undoable. I think nearly every crate would be broken by this change or start emitting warnings (depending on strategy).

2 Likes

Note: I’ve added one more rule for disallowing

macro_rules! splat { ($($x:tt)*) => { foo($($x)*) } }
splat!(x = 3); // disallowed

I've created the tread for = in struct construction

I think I like this one best, since it feels like it'd have fewer edge cases (I have no idea what tokens vs not tokens are supposed to mean for macros here, for example), and one can easily turn the a = b statement into an expression as { a = b }.

3 Likes

I guess this can’t hurt, but I think named arguments will end up requiring a separator (sigil or keyword) such as foo(x ; a = a) so that we can use the sugar foo(x ; a) without being confusing. Though foo(; a) is a bit ugly. We also need a separator to support patterns such as foo(; Pat(a) = a).

Usage of “=” for struct construction will likely not happen. With that in mind, reserving = for usage in named parameters in function calls doesn’t make a lot of sense. For consistence within Rust, the syntax foo(name: arg) would be the more logical syntax choice for named params (like Swift).

4 Likes

We already supported named params in println!("{a}", a = value);, so I consider = at least consistent if it were chosen.

2 Likes

It is not really a "named param" per say. This syntax is specific to the println! macro. You could write the same macro using any other token.

4 Likes