Skip to content

Weird problem with Generics #61312

@boginni

Description

@boginni

Hi guys, I am having this subtype of type problem with this scenario, but it shouldn't happen:

class Either<L, R> {
  final L? leftValue;
  final R? rightValue;

  Either.left(this.leftValue) : rightValue = null;

  Either.right(this.rightValue) : leftValue = null;

  bool get isLeft => leftValue != null;

  bool get isRight => rightValue != null;

  Either<L, R2> flatMap<R2>(Either<L, R2> Function(R r) f) {
    if (isRight) {
      return f(rightValue as R);
    }

    return Either.left(leftValue as L);
  }
}

class Failure {}

class FooFailure implements Failure {}

Either<Failure, int> query() => Either.left(FooFailure());

Either<FooFailure, int> query2() => Either.left(FooFailure());

Either<Failure, int> getFooQuery() => query();

Either<Failure, int> getFooQuery2() => query2();

final Either<Failure, int> straight = Either.left(FooFailure());

void main() {
  final fooQuery = getFooQuery();

  final fooQuery2 = getFooQuery2();

  fooQuery.flatMap(
    (a) => Either.right(a),
  );
  print('fooQuery flatMap works fine');

  /// works just fine

  straight.flatMap(
    (a) => Either.right(a),
  );
  print('straight flatMap works fine');

  /// works just fine

  fooQuery2.flatMap(
    (a) => Either.right(a),
  );
  print('fooQuery2 flatMap works fine');

  /// type '(int) => Either<Failure, int>' is not a subtype of type '(int) => Either<FooFailure, int>' of 'f'
}

I honestly don't think is that unreasonable to return FooFailure from the query2, but it's unclear to me why the error does not happen with the straight variable, which does basically the same...

some details:

dart --version

Dart SDK version: 3.8.1 (stable) (Wed May 28 00:47:25 2025 -0700) on "windows_x64"

stackTrace:

Unhandled exception:
type '(int) => Either<Failure, int>' is not a subtype of type '(int) => Either<FooFailure, int>' of 'f'
#0      Either.flatMap (file:///C:/Users/[altered for privacy]/bin/test_type.dart:13:57)
#1      main (file:///C:/Users/[altered for privacy]/bin/test_type.dart:55:13)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#3      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

flutter doctor:

[√] Flutter (Channel stable, 3.32.8, on Microsoft Windows [Version 10.0.22631.5039], locale en-US)
[√] Windows Version (11 Pro 64-bit, 23H2, 2009)
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.1)
    ! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.14.6 (June 2025))
[√] Android Studio (version 2025.1.2)
[√] VS Code (version 1.102.3)
[√] Connected device (4 available)
[√] Network resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions