site-www
site-www copied to clipboard
[2.19] Private field promotion docs
This is an evaluation ticket
Evaluating the possible need for doc updates due to dart-lang/language#2020
Summary
Type promotion is currently only available for local variables. #2020 will make it possible for class fields to be safely promoted if they meet certain criteria: when the field is private
and final
(and there are no concrete getters of the same name, in the same library).
Limiting promotable fields to final
tells the compiler the instance value can't change (and therefore, type promotion remains sound). But, final
doesn't protect soundness if another class implements the original and changes the field declaration. The compiler can at least scan the library for implementing classes and prevent type promotion of the original because of it.
The compiler can't check for implementing classes outside of the original's library though, which is why the field must also be private
, to verify that an implementing class from another library also isn't able to change the value.
One loophole (nosuchmethod
overriding interfaces in an implementing class that doesn't fulfill the interface contract, i.e. doesn't explicitly declare the fields of the original class) is covered in #49687 and another evaluation ticket (https://github.com/dart-lang/site-www/issues/4263).
Evaluation
-
Fixing type promotion failures
-
The sections on this page are actually linked to in type promotion error messages.
-
Only local variables can be promoted is no longer an error
-
"Write captured by a local function", "Written outside of the current closure or function expression", "Write captured outside of the current closure or function expression" sections all have "create a local variable" as a solution / workaround, so I'm wondering if they'll still be errors once non-local variables can be promoted, or maybe the workaround will change to utilize private final field promotion
- "Other causes and workarounds" section also mentions creating a local variable to fix most type promotion issues
-
New sections will need to be added to support new error messages from 2020 (@stereotype441 evaluating actual error code):
- When non-local field promotion is not allowed because they're using an older version of Dart
- When promotion doesn't work because the field is not final and private
- When there's a getter with the same name in the same library that isn't final
- This comment in 2020 says: "If the user tries to promote a field, and it's not promotable because there's some other concrete instance getter with the same name that's not a final field, we can easily explain to them why the promotion failed. And if they want promotion anyway (and know that it's safe), the workaround should be fairly intuitive: just rename the field."
- The workaround here is unclear, "just rename the field" is referring to the original field or the getter?
- wouldn't the getter need to have the same name as the field it's getting?
- wouldn't the fix be that they need to declare the getter final too?
-
-
Effective Dart Implementation draft here: https://github.com/dart-lang/site-www/pull/4272
- "Unfortunately, promotion is only sound for local variables and parameters, so fields and top-level variables aren’t promoted." - no longer true
- ~The entire workaround is technically no longer necessary, maybe the section can be removed?~
- It's still necessary, there are still many cases where type promotion isn't allowed and this is still a workaround for them.
- ~Should we add a "CONSIDER" section recommending declaring private final fields if you want type promotion to happen?~
- No, stating it in the existing section instead
TODO: Check all null safety pages:
- [ ] Understanding null safety:
-
Type promotion on null checks
- This seems like the de facto site definition for type promotion, so will definitely need to mention what is promoted there
- Working with nullable fields
- Lots of minor wording about local-only
-
Type promotion on null checks
- [X] Overview (nothing related)
- [X] FAQ (nothing related)
- [X] Codelab
- Fairly certain there's nothing related, but the examples should probably be tested as-is with private final field promotion active...?
References
- Original issue: https://github.com/dart-lang/language/issues/2020
- Comment that mostly sums up the final conclusion: https://github.com/dart-lang/language/issues/2020#issuecomment-1190546861
Minor nit: when you say "and getters of the same name, in the same library, are also final" I think you mean something like "and there are no concrete getters of the same name, in the same library". (There's no such thing as a final or non-final getter).
Note: need to take into consideration record fields as well
I don't think you intended to close this as done yet. I'm going to reopen it, but feel free to close if that's what you meant :)
@parlough Thanks, that wasn't supposed to happen! 😱 I think it happened because I linked the recent go-link pr to this, and just closed that. But you're right, definitely not anywhere near being done :)