-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Using a toplevel variable changes inference results in CFE #32866
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
I'll take this one. It looks like our implementation only infers in types of initializing formals after it has completed top-level inference for fields, getters, and setters. What you are seeing is a consequence of performing inference based on the parameter type of What it seems like should happen is that when inferring the type of the static field |
Note that that PR is very obsolete, we got strong push back on it and @stereotype441 agreed to implement something more general. What he implemented hasn't been specified yet, but I don't think we considered that inference of fields feeds into the types of constructors. I don't think this is problematic, but if it is we can consider rejecting this case. Here's an algorithmic sketch of what I think top level inference should be doing now, with initializing formals considered:
cc @lrhn |
I'll read it more closely, but I have an immediate concern with the specified algorithm:
I'm not sure it gives a satisfactory result to do override based "inference" first because it means you can't inherit an inferred field type. Example: class C {
var x = new B(); // Inference finds x as B
}
class D {
get x { log("getting x"); return super.x; }
set x(value) { log("setting x"); super.x = value; }
} Here I would very much like the setter and getter to inherit the type Would it be possible to include override "inference" in the inference loop, and handle it like any other inference (with cycle detection, but since it usually only depends on the superclass, and we don't have cyclic class hierarchies, that's rarely going to be an issue).
(or something like that.) As for the initializing formals, it seems fine, even if it'll rarely be useful. We don't see many fields that both have initializer expressions and are also initialized by a constructor. |
Yes, @lrhn is correct, you can't separate override out entirely. Let's try that again, maybe something like this? @stereotype441 does this look reasonably close to what you implemented (semantically - I'm sure the actual algorithm is different)?
|
cc @eernstg |
It seems like what we have implemented, except that as I noted above we don't handle initializing formals properly. I'm going to lower the priority because I don't think this is affecting users in production, but bump it back up or let me know if it is affecting users. |
Re priority: this shows up when enabling strong-mode in dart2js for internal customers (that's how we discovered the issue), it happens on a couple targets only, though. |
Just wanted to raise attention to this again - I've seen this come up in a couple more scenarios in customer apps. |
Bumping up given @sigmundch 's comment. |
FWIW - I sent out CLs to our internal customers to workaround it, so we are not blocked. There were about 10 files that required modifications due to this. |
I'm keeping the high priority but moving this to the Dart2Stable milestone. |
Proposed fix is here: https://dart-review.googlesource.com/c/sdk/+/60140 |
We seem to be running into more issues of this kind. This is currently showing up on internal customer apps. Here is a small repro: abstract class B {
String get f;
}
class A implements B {
final f;
A(this.f);
}
var a = new A("foo");
main() => print(a); This yields a compile-time error of this form: > pkg/front_end/tool/fasta compile --strong a.dart
a.dart:7:10: Error: The type of parameter 'f' (dynamic) is not a subtype of the corresponding field's type (dart.core::String).
Try changing the type of parameter 'f' to a subtype of dart.core::String.
A(this.f);
^
a.dart:6:9: Context: The field that corresponds to the parameter.
final f;
^ If you remove |
This is a front-end bug in the implementation of inference for initializing formals. When I implemented it I hadn't noticed the feature of our type inference implementation that it records that some, but not all, fields need to have their type inferred. In this case, the field A.f doesn't even know that it needs to have override inference performed to determine its type. |
Top level variable inference in the CFE seems to be going wrong in very non-local ways. For this program:
This program correctly prints
A<int>
.a
to suddenly become an error indicating thata
the type argument of the constructor is being inferred as dynamic:a
is being inferred as having typeA<dynamic>
.a
is incorrectly inferred asA<dynamic>
), but the runtime cast failure indicates that the reified type isA<int>
.This showed up as an unexpected failure when testing dart2js with preview-dart-2 on internal code.
cc @srawlins @sigmundch @stereotype441
The text was updated successfully, but these errors were encountered: