Skip to content

Extensions on nested generic mixins don't promote types properly #3382

Open
@ahmednfwela

Description

@ahmednfwela

When declaring extensions on nested generic mixins Mixin<Mixin<T>> for example; the last type T is lost, and the compiler thinks it's dynamic.
leading to runtime errors when the type mismatches.

mixin TestMixin<T> {
  void operateOnValue(T value);
}
// First class expects a string.
class C1 with TestMixin<String> {
  @override
  void operateOnValue(String value) {
    print('operateOnValue: $value');
  }
}

// Second class expects C1 which is a TestMixin<String>
// so this class is matched with TestMixin<TestMixin<String>>
class C2 with TestMixin<C1> {
  @override
  void operateOnValue(C1 value) {
    // do nothing.
  }
}

// extension targets TestMixin<TestMixin<TSub>>.
extension NestedMixinExt<TSub, TestSub extends TestMixin<TSub>>
    on TestMixin<TestSub> { 
  void operateOnNestedValue(TestSub nestedMixin, TSub sub) {
    print('calling operateOnValue, sub type is: $TSub');
    nestedMixin.operateOnValue(sub);
  }
}

void main(List<String> arguments) {
  final c1 = C1(); //TestMixin<String>
  final c2 = C2(); //TestMixin<C1> == TestMixin<TestMixin<String>>

  c2.operateOnNestedValue(c1, 'hello'); // prints "operateOnValue: hello" as expected.
  c2.operateOnNestedValue(c1, 50); // compiles normally, and throws runtime error.
  // type 'int' is not a subtype of type 'String' of 'value'
}

output of the program is:

calling operateOnValue with value hello, sub type is: dynamic
operateOnValue: hello
calling operateOnValue with value 50, sub type is: dynamic
Unhandled exception:
type 'int' is not a subtype of type 'String' of 'value'

also in my use case, I can't change the extension to

extension NestedMixinExt<TSub> on TestMixin<TestMixin<TSub>>

since I need access to the exact nested type.

dart info:

  • Dart 3.1.3 (stable) (Tue Sep 26 14:25:13 2023 +0000) on "windows_x64"
  • on windows / "Windows 10 Pro N" 10.0 (Build 19045)

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