Skip to content

Proposal: don't require synthetic mixin applications to have a well-typed interface. #4476

@stereotype441

Description

@stereotype441

Consider the following code (from dart-lang/sdk#61145):

class A {}
class B {}
class C implements A, B {}
abstract class D {
  A get foo;
}
abstract class E {
  B get foo;
}
mixin M implements E {}
abstract class F extends D with M {
  C get foo;
}

main() {}

The analyzer accepts this code; the CFE rejects it. The CFE says:

../../tmp/proj/test.dart:11:16: Error: Class 'D with M' inherits multiple members named 'foo' with incompatible signatures.
Try adding a declaration of 'foo' to 'D with M'.
abstract class F extends D with M {
               ^
../../tmp/proj/test.dart:5:9: Context: This is one of the overridden members.
  A get foo;
        ^^^
../../tmp/proj/test.dart:8:9: Context: This is one of the overridden members.
  B get foo;
        ^^^

Based on my understanding of the spec, the CFE is correct in rejecting the code, because:

  • The declaration abstract class F extends D with M should be understood as syntactic sugar for abstract class F extends DwithM, where DwithM is a synthetic mixin application, defined as class DwithM = D with M.
  • The interface for class DwithM inherits two declarations of foo: one with type A (from D), and one with type B (from M, via E).
  • Since neither A nor B is a subtype of the other, the compiler cannot assign a type to foo in the interface for DwithM.

This is a particularly frustrating situation because:

  • The error can't be conveniently worked around; the CFE's suggestion to "Try adding a declaration of 'foo' to 'D with M'" is impossible.
  • It's not obvious why this code needs to be rejected at all; after all, class F provides a declaration of foo with a type that's compatible with the interfaces of both D and M, and it's impossible for any expression to have a static type of DwithM, so there's no reason the compiler would ever need to look up the type of foo in DwithM at all. More generally, it's impossible for an expression to have a static type that is a synthetic mixin application. (The proof of this is subtle; I'll make a follow-up comment with details). Edit: this is wrong in some cases involving generics. See Proposal: don't require synthetic mixin applications to have a well-typed interface. #4476 (comment).

I propose that we drop the requirement for synthetic mixin applications to have well-defined interfaces, in which case the analyzer's behavior will be considered correct, and the example code above will be allowed.

CC @dart-lang/language-team

Metadata

Metadata

Assignees

No one assigned

    Labels

    requestRequests to resolve a particular developer problem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions