Skip to content
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

The Dart Analyzer hangs when destructuring a sealed type variant with a large number of fields inside a switch statement #59927

Open
bubnov opened this issue Jan 17, 2025 · 2 comments
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@bubnov
Copy link

bubnov commented Jan 17, 2025

Let's say we have the following sealed class:

sealed class State {
   const State._();
}

final class StateWithBunchOfFields extends State {
   const StateWithBunchOfFields({
      this.value1,
      this.value2,
      this.value3,
      this.value4,
      this.value5,
      this.value6,
      this.value7,
      this.value8,
      this.value9,
      this.value10,
      this.value11,
      this.value12,
      this.value13,
      this.value14,
      this.value15,
      this.value16,
      this.value17,
      this.value18,
      this.value19,
      this.value20,
      this.value21,
      this.value22,
      this.value23,
      this.value24,
      this.value25,
      this.value26,
      this.value27,
      this.value28,
      this.value29,
      this.value30,
   }) : super._();
  
   final String? value1;
   final String? value2;
   final String? value3;
   final String? value4;
   final String? value5;
   final String? value6;
   final String? value7;
   final String? value8;
   final String? value9;
   final String? value10;
   final String? value11;
   final String? value12;
   final String? value13;
   final String? value14;
   final String? value15;
   final String? value16;
   final String? value17;
   final String? value18;
   final String? value19;
   final String? value20;
   final String? value21;
   final String? value22;
   final String? value23;
   final String? value24;
   final String? value25;
   final String? value26;
   final String? value27;
   final String? value28;
   final String? value29;
   final String? value30;
}

If we try to use it inside a switch statement, the Dart analyzer will likely hang:

final State state; // some state initialized somewhere

switch (state) {
   case StateWithBunchOfFields(
         :var value1,
         :var value2,
         :var value3,
         :var value4,
         :var value5,
         :var value6,
         :var value7,
         :var value8,
         :var value9,
         :var value10,
         :var value11,
         :var value12,
         :var value13,
         :var value14,
         :var value15,
         :var value16,
         :var value17,
         :var value18,
         :var value19,
         :var value20,
         :var value21,
         :var value22,
         :var value23,
         :var value24,
         :var value25,
         :var value26,
         :var value27,
         :var value28,
         :var value29,
         :var value30,
      ): 
      print("too many fields");
}

One possible workaround for this issue is to use an intermediate fields container like this:

sealed class State {
   const State._();
}

final class StateWithFieldsContainer extends State {
  const StateWithFieldsContainer({
    required this.fields,
  }) : super._();

  final FieldsContainer fields;
}

final class FieldsContainer {
  const FieldsContainer({
    this.value1,
    this.value2,
    this.value3,
    this.value4,
    this.value5,
    this.value6,
    this.value7,
    this.value8,
    this.value9,
    this.value10,
    this.value11,
    this.value12,
    this.value13,
    this.value14,
    this.value15,
    this.value16,
    this.value17,
    this.value18,
    this.value19,
    this.value20,
    this.value21,
    this.value22,
    this.value23,
    this.value24,
    this.value25,
    this.value26,
    this.value27,
    this.value28,
    this.value29,
    this.value30,
  });

  final String? value1;
  final String? value2;
  final String? value3;
  final String? value4;
  final String? value5;
  final String? value6;
  final String? value7;
  final String? value8;
  final String? value9;
  final String? value10;
  final String? value11;
  final String? value12;
  final String? value13;
  final String? value14;
  final String? value15;
  final String? value16;
  final String? value17;
  final String? value18;
  final String? value19;
  final String? value20;
  final String? value21;
  final String? value22;
  final String? value23;
  final String? value24;
  final String? value25;
  final String? value26;
  final String? value27;
  final String? value28;
  final String? value29;
  final String? value30;
}

Actual behavior

The Dart Analyzer hangs for a very long time (10+ minutes in my case) when attempting to analyze the switch statement with pattern matching on a class containing numerous fields.

Expected behavior

The Dart Analyzer should either:

  • Complete the analysis in a reasonable time frame
  • Fail gracefully with a clear error message indicating the complexity issue
  • Provide a warning if the pattern matching operation exceeds recommended complexity

Repro

demo.zip

For additional context about this issue, please refer to Dart-Code/Dart-Code#5392

Dart SDK version

Dart SDK version: 3.6.1 (stable) (Tue Jan 7 09:50:00 2025 -0800) on "macos_arm64"
@bubnov bubnov added the area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. label Jan 17, 2025
@bwilkerson
Copy link
Member

@scheglov

@scheglov
Copy link
Contributor

Is was able to reproduce it with the code from Dart-Code/Dart-Code#5392 (comment)

Looking into the profiler it seems to me that we spend all this time checking for exhaustiveness.

Image

I have not tried to analyze the reason, because I don't have yet knowledge how this part of the system works.
@johnniwinther if you have idea.

@scheglov scheglov added P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) labels Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

3 participants