(Note that this was reported as dart-lang/sdk#35330, which was closed in favor of this one because language and specification issues are in general handled in this repo.)
Until now, the language specification did not specify that it is a compile-time error for a function declaration to have a control flow where the end of the function can be reached (that is, the body 'completes normally', as opposed to other completions like 'returns with a value' or 'throws'), and hence the null object is returned in situations where that is not likely to be intended.
A future enhancement of Dart with nullable types will give further urgency to fix this omission, because it would have to be a run time error to make that attempt to return the null object, and such an error should be detected at compile-time.
The Dart tools have emitted errors for such situations for a long time, we just need to get it specified (and resolve inconsistencies that tools currently exhibit, if any).
Obviously, this is in general an undecidable question, so we would want to specify a conservative approximation: For this function body, it is statically guaranteed that it will not complete normally. A function body that fails this check will be an error, even though it may be semantically correct (because the reasons for not completing normally are too complex for the analysis to recognize).
Here is a proposal from @lrhn about how we might specify such an approximation, that is, how we would conclude that for a statement S, it is statically known that S will not complete normally (and if we cannot conclude that, a compile-time error occurs, except when the return type is among a short list of exceptions):
A statement is known to not complete normally iff:
- It is a return statement.
- It is a "throw statement" (statement expression where the expression is a throw expression).
- It is a rethrow statement.
- It is a break statement.
- It is a continue statement.
- It is a block statement whose last statement is known to not complete normally.
- It is an if statement with an else branch where both branches are known to not complete normally.
- It is a try-finally statement where the finally block statement is known to not complete normally.
Moreover:
- An unlabeled switch with a default is known to not complete normally if every case and the default block are all known to not complete normally, and the switch does not contain any break targeting the switch.
- An unlabeled do-while loop is known to not complete normally if its body is known to not complete normally and it contains no break or continue targeting the loop.
- A for loop, while loop or do-while loop with a condition expression that is a constant expression evaluating to
true, or a for loop with no condition, are known to not complete normally if their body contains no break targeting the loop.
The goal will be to have a decision criterion which is not "too stupid" to detect that a particular function body does indeed never complete normally (in which case developers would have to write extra statements like return 0; /* Unreachable! */, in spite of the fact that said statement is "obviously" not reachable), and at the same time the complexity of the analysis must be limited at some point, because the underlying question is undecidable.
(Note that this was reported as dart-lang/sdk#35330, which was closed in favor of this one because language and specification issues are in general handled in this repo.)
Until now, the language specification did not specify that it is a compile-time error for a function declaration to have a control flow where the end of the function can be reached (that is, the body 'completes normally', as opposed to other completions like 'returns with a value' or 'throws'), and hence the null object is returned in situations where that is not likely to be intended.
A future enhancement of Dart with nullable types will give further urgency to fix this omission, because it would have to be a run time error to make that attempt to return the null object, and such an error should be detected at compile-time.
The Dart tools have emitted errors for such situations for a long time, we just need to get it specified (and resolve inconsistencies that tools currently exhibit, if any).
Obviously, this is in general an undecidable question, so we would want to specify a conservative approximation: For this function body, it is statically guaranteed that it will not complete normally. A function body that fails this check will be an error, even though it may be semantically correct (because the reasons for not completing normally are too complex for the analysis to recognize).
Here is a proposal from @lrhn about how we might specify such an approximation, that is, how we would conclude that for a statement
S, it is statically known thatSwill not complete normally (and if we cannot conclude that, a compile-time error occurs, except when the return type is among a short list of exceptions):A statement is known to not complete normally iff:
Moreover:
true, or a for loop with no condition, are known to not complete normally if their body contains no break targeting the loop.The goal will be to have a decision criterion which is not "too stupid" to detect that a particular function body does indeed never complete normally (in which case developers would have to write extra statements like
return 0; /* Unreachable! */, in spite of the fact that said statement is "obviously" not reachable), and at the same time the complexity of the analysis must be limited at some point, because the underlying question is undecidable.