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
Does implicit null count as an initializing expression? #3725
Comments
Yes and no! (Aka, "Why not both?", or "It depends!") There is no good reason to disallow the example program here, it works. Which means that the rule "can't call That is:
EDIT: The following is handled by the spec, and is not a problem. But what is the type of the variable, if it has no declared type, yet? final x = 42;
augment final x = augmented.toRadixString(16) * 1.5;
augment final num x; Is this valid at all? If not, why not? If valid, what is the static type of We need to decide what the type of final x = 42;
augment final x = augmented.toRadixString(16);
augment final x = StringBuffer(augmented);
augment final x = (augmented..write("!Banana")).toString();
augment final x = augmented.length;
augment final int x; EDIT. End of part that you can ignore. We probably also need to check if it works with late int x;
augment int x = augmented + 1; This looks like it could be valid, because it's a non-local I'd go with the same rule as above: The agumentee variable has no initializer expression and is not nullable, If there is an initializer expression, an augmentation can can refer to that expression, even more than once. late final int x;
augment int x = 21;
augment int x = augmented + augmented; will define a variable equivalent to |
@eernstg pointed me to this part of the spec
So, phew! Every variable's type is defined by its initial declaration, augmentations can only change modifiers and values. Also, please change Without macros there should be no issue, the program must be complete, so we can do type inference on each expression. |
What about late final String v;
augment late final String v = "Augment: $augmented"; // Expect runtime LateInitializationError? |
late final String v;
augment late final String v = "Augment: $augmented"; // Expect runtime LateInitializationError? That was my first thought too, but I think it's wrong. The I would make this a compile-time error because Had the declaration been late final String? v;
augment late final String? v = "Augment: $augmented"; // Expect runtime LateInitializationError? I'd allow it to declare a variable equivalent to: late final String? v = "Augment: ${null}"; If the late final String x = "banana";
augment late final String x = "($augment)"; would run into an error when it tries to set There is definitely only one variable, and if it's |
Interesting! If int counter = 0;
late final String v = 'Counter: ${counter++}';
augment late final String v = "Augment: $augmented, $augmented"; // 'Augment: Counter: 0, Counter: 1'. We could also say that
I tend to think of augmentations of functions and variables as introducing new entities (fresh, private name) and implicitly using that new entity when evaluating How, otherwise, do we explain the semantics of |
You can indeed repeat the Let's check the specification:
plus some compile time errors including:
This issue started because of that compile-time error. About the initializer expression, the spec is equally clear:
That clearly says that the new initializing expression replaces the existing initializing expression, and occurrences of That can be a problem, if someone writes an initializer expression expecting it to only be evaluated once, and then a macro evaluates it twice, say to do Alternatively, we could say that initializer expressions are evaluated once and cached, if (It is wrong that the initializer is the only meaningul part, one can want to add annotations too.) So the current spec is clear, the question is whether there is a better behavior. I haven't been able to find one, other than possibly caching the value. Any attempt to make the |
Here's a corner case which is perhaps somewhat ambiguously specified. Thanks to @sgrekhov for bringing up this issue!
Consider the following program:
The augmentation specification has the following rule:
So the question is whether or not the implicit initialization to null counts as an initializing expression? I'd recommend that it does not, and the line marked
OK?
is a compile-time error, for simplicity.However, it could also be argued that some macros can be simpler if they are allowed to use
augmented
as shown above both in the case where there is an explicit initializing expression and in the case where the variable has an implicit initializer with the value null. The argument would be "It's useful, so why not?".[Update: At this time I think "It's useful, so why not?" wins. I'd recommend that we use the semantic criterion "this variable has an initial value" rather than the syntactic "this variable declaration has an initializing expression". So
OK?
above should beOK!
.]@dart-lang/language-team, WDYT?
The text was updated successfully, but these errors were encountered: