Skip to content

Exhaustiveness checking fails on sealed classes with multiple generic parameters, even with inout variance #4667

@omar-mohamed-khallaf

Description

@omar-mohamed-khallaf

I am encountering a non-exhaustive switch error when using a sealed hierarchy with two generic parameters. While I understand this is a known limitation, I wanted to highlight that enabling the experimental variance feature and marking the primary parameter as inout "invariant" does not resolve the issue. The compiler still fails to prove that the subclasses cover the full type space for a specific generic instance.

# analysis_options.yaml
analyzer:
  enable-experiment:
    - variance
abstract class Table {}

sealed class Criterion<inout T extends Table> {}

sealed class Constraint<inout T extends Table, V> extends Criterion<T> {}

final class BoolConstraint<inout T extends Table> extends Constraint<T, bool> {}
final class StringConstraint<inout T extends Table> extends Constraint<T, String> {}

void evaluate<T extends Table>(Criterion<T> criterion) {
  // ERROR: The type 'Criterion<T>' is not exhaustively matched by the switch.
  // It suggests that 'Constraint<Table, Object>' is not covered, 
  // even though T is invariant.
  final result = switch (criterion) {
    BoolConstraint<T>() => 'bool',
    StringConstraint<T>() => 'string',
  };
}

The compiler expects the switch to cover Constraint<Table, Object> (the top-level bounds) rather than recognizing that for a specific Criterion<T>, the only valid subclasses in this sealed hierarchy are those bound to that same T.

With inout variance, the compiler should be able to guarantee that Constraint<T, V> is the only branch to follow, and since all subclasses of Constraint are accounted for, the switch should be exhaustive.

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