Skip to content

Lint concrete class with deceptive member signature caused by inherited covariant parameter #58477

@eernstg

Description

@eernstg

Consider the following example:

class A {
  void m(covariant int i) {}
}

abstract class I {
  void m(num n);
}

class B extends A implements I {
  // Has member signature `void m(covariant num)`.
}

void main() {
  B().m(3.1); // OK statically, but throws at run time.
}

This situation is unfortunate, because it is known statically that an instance of C has the member signature void m(covariant int); but because the method implementation is inherited and a superinterface says otherwise, the static analysis reports the member signature void m(covariant num).

This means that we will have a run-time type error, and it is known statically, but there is no indication that there is a problem at compile-time.

As a matter of style, we could eliminate this problem by always declaring the actual member signature of the inherited method in the case where there is a covariant parameter whose type is a subtype of the one in the class interface:

// ...

class B extends A implements I {
  void m(covariant int i);
}

void main() {
  B().m(3.1); // A compile-time error, as it should be.
}

The situation may not arise very often, but this is just one more reason why developers shouldn't have to think about it, when they could have it flagged by a lint:

LINT declare_covariant_parameter_type: A parameter p in the interface of a concrete class C is covariant-by-declaration and has type T, but the implementation in an instance of C of the enclosing method is inherited, and the corresponding parameter has type S such that S <: T and S != T.

The lint advice would be to add an abstract declaration with the same signature as the inherited method. There could be a quick fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3A lower priority bug or feature requestarea-devexpFor issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.linter-lint-proposaltype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions