Ticket #89 (closed defect: invalid)

Opened 3 years ago

Last modified 4 months ago

"Can't copy" warning with nested loops

Reported by: RichardT Assigned to:
Priority: moderate Keywords:
Cc:

Description

If you try to modify an array within a nested loop...

sum_b = ([10, 20, 30])
for a in range(3):
    for b in range(4):
        sum_b[a] += b

...it gives an (apparently benign) warning:

'sum_b...' apparently modified, but can't copy it

No such warning is given when run directly from the command line with python.

Robert Schroll wrote:

This is indeed a problem with Reinteract. The problem lies in the part of the code that attempts to track and copy objects that are modified, so that a previous state can be restored when a statement it edited and re-executed. I don't know what Reinteract is trying and failing to copy. It's not sum_b itself, since that is properly restored before the for loop is re-executed.


Owen Taylor wrote:

Sadly, not completely straightforward:

  c = [[1, 2], [3,4]]
  c[1] += [2]

Then before the line c[1] += [2], we need to make a "backup" copy of c so we can rewind execution to that point. Reinteract normally does a backup copy as a shallow copy. But a shallow copy of c isn't good enough because the line c[1] += [2] actually goes ahead and "mutates" not just C, but the [3,4] array that it points. To so, reinteract does a shallow copy of C, and then it descends one level deeper and makes a shallow copy of [3,4]. Richards example:

   for a in range(3):
      for b in range(4):
         sum_b[a] += b

Is a lot like the c[1] += [2], except that the elements we are doing a "deep mutation" on are determined at runtime. What reinteract does is (effectively) rewrite the statement to be:

  sum_b = copy.copy(sum_b)
  sum_b[a] = copy.copy(sum_b[a])
   for a in range(3):
      for b in range(4):
         sum_b[a] += b

But at the second line, a is undefined, so it fails. What might be possible to do is to actually insert the "backup" statements right into place immediately before the modifying statement, so we have instead:

  sum_b = copy.copy(sum_b)
   for a in range(3):
      for b in range(4):
         sum_b[a] = copy.copy(sum_b[a])
         sum_b[a] += b

Which should work, though a bit slowly. There might be some other pitfalls with that that I'm not thinking of right at the moment.

Change History

09/27/11 23:19:56 changed by otaylor

  • status changed from new to closed.
  • resolution set to invalid.

Moved to https://bugzilla.gnome.org/show_bug.cgi?id=660315 - closing as "invalid"