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

Change Array.clone to return iso^ #1782

Closed
wants to merge 1 commit into from

Conversation

sgebbie
Copy link
Contributor

@sgebbie sgebbie commented Mar 30, 2017

The signature for Array.clone was:

fun clone(): Array[this->A!]^ =>

This commit changes it to:

fun clone(): Array[this->A!] iso^ =>

This brings Array.clone in line with the semantics of String.clone.

This is important to be able to easily make copies of local Arrays
that can be sent to other actors. That is, a given actor, Holder,
can now easily construct a copy of an Array to send:

actor Holder
  let _collected: Array[T val] iso
  ...
  be send() =>
    destination.process(_collected.clone())

Previously this might have been done in the following contrived way:

actor Holder
  let _collected: Array[T val] iso
  ...
  be send() =>
    destination.process(_cpy())

  fun ref _cpy(): Array[T val] val =>
    recover val
      let c: Array[T val] ref = Array[T val](0)
      let s = _collected.size()
      var i: USize = 0
      while i < s do
        try
          c.push(_collected(i))
        end
        i = i + 1
      end
      c
    end

This change also makes it possible to send copies when the local Array
is a ref field vs iso field.

The signature for Array.clone was:
	fun clone(): Array[this->A!]^ =>
This commit changes it to:
	fun clone(): Array[this->A!] iso^ =>

This brings Array.clone in line with the semantics of String.clone.

This is important to be able to easily make copies of local Arrays
that can be sent to other actors. That is, given an actor, Holder
can now easily construct a copy of an Array to send:

actor Holder
  let _collected: Array[T val] iso
  ...
  be send() =>
    destination.process(_collected.clone())

Previously this might have been done in the following contrived way:
actor Holder
  let _collected: Array[T val] iso
  ...
  be send() =>
    destination.process(_cpy())

  fun ref _cpy(): Array[T val] val =>
    recover val
      let c: Array[T val] ref = Array[T val](0)
      let s = _collected.size()
      var i: USize = 0
      while i < s do
        try
          c.push(_collected(i))
        end
        i = i + 1
      end
      c
    end

This change also makes it possible to send copies when the local Array
is a ref field vs iso field.
@jemc
Copy link
Member

jemc commented Mar 30, 2017

Unfortunately, this isn't safe in the general case 😞. Specifically, it's not safe for Array[A] unless A <: Any #share - that is, unless A is val or tag.

Please see discussion in #1360, which this is a duplicate of.

This is actually one of the really common pain points in Pony, and we're actively working to solve it. The RFC for specialization (ticket #1410), when implemented, will give us the tools we need to allow iso clone when A <: Any #share, but only allow ref clone in other cases.

@sgebbie
Copy link
Contributor Author

sgebbie commented Mar 30, 2017

Ah right, thanks.

In the code where I wanted to use this I had explicitly made sure that the elements where val, but in my hopefulness the fact that this implementation of clone would expose unsafe copying of elements in the language had slipped past me.

Ah well, easy come, easy go ;)

I will take a look at the discussion and RFC that you mention.

Thanks again.

@jemc
Copy link
Member

jemc commented Mar 30, 2017

@sgebbie I went ahead and created a ticket that you can subscribe yourself to, to watch for progress on this issue, which I'm calling a principle-of-least-surprise bug. See #1784

In the meantime, I'll close this PR and we can do a new one with the other approach when it is unblocked.

Thanks!

@jemc jemc closed this Mar 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants