-
Notifications
You must be signed in to change notification settings - Fork 214
Decide what advice and hints/lints we want around late final
fields
#1239
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
The point of the feature is that this is sometimes not possible. |
There are 100% false positives, in the sense of code for which the only valid alternative is to use a non-final late field (or a normal nullable non-final field). If we really feel that we just don't want to support this, we should just remove the feature. |
My expectation is that the "obvious" migration from fields that are set in a constructor body will be
I would like to explore when this might come up, and whether there are other better patterns for it. Introducing an unusable setter is probably not worth it compared to the old patterns of private field, public getter. I'm aware of at least one place we used this incorrectly, I'm not yet aware of any places where public |
What pattern(s) would we look for after the fact to know that |
After some more discussion I don't think we can tell for sure if it was intentional or a mistake. People do write code with a private field, public getter, and public setter that throws if it is called more than once. If we were to add a hint about public late final Foo _foo;
Foo get foo => _foo;
set foo(Foo foo) => _foo = foo; The question is whether we think this pattern is unusual enough, and the mistake is likely enough, that it's worth disallowing it and forcing this extra boilerplate. We already have some boilerplate if you want to use the feature without the public setter: late final Foo _foo;
Foo get foo => _foo; My opinion is that this is enough of a footgun to just disallow it and impose the boilerplate for the usual cases too. |
One thing that could help here, at least some places where this is done could be avoiding if we have #622 That is the case with dart-archive/collection#156 |
Have you considered making the setter of a public late final field without initializer private? That way the developer adding the field has more control over its usage. |
We have somewhat, yes. So far, the general feeling on the language team is that automatically adding or removing |
You could argue that it is also a bit "magical" that a final field has a public setter. I think, I prefer the magical "_". Have you done any experiments to see how much code would break? |
@nielsenko, yep, this strange behavior of public final fields having setters is a bit of a known problem. See the issue I opened, #1390, where it seems to have been decided that a lint rule should be enough to catch certain error-prone cases. |
As far as I can tell a
late final
field with no initializer is not something anyone should ever write, but it feels very natural for some migrations where fields are initialized in a constructor. The better migration is generally to uselate final
with an initializer (though there are some caveats there as well if it matters when the initializing expression is called).If we think there should be no false positives we should write a hint for this. If we think there do exist valid use cases for this we could make it a lint. Either way we should mention this in the migration guide. cc @munificent
See, for example, dart-archive/async#139
The text was updated successfully, but these errors were encountered: