Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Audit covariant usage in tool #114112

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

Closed
wants to merge 3 commits into from
Closed

Audit covariant usage in tool #114112

wants to merge 3 commits into from

Conversation

jmagman
Copy link
Member

@jmagman jmagman commented Oct 26, 2022

Remove covariant where possible to avoid subtle null safety issue. Where it's still useful, remove from base class and push covariant into overrides to by-default enforce nullability where covariant isn't needed.

See https://dart.dev/guides/language/sound-problems#the-covariant-keyword about how this suppresses the analyzer.

Some (rarely used) coding patterns rely on tightening a type by overriding a parameter’s type with a subtype, which is invalid. In this case, you can use the covariant keyword to tell the analyzer that you are doing this intentionally. This removes the static error and instead checks for an invalid argument type at runtime.

This will need a g3fix.

Note I left the covariant in startApp. That one is really a mess since most subclasses do expect it to be non-null, but it is legitimately called as null in the web case. I guess we can leave that one for now until it causes issues...

if (package == null) {
_logger!.printStatus('This application is not configured to build on the web.');
_logger!.printStatus('To add web support to a project, run `flutter create .`.');
}

Fixes #114090

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@jmagman jmagman added tool Affects the "flutter" command-line tool. See also t: labels. c: tech-debt Technical debt, code quality, testing, etc. labels Oct 26, 2022
@jmagman jmagman self-assigned this Oct 26, 2022
@flutter-dashboard flutter-dashboard bot added the platform-ios iOS applications specifically label Oct 26, 2022
@@ -197,8 +196,7 @@ abstract class DesktopDevice extends Device {
}

/// Builds the current project for this device, with the given options.
Future<void> buildForDevice(
ApplicationPackage package, {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package wasn't used in any of the subclass implementation, remove.

@@ -533,7 +532,7 @@ class IOSSimulator extends Device {

@override
Future<bool> stopApp(
ApplicationPackage app, {
ApplicationPackage? app, {
Copy link
Member Author

@jmagman jmagman Oct 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where the nullability mismatch caused the runtime test failure seen during the roll

Since covariant has been removed from the base class signature, there was correctly an error when this wasn't nullable.

@jmagman jmagman changed the title Audit covariant usage in tool Audit covariant usage in tool Oct 26, 2022
@@ -497,16 +510,6 @@ class FlutterDevice {
);
}

if (package == null) {
Copy link
Member Author

@jmagman jmagman Oct 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rearranged this check to be above the 'Launching ${package!.displayName} ' call, which would crash.

@@ -366,7 +366,7 @@ class AndroidDevice extends Device {

@override
Future<bool> isAppInstalled(
AndroidApk app, {
ApplicationPackage app, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so for this call, will we just be more permissive and allow any ApplicationPackage?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if the right solution to this is not to make Device:

abstract class Device<A extends ApplicationPackage> {
  isAppInstalled(A app, ...) {}
}

Copy link
Member Author

@jmagman jmagman Nov 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be a much better solution, but it also means every single usage of the base class Device becomes Device<ApplicationPackage> if we can't derive the implemented type, and we have hundreds of them.

info: Specify type annotations. (always_specify_types)

I gave up with about 400 more warnings to go:
e780f1d

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you want me to do with this PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me make one more pass, we can land as is

@@ -478,7 +478,7 @@ class AndroidDevice extends Device {

@override
Future<bool> uninstallApp(
AndroidApk app, {
ApplicationPackage app, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not covariant AndroidApk here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because covariant AndroidApk would turns off the static analysis for this type, so if the base class switched to ApplicationPackage? say, the analyzer wouldn't complain and we'd be back where we started.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, I forgot

@@ -519,7 +519,7 @@ class AndroidDevice extends Device {

@override
Future<LaunchResult> startApp(
AndroidApk package, {
AndroidApk? package, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why allow null for Android app?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be nullable because the base class is nullable due to web. That's the bug this is fixing--covariant was hiding that null could be passed in, which in some cases caused crashes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, that was a brain fart on my part

@@ -720,11 +720,11 @@ class AndroidDevice extends Device {

@override
Future<bool> stopApp(
AndroidApk? app, {
ApplicationPackage? app, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not covariant AndroidApk?

Copy link
Contributor

@christopherfujino christopherfujino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jmagman
Copy link
Member Author

jmagman commented Nov 9, 2022

Despite the passing Google Testing, this had a FRoB test failure and needs a g3fix before it can merge.

@jmagman
Copy link
Member Author

jmagman commented Dec 12, 2022

Going to reopen this and hopefully get new google testing failures.

@jmagman jmagman closed this Dec 12, 2022
@jmagman jmagman deleted the covariant branch December 12, 2022 22:22
@jmagman jmagman mentioned this pull request Dec 12, 2022
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: tech-debt Technical debt, code quality, testing, etc. platform-ios iOS applications specifically tool Affects the "flutter" command-line tool. See also t: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Audit covariant usage in flutter_tool
2 participants