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

Dictionary duplicate(deep=true) creates shallow copy #37162

Closed
paulmiller opened this issue Mar 19, 2020 · 3 comments · Fixed by #37482
Closed

Dictionary duplicate(deep=true) creates shallow copy #37162

paulmiller opened this issue Mar 19, 2020 · 3 comments · Fixed by #37482

Comments

@paulmiller
Copy link

Godot version: 3.2

OS/device including version: Arch Linux (i7-6700, GTX 1070, nvidia driver 440.59-7)

Issue description:
Is duplicate(true) intended to make a deep copy? The parameter is undocumented, but if the dictionary contains Objects, it actually makes a shallow copy, like duplicate(false). If this is intended, then the documentation should explain that. (And maybe the parameter should be renamed.) If it's intended to be a deep copy, then the Objects in the dictionary should be copied.

I wonder if d280b14 is related; it commented out the part of Variant::duplicate that checks the deep flag.

Steps to reproduce:
Try this:

class Thing:
  var x
  func _init(_x):
    x = _x

func _ready():
  var t = Thing.new(1)
  var d1 = { 1:t }
  var d2 = d1.duplicate(true)
  print(d1[1] == d2[1])
  t.x = 3
  print(d1[1].x)
  print(d2[1].x)

It prints:

True
3
3

I'd expect it to print:

False
3
1

Minimal reproduction project: Just paste the above code into any project. Nothing else is needed.

@bojidar-bg
Copy link
Contributor

The deep flag was added with #17382. At that time, some code related to duplicating objects was added in commented, just as a note. At the time I decided that the potential for breaking things if the flag duplicated object was too great.

2dc738c uncommented the code and made it duplicate Resources when deep is on, making sure to pass it on and duplicate other resources recursively.

And finally, the commit you mentioned, d280b14 was added on the very next day. It disabled Resource duplication from Variant::duplicate, with the comment that it breaks stuff :(. A suggestion made in that commit was to add one more argument to duplicate, which would control whether objects are duplicated as well.

@paulmiller
Copy link
Author

Is the intention to only deep-copy Resources, and shallow-copy other Objects? We should document that it's not currently implemented, or remove the parameter from the GDScript API until it is. The current behavior is very surprising. Or should I say, I was very surprised :)

@bojidar-bg
Copy link
Contributor

I feel that the best solution is to document that the deep parameter affects only the copying of dictionaries and arrays. There are too many object types one would prefer to not have duplicated by mistake, especially some types of Resources.

zak-grumbles added a commit to zak-grumbles/godot that referenced this issue Apr 2, 2020
* Added additional clarification for the function of the 'deep'
parameter in the Dictionary's `duplicate` method.
@akien-mga akien-mga added this to the 4.0 milestone Apr 10, 2020
akien-mga pushed a commit to akien-mga/godot that referenced this issue Apr 16, 2020
* Added additional clarification for the function of the 'deep'
parameter in the Dictionary's `duplicate` method.

(cherry picked from commit 469b7c9)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants