Skip to content

Pattern Matching on Sealed Classes with Default Generic Type Crashes Analyzer in Nested Functions #60264

Closed
@GiancarloCante

Description

@GiancarloCante

I've discovered that using pattern matching with sealed classes works perfectly in global functions and class methods, but attempting the exact same code in a nested function crashes the Dart analyzer completely with error code -32013.

Steps to Reproduce

A simple implementation of Option type.

For the None type we use Never to avoid setting it.

So for reproduce the error is important to set a default type for the parent class.

I use Never but T can be any type.

class None extends Option<Never> {
  const None();
}

If we use a implementation like this, it will work.

class None<T> extends Option<T> {
  const None();
}

Code Example

sealed class Option<T> {
  const Option();
}

class Some<T> extends Option<T> {
  final T value;
  const Some(this.value);
}

class None extends Option<Never> {
  // T can be any type
  const None();

  /// Placeholder get, to use it in switch in this example
  bool get noneProp => false;
}

/// Global const.
const none = None();

/// Works as expected
void fun<T>(Option<T> option) {
  switch (option) {
    case Some():
      final _ = option.value;
    case None():
      final _ = option.noneProp;
  }
}

/// Works as expected
class MyClass {
  void fun<T>(Option<T> option) {
    switch (option) {
      case Some():
        final _ = option.value; 
      case None():
        final _ = option.noneProp;
    }
  }
}

void globalFunWithNestedFun() {
  // **************************
  // Uncomment to crash the analyzer.
  // This is the same as the function
  // above but nested
  // **************************

  // void fun<T>(Option<T> option) {
  //   switch (option) {
  //     case Some():
  //       final _ = option.value; 
  //     case None():
  //       final _ = option.noneProp;
  //   }
  // }

  // **************************
  // After uncommenting the code above,
  // you can write any bad syntax,
  // and usually the editor will not show any error.
  // **************************
}

Expected Behavior

Should work consistently regardless of where the function is defined.

Dart analyzer logs

When uncommenting the nested function, the analyzer immediately crashes. The log shows that uncommenting the function (by removing comment markers) causes the analyzer to fail:

// Log timestamp when the comment markers are removed
[9:56:31 AM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"...","version":741},"contentChanges":[
  {"range":{"start":{"line":56,"character":2},"end":{"line":56,"character":5}},"rangeLength":3,"text":""},
  {"range":{"start":{"line":55,"character":2},"end":{"line":55,"character":5}},"rangeLength":3,"text":""},
  // ...more removals of comment markers...
]},"clientRequestTime":1741272991134}

// Immediately after, the analyzer starts failing with error code -32013
[9:56:31 AM] [Analyzer] [Info] <== {"id":3039,"jsonrpc":"2.0","error":{"code":-32013,"data":"...","message":"Analysis failed for file"}}

The analyzer repeatedly fails with the same error for all subsequent operations:

  • textDocument/inlayHint: {"code":-32013,"data":"...","message":"Analysis failed for file"}
  • textDocument/codeLens: {"code":-32013,"data":"...","message":"Analysis failed for file"}
  • textDocument/documentSymbol: {"code":-32013,"data":"...","message":"Analysis failed for file"}
  • textDocument/documentColor: {"code":-32013,"data":"...","message":"Analysis failed for file"}

The editor becomes unusable until the nested function is removed or commented out again.

Environment

  • Dart SDK version: 3.7.0
  • Flutter version: 3.29.0
  • Platform: macOS

Metadata

Metadata

Assignees

Labels

P2A bug or feature request we're likely to work onarea-dart-modelFor issues related to conformance to the language spec in the parser, compilers or the CLI analyzer.type-bugIncorrect behavior (everything from a crash to more subtle misbehavior)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions