-
Notifications
You must be signed in to change notification settings - Fork 228
Description
Consider the following program:
class Test {
const Test(this.values): assert(values != null && values.length != 0);
final List<int> values;
}
const test = Test([1,2,3]); // Compile-time errorThis yields a suboptimal developer experience because values.length is accepted as a potentially constant expression, but there could never be an invocation of the constant constructor which doesn't fail (because values doesn't evaluate to a String).
We could detect and flag this kind of compile-time error at the constructor declaration in many cases, rather than delaying it to the call sites: We could require that in order for e.length to be a potentially constant expression, the static type of e must be either String or dynamic.
The current notion of potentially constant expression is purely syntactical, so we may wish to ensure that this doesn't introduce anything substantially different about potentially constant expressions. However, the static type of e does not depend on the status of e or any of its subexpressions being constant or potentially constant. It would amount to a static type which is already used anyway when deciding on whether to accept e.length as a correctly typed expression. It's just a bit more strict, because an e of type List<...> will be rejected.
We could do similar things for other potentially constant expressions. E.g., we could require for e1 + e2 to be a potentially constant expression that the static type of e1 and e2 is dynamic, num, int, double, or String. This would allow e1 to have static type int and e2 to have static type String, but that kind of mismatch would be caught by the normal type checks on the expression.