site-www icon indicating copy to clipboard operation
site-www copied to clipboard

[2.19] Private field promotion docs

Open MaryaBelanger opened this issue 2 years ago • 1 comments

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:
  • [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

MaryaBelanger avatar Oct 03 '22 19:10 MaryaBelanger

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).

stereotype441 avatar Oct 03 '22 21:10 stereotype441

Note: need to take into consideration record fields as well

MaryaBelanger avatar Nov 22 '22 20:11 MaryaBelanger

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 avatar Oct 10 '23 15:10 parlough

@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 :)

MaryaBelanger avatar Oct 10 '23 15:10 MaryaBelanger