cairo
cairo copied to clipboard
bug: cannot assign mut tuple
Bug Report
Cairo version:
eaf16c6eb
Current behavior:
Trying to assign the result of a function call to a tuple of mut
variables results in a compilation error.
fn mul2(v1: u64, v2: u64) -> (u64, u64) {
(v1 * 2, v2 * 2)
}
fn main() {
let mut v1 = 10;
let mut v2 = 20;
(v1, v2) = mul2(v1, v2);
}
Compiling this throws
error: Invalid left-hand side of assignment.
--> no_tuple.cairo:8:5
(v1, v2) = mul2(v1, v2);
^******^
Error: Compilation failed.
Expected behavior:
It should be possible to assign to a tuple of mutable variables. In the example above, the new values for v1
and v2
should be 20 and 40.
The assignment works with let (v1, v2) = mul2(v1, v2);
but that's not the intended behaviour and can lead to subtle bugs. Assigning to a single mutable variable also works (if mul2
would return only a single value, v1 = mul2(v1);
is fine), so this would just be an extension of the functionality onto tuples.
You can do let (u1, u2) = mul(v1, v2); u1=v1; u2=v2;
.
I'm not sure I'm in favor of your proposed syntax. For one, it's not supported in rust:)
If we would support something liek this, it wouldn't be just for tuples though, but for general pattern. Probably more like
let (assign v1, assign v2) = mul(v1, v2)
or something equivalent.
Why is it different with tuples then? If I have only a single mut variable, all is fine:
fn mul2(v1: u64) -> u64 {
v1 * 2
}
fn main() {
let mut v1 = 10;
v1 = mul2(v1);
}
It's not different with tuples. you can still do
let mut x = (1,2);
x = foo();
tuple type is the same as other stuff. The request here was to introduce some kind of tuple unpacking into existing variables.
Concrete suggestion: Add another pattern kind, Assignment expr.
Suggested syntax: -> x
It can be used wherever a pattern can be used (let and match arms, and nested in other patterns).
Examples:
let (_, (->b.x.y, c)) = (0, (1, 2));
let Struct { x: ->a, y: b, .. } = bar();
match foo() {
Some(->x) => {},
None => {},
}
// Question: should we have a short syntax for y: ->y ?
let Struct { x, y: ->y } = Struct { x: 5, y: 6 };
// For example
let Struct { x, ->y } = Struct { x: 5, y: 6 };