Adjust NNBD_TOP_MERGE such that void
does not prevail
#824
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I raised an issue in #793 about the nnbd mechanism for computing a member signature named
m
where multiple most-specific member signatures namedm
occur in the direct superinterfaces, and the class itself does not declare a member namedm
. Here is an example showing the main cases (with the member signature ofm
in comments):The problem that this PR aims to resolve is that it is a breaking change, and not a useful one as far as I can see, to get so many situations where return types and parameter types are
void
. The same issue arises at any level of nesting, so we'd have a similar example where the type ends up beingList<void>
with the current nnbd rules, andList<Object?>
with this PR.The breakage occurs in two ways:
void
rather thanObject?
ordynamic
then an error is likely to occur whenever the returned value is used (another possible outcome is that some local variable now gets inferred typevoid
, which may cause a similar problem when that variable is used).void
rather thanObject?
ordynamic
in a method declaration where the superinterfaces are used to infer the parameter type ('override inference'), the same problems arise as those with the return type, except that it affects all usages of said parameter.There is no guarantee that the pre-nnbd rules would choose any particular top type, because those rules used the textual order of the superinterfaces. But if that rule gave rise to the choice of a return or parameter type which was not
void
, then it will be a breaking change if just one of the most specific member signatures (from any superinterface) hasvoid
. So in that sense it is a breaking change, even though there can be cases where there is no breakage.This PR ensures that
void
will only occur in a member signature namedm
when all the direct superinterfaces that have a member signature namedm
agree that this position in the signature should be the typevoid
. If just one of them saysdynamic
thendynamic
prevails, and if just one of them saysObject?
then it prevails over bothvoid
anddynamic
.This is meaningful relative to the return type. Let's say we can choose that
m
returnsvoid
(that is, we use the current nnbd rules) orObject?
(with this PR). In this case at least one superinterface promises thatm
returns a usable object, and then the current class should also return a usable object, hence the type should beObject?
. Whenm
is called and the static type is a superinterface wherem
returnsvoid
, the caller assumes that the object should be discarded. But that's also allowed when the return type isObject?
, so that client can use the invocation correctly as well.