-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Analyzer and CFE inference disagreement #32305
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
Comments
In Analyzer, resolution (type inference) happens as a separate phase before checking (type casts). So when it pushes down I guess CFE sees that an implicit cast is required to This does seem like it will result in more inference of FWIW, this program will behave the same in CFE as Analyzer: void main() {
Function(int) f;
List<num> l;
var a = l.map(f);
int x = a;
} I don't think it would be too difficult to have Analyzer match CFE. We'd need to check the downwards context type and the argument type, and if a cast was implied, discard the argument type in favor of the (greatest closure of the) context type. |
@stereotype441 any thoughts on this? (there are several internal instances of this issue) |
@stereotype441 ping |
I spent some time tracing through this in the debugger, and my analysis is slightly different from both Leaf's and Jenny's. TL;DR: I agree that the CFE is behaving correctly and the analyzer is wrong, but I have a different reason to believe the reason the analyzer is wrong: it's due to a difference in the subtype matching algorithm that should have been benign, but isn't benign due to issue #31792. Because of the difficulty of fixing #31792, I think we should address the difference in subtype matching behavior first. Both the analyzer and the common front end correctly try to infer the type of But that's not what happens, because of issue #31792 (which affects both the analyzer and the front end). What actually happens is that the assignability check doesn't happen until later. So both the analyzer and the front end try to solve for the type parameter of Then the behavior diverges: the front end, on seeing that The analyzer, on the other hand, doesn't fully verify whether a subtype constraint is possible to satisfy. (It only checks whether there are incompatible constraints on any type variables, which there aren't in this case). So after Both behaviors are wrong, but the front end behavior is benign, because it doesn't lead to any correct programs being rejected or incorrect programs being allowed (notwithstanding the examples in #31792). The analyzer behavior is bad, because it means that if we comment out the line If we were to fix issue #31792, then the difference in the subtype constraint matching algorithms would be benign, since it would never even attempt to solve a nonsense constraint like Unfortunately, fixing #31792 in the analyzer is non-trivial. I think a better short-term fix would be to replicate the common front end's current subtype matching behavior in the analyzer. |
I think we may be suggesting the same thing :). Agree a full fix for #31792 would be too much. My idea was to do to a subtype check before we match types, and if the subtype check fails, don't match types. I think that's equivalent to your suggestion? Fixing _matchSubtypeOf directly to compute subtyping as it matches would work as well. I figured it might be a bit tricky, since it will be doing more work (computing the boolean result value), and it'll need track any implied constraints so they can be discarded or rolled back if the subtype check fails. Throwing in a quick But regardless I agree with your analysis, and that a fix shouldn't wait for #31792 |
@jmesserly Ah, I misunderstood your suggestion. Glad we are on the same page :) Yes, I agree that doing the subtype check before we match types would be equivalent to my suggestion, and easier to implement. I'm not assigning the bug to myself yet, since I have limited time (I'm currently recovering from the flu and I have an upcoming vacation Apr 2-20). But I've added it to my list and if I have time I'm glad to do it. Otherwise, anyone else feel free to pick it up--it should be fairly easy to find the non-recursive callers of _matchSubtypeOf and make sure they do the necessary subtype check, and add a unit test (Leaf's example without the last line should do the trick). |
To update: we don't believe this is a blocking issue for beta 3, and have moved this to beta 4. @leafpetersen will look at this as a target of opportunity for beta 3; in the event that he doesn't have cycles, @stereotype441 will take up in the beta 4 timeframe once he's back from vacation. |
@stereotype441 Will you still be able to look at this? |
@bwilkerson Yes, I began working on this on Tuesday and I'm hoping to have a fix ready by early next week. |
The use of _convertStatementsBoundAttribute in _convertAttributes has a type error that the analyzer has been failing to detect due to dart-lang/sdk#32305. In order to fix this analyzer bug, we need to first fix any type errors that exist in the wild. This change fixes the type of _convertStatementsBoundAttribute to match the type expected at the use site, and adds the necessary "as" cast.
Change needed for dart-lang/sdk#32305
Change needed for dart-lang/sdk#32305
The use of _convertStatementsBoundAttribute in _convertAttributes has a type error that the analyzer has been failing to detect due to dart-lang/sdk#32305. In order to fix this analyzer bug, we need to first fix any type errors that exist in the wild. This change fixes the type of _convertStatementsBoundAttribute to match the type expected at the use site, and adds the necessary "as" cast.
Fix out for review: https://dart-review.googlesource.com/c/sdk/+/53685 |
Explicitly specify type for curried function in tests. (#49) Change needed for dart-lang/sdk#32305 Fixed runtime errors in Dart 2 (b 78910237) for file in `ls test/instances/*.dart` ; do dart --preview-dart-2 $file ; done
* Bumping version to 0.5.3-dev Explicitly specify type for curried function in tests. (#49) Change needed for dart-lang/sdk#32305 Fixed runtime errors in Dart 2 (b 78910237) for file in `ls test/instances/*.dart` ; do dart --preview-dart-2 $file ; done * Formatting
For this code:
the analyzer infers
int
as the type argument tomap
, and with an implicit downcast on the argument tomap
(fromint -> int
tonum -> int
), as witnessed by this error message:The CFE infers
dynamic
as the type argument tomap
, with the result that the argument tomap
is invalid (a cross cast fromint -> int
tonum -> dynamic
):I believe that the CFE behavior is correct for Dart 2. We intentionally push the context type down into sub-terms and insert casts to the context type (or to the greatest closure thereof), in order to avoid relying on least upper bound with the pathologies that result (e.g. giving no error message for
String x = (b) ? 3 : []
).cc @jmesserly @stereotype441 @vsmenon to check my thinking on this.
The text was updated successfully, but these errors were encountered: