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

Inconsistent behavior when modifying during iteration #35605

Open
matanui159 opened this Issue Jan 8, 2019 · 3 comments

Comments

Projects
None yet
3 participants
@matanui159
Copy link

matanui159 commented Jan 8, 2019

Info:

  • Dart SDK Version: Dart VM version: 2.1.0 (Tue Nov 13 18:22:02 2018 +0100) on
    "windows_x64"
  • OS: Windows 10 64-bit
  • Browser: tested on chrome, probably happens on all

Given the example code:

void main() {
   var x = [1, 2, 3];
   for (var y in x) {
      print(y);
      if (y == 2) {
         x.remove(y);
      }
   }
}

On webdev serve/dartdevc it outputs:

1
2

and it skips 3

On webdev build/webdev serve --release/dart2js it outputs:

1
2
Uncaught Error: Concurrent modification during iteration: Instance of 'minified:n<int>'.

This sort of inconsistent behavior is an issue during development as it makes bugs and crashes go pass into production unnoticed (which happened to me while developing/releasing a game).

@lrhn

This comment has been minimized.

Copy link
Member

lrhn commented Jan 9, 2019

We don't generally promise to report all concurrent modifications. In many cases, it's a "best effort" approach, and some compilers remove the concurrent modification checks to improve performance.

That does lead to situations like this, where one platform lets a concurrent modification pass, and another catches it.
The development compiler should probably be the most strict here.

I can't see why the dev-compiler should not throw in this situation.
Looking at the source code, the iterator should throw at this point.

If the compiler somehow rewrites the iteration to not use the iterator, then it probably decided to not insert the modification check in that case.

@matanui159

This comment has been minimized.

Copy link

matanui159 commented Jan 9, 2019

This seems to be the output code for a non-release build:

define(['dart_sdk'], function(dart_sdk) {
  'use strict';
  const core = dart_sdk.core;
  const _interceptors = dart_sdk._interceptors;
  const dart = dart_sdk.dart;
  const dartx = dart_sdk.dartx;
  const _root = Object.create(null);
  const main = Object.create(_root);
  const $remove = dartx.remove;
  let JSArrayOfint = () => (JSArrayOfint = dart.constFn(_interceptors.JSArray$(core.int)))();
  main.main = function() {
    let x = JSArrayOfint().of([1, 2, 3]);
    for (let y of x) {
      core.print(y);
      if (y === 2) {
        x[$remove](y);
      }
    }
  };
  dart.trackLibraries(/* lots of unimportant stuff */);
  // Exports:
  return {
    main: main
  };
});

By the way it has sort of bugged me about Dart that there are two compilers, one for development and a completely different one for release. Wouldn't these kind of issues be alot less common if there was only a single compiler for development and release?

@zoechi

This comment has been minimized.

Copy link
Contributor

zoechi commented Jan 9, 2019

@matanui159 https://webdev.dartlang.org/tools/dartdevc might provide the info to make it more clear why there are two Dart-to-JS compilers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment