Dart 2 Breaking Change: Implementing inconsistent interfaces is an error

35 views
Skip to first unread message

Leaf Petersen

unread,
Mar 7, 2018, 7:25:48 PM3/7/18
to Dart Misc
What is changing?

In Dart 1 it was legal for a class to indirectly implement the same generic interface inconsistently (that is, with different generic parameters).  For example:

abstract class Box<T> {
  T get x;
}
abstract class NumBox extends Box<num> {}

class DoubleBox extends NumBox implements Box<double> {
  DoubleBox(this.x);
  final double x;
}

Note that `DoubleBox` implements both `Box<num>` and `Box<double>`.   In Dart 2, this will be a static error.  It will still be legal to implement the same interface multiple times with consistent generic parameters (for example, `Box<num>` and `Box<num>`).

What will break?

Class hierarchies which result in classes which implement the same interface inconsistently will get a static error listing the inconsistently implemented interfaces.  

We expect this to be relatively rare since dart2js has never supported multiple inconsistent generic interfaces, and since in strong mode it was difficult to arrange class hierarchies for which this made all overrides valid.

How do I fix it?

If possible, remove one of the interfaces, or make the generic parameters consistent.  Inconsistent interfaces sometimes result from a class leaving type parameters entirely off of an interface that it implements (e.g. `implements Box`).

In some cases, it may be necessary to make additional classes in the hierarchy generic to allow a consistent generic parameter to be threaded through to the appropriate places.  For example, the code above might be changed to:

abstract class Box<T> {
  T get x;
}
abstract class NumBox<T extends num> extends Box<T> {}

class DoubleBox extends NumBox<double> implements Box<double> {
  DoubleBox(this.x);
  final double x;
}


Why is this change being made?

Inconsistent generic interfaces make runtime representations of class hierarchies more difficult, and so some tools have never supported them (e.g. the dart2js compiler).  They also complicate static analysis in various ways.  Restricting this eliminates an inconsistency in our tooling and simplifies various aspects of the tool implementations.

When will this happen?

This has landed in the Dart SDK in 2.0.0-dev.33.0, and was rolled into Flutter bleeding edge this week.

Please reach out to me here or offline with any concerns, and/or with help resolving any issues.

thanks,
-leaf
Reply all
Reply to author
Forward
0 new messages