Skip to content

A Switch over a sealed class can match unrelated types #60340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
EArminjon opened this issue Mar 18, 2025 · 3 comments
Closed

A Switch over a sealed class can match unrelated types #60340

EArminjon opened this issue Mar 18, 2025 · 3 comments
Labels
area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.

Comments

@EArminjon
Copy link

EArminjon commented Mar 18, 2025

Hello :) !

I didn't understand how the code bellow didn't show any warnings.

This can lead to very hard nested issue when you didn't understand why your switch isn't working as expected and you suddenly see that the value used in the switch can't match any case value...

In big entreprise team with different skill levels, it become a massive issue.

Bellow code of the issue, I deliberately put a dumb examples to be more explicit.

sealed class User {
  const User();
}

class Connected extends User {
  const Connected();
}

class Disconnected extends User {
  const Disconnected();
}

void test() {
  User user = const Connected();
  Widget child = AppBar();

  print(switch (user) {
    Connected() => true,
    Disconnected() => true,
    AppBar() => false, // not warning ? This type has nothing in common with User class
  });

  print(switch (child) {
    Connected() => true, // no warning ? This type has nothing in common with Widget class
    Disconnected() => true, // no warning ? This type has nothing in common with Widget class
    AppBar() => false,
    _ => throw UnimplementedError(),
  });

  print(switch (10) {
    10 => true,
    '10' => false, // warning well displayed !
    _ => throw UnimplementedError(),
  });
}
@EArminjon EArminjon added the legacy-area-analyzer Use area-devexp instead. label Mar 18, 2025
@johnniwinther johnniwinther added area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. and removed legacy-area-analyzer Use area-devexp instead. labels Mar 18, 2025
@mraleph
Copy link
Member

mraleph commented Mar 18, 2025

You need to mark Connected and Disconnected as final. sealed does not imply finality of subclasses. As written now you can create a subtype of Connected and AppBar in another library.

If you mark all subclasses final you will get the warning.

@EArminjon
Copy link
Author

EArminjon commented Mar 18, 2025

Understood, as we can have something as bellow, the switch will well cover all cases.

class Test extends AppBar implements User {
  Test({super.key});
}

Thanks for your answer.

@eernstg
Copy link
Member

eernstg commented Mar 18, 2025

@EArminjon, you did mention one case which could presumably be handled better. I created #60342 to clarify the matter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.
Projects
None yet
Development

No branches or pull requests

4 participants