language icon indicating copy to clipboard operation
language copied to clipboard

Specify order that instance field initializers run with augmentations

Open munificent opened this issue 1 month ago • 1 comments

The language says that the initializers for instance fields run in the order their declarations appear:

int i = 0;

class C {
  int a = i++;
  int b = i++;
}

main() {
  var c = C();
  print('${c.a} ${c.b}');
}

This prints 0 1.

Now consider:

int i = 0;

class C {}

augment class C {
  int a = i++;
}

augment class C {
  int b = i++;
}

Does it behave the same? Consider that these augmentations may be in separate part files.

I think the obvious answer is that field initializers run in augmentation application order. Or, said another way, applying an augmentation appends new members to a type. That's consistent with how enum values and mixin with clauses are handled.

I don't think there's anything scary here, the proposal just needs to actually specify this.

munificent avatar Nov 22 '25 00:11 munificent

I'd say that they run in "generalized source order", which is the same thing as augmentation application order, plus source order within the individual declarations. (I never expected anything other than this.)

Worth mentioning is that initializer expressions like these are currently evaluated as the first thing when invoking an initializing constructor, before binding actuals to formals and initializing variables by initializing formals. This order is observable for mutable variables since the latter can overwrite the former.

With initializing formals, initializer expressions can access the parameter scope created by binding actual to formals, so something had to be changed in the specification. See #4572

lrhn avatar Nov 23 '25 19:11 lrhn