Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make copy / reference semantics more explicit #2435

Open
chriseth opened this issue Jun 21, 2017 · 11 comments
Open

Make copy / reference semantics more explicit #2435

chriseth opened this issue Jun 21, 2017 · 11 comments
Labels
breaking change ⚠️ high effort A lot to implement but still doable by a single person. The task is large or difficult. high impact Changes are very prominent and affect users or the project in a major way. language design :rage4: Any changes to the language, e.g. new features needs design The proposal is too vague to be implemented right away selected for development It's on our short-term development

Comments

@chriseth
Copy link
Contributor

chriseth commented Jun 21, 2017

Implicit copy operations from storage to memory, from calldata to memory, from memory to external function arguments, etc is not possible anymore except for value types.

To make an ordinary value copyable, use the copyof operator: x cannot be copied, but copyof x can be copied. Using copyof twice is invalid. Storing a copyable type somewhere erases the copyable property again, i.e. uint[] memory x = copyof y; c.f(x); is invalid.

@o0ragman0o
Copy link

Would a unitary symbol against the variable be better to indicate assignment by reference rather than introduce a new assignment symbol?

    uint[] a;
    uint[] b;
    function foo() {
        uint[] ref = @a; // by reference
        b = ref; // elementwise
    }

@chriseth
Copy link
Contributor Author

I think something like a = b (a and b are identical afterwards, i.e. assignment by reference) and a <- b (a now holds a copy of b and they are only equal, but might diverge) would be more intuitive. On the other hand, this would require us to change = to <- for value types everywhere.

The @-notation on the other hand, is also useful in places where a copy is performed, but not due to an assignment but e.g. due to passing arguments to a function call.

@axic
Copy link
Member

axic commented Sep 14, 2017

This is also a question when passing variables of differing location as function arguments (as this came up on yesterday's weekly call).

Instead of considering C++'s *_cast methods I propose to use copy:

contract C{
  struct A {}
  A a;
  function f(A memory a) {}
  function g() {
    f(copy<memory>(a));
  }
}

@axic axic added language design :rage4: Any changes to the language, e.g. new features and removed requires discussion labels Jul 28, 2018
@chriseth
Copy link
Contributor Author

chriseth commented Nov 8, 2018

I would like to open the discussion on this again. As mentioned earlier, an different assignment symbol is not sufficient, because we also need to consider passing data along function calls.

My proposal would be that reference types are always assigned and passed by reference by default. If this is not possible (because it is an assignment to storage or from storage to memory or across function calls), an rvalue can be turned into an rvalue of "copyable type" by using copy(...). The actual copy will only be performed with the assignment or external function call itself, i.e. copy(x) is not yet a copy of x. The type of copy(x) does not allow any member access or operators. copy(copy(x)) is invalid. Assigning a copyable type to a local variable of storage reference type is invalid.

This will result in rather verbose syntax for external function calls. An alternative would be to use a symbol instead of an actual function call (i.e. %x or whatever).

Another alternative would be to perform copies by default and make references explicit. I think this is not as good because it could result in too many unnecessary (and unnoticed) copy operations.

@chriseth chriseth changed the title Require different assignment symbol for assignments that copy by value Make copy / reference semantics more explicit Nov 9, 2018
@ekpyron
Copy link
Member

ekpyron commented Dec 3, 2018

I think always passing by reference by default and requiring a copy(...) construct is good - the only question is whether the resulting verbosity for external function calls is in fact a problem. I think it would probably be fine and using a symbol instead will probably increase the learning curve of the language and decrease its readability (and we could still add a symbol as an alias for copy(...) later, if people complain).

In theory the verbosity could be decreased by just having copy be the identity/no-op for all simple types and allowing to pass function arguments as tuples and having a variadic variant of copy, e.g. a.someFunction(copy(someArray,10,someOtherArray)) being the same as a.someFunction(copy(someArray),copy(10),copy(someOtherArray)) being the same as a.someFunction(copy(someArray),10,copy(someOtherArray)), but that would be a lot at once and probably overkill for the problem at hand (are there plans for allowing to forward tuple-returns as function arguments?)...

@axic axic mentioned this issue Feb 19, 2019
2 tasks
@leonardoalt
Copy link
Member

I agree with @ekpyron

@chriseth
Copy link
Contributor Author

What about value types? They are copied all the time, so I would assume that a copy operator is not required.

We might also think about using a copy operator instead of a function: f(copy x, copy y[2]). or copyof x.

@chriseth
Copy link
Contributor Author

Note that with this, the expression a = copyof b actually reads like proper english.

@ekpyron
Copy link
Member

ekpyron commented Jan 15, 2020

These days I'm most in favour of using an operator called copyof.

@chriseth
Copy link
Contributor Author

Open question: Do we also require copyof for things like abi.encode? I would probably say yes.

@chriseth
Copy link
Contributor Author

@axic was suggesting copyof(x) but also said that he is not sold on any of the syntax.

If we use the operator without parentheses, the precedence has to be determined.

Next step would be to take a look at some contracts and see how they would look like.

@cameel cameel added selected for development It's on our short-term development high effort A lot to implement but still doable by a single person. The task is large or difficult. high impact Changes are very prominent and affect users or the project in a major way. needs design The proposal is too vague to be implemented right away labels Sep 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change ⚠️ high effort A lot to implement but still doable by a single person. The task is large or difficult. high impact Changes are very prominent and affect users or the project in a major way. language design :rage4: Any changes to the language, e.g. new features needs design The proposal is too vague to be implemented right away selected for development It's on our short-term development
Projects
None yet
Development

No branches or pull requests

6 participants