Skip to content

Macro: Internal problem: Expected 'null', but got 'ReturnStatement'. #59760

@mcmah309

Description

@mcmah309

For the macro

final variantRegex = RegExp(r'^(\w+)\((.*?)\)$');

macro class Enum
    implements ClassTypesMacro, ClassDeclarationsMacro
    {


      final String? variant1, variant2;

  const Enum([this.variant1, this.variant2]);

  List<String> get variants => [
    if(variant1 != null) variant1!,
    if(variant2 != null) variant2!
    ];

  @override
  FutureOr<void> buildTypesForClass(ClassDeclaration clazz, ClassTypeBuilder builder) {
    final className = clazz.identifier.name;
    for(final variant in variants) {
      final match = variantRegex.firstMatch(variant);
      if (match == null) {
        throw Exception("Variant `$variant` is not valid");
      }
      final newTypeName = match.group(1)!;
      final fieldTypes = match.group(2)!.split(',').map((s) => s.trim()).toList();
      int count = 1;
      final fields = StringBuffer();
      final constructors = StringBuffer();
      for(final fieldType in fieldTypes) {
        fields.write("\t$fieldType v$count;\n");
        constructors.write("this.v$count,");
      }
      builder.declareType(newTypeName, DeclarationCode.fromString('''
final class $className\$$newTypeName implements $className {
$fields

  $className\$$newTypeName._($constructors);
}'''));
    }
  }

  @override
  Future<void> buildDeclarationsForClass(
      ClassDeclaration clazz, MemberDeclarationBuilder builder) async {
        final className = clazz.identifier.name;
      for(final variant in variants) {
        final match = variantRegex.firstMatch(variant);
        if (match == null) {
          throw Exception("Variant `$variant` is not valid");
        }
        final newTypeName = match.group(1)!;
        final fieldTypes = match.group(2)!.split(',').map((s) => s.trim()).toList();
        int count = 1;
        final constructor = StringBuffer();
        for(final fieldType in fieldTypes) {
          constructor.write("$fieldType v$count,");
        }
        builder.declareInType(DeclarationCode.fromString("factory $className.$newTypeName($constructor) = $className\$$newTypeName._;"));
      }
  }
}

Used like

@Enum("Variant(int)")
sealed class W {
}

void main() {
  final w = W.Variant(1);
}

Passes the analyzer and the generated augmentations are correct, but Gives the following error during compilation

Crash when compiling:
org-dartlang-augmentation:/workspaces/algebraic_types/bin/algebraic_types.dart-1: Internal problem: Expected 'null', but got 'ReturnStatement'.

#0      internalProblem (package:front_end/src/base/problems.dart:50:5)
#1      unexpected (package:front_end/src/base/problems.dart:79:10)
#2      RedirectingFactoryBuilder.setRedirectingFactoryBody (package:front_end/src/source/source_factory_builder.dart:452:7)
#3      ClassDeclarationMixin.resolveConstructors (package:front_end/src/source/class_declaration.dart:211:25)
#4      SourceLibraryBuilder.resolveConstructors (package:front_end/src/source/source_library_builder.dart:855:24)
#5      SourceLibraryBuilder.resolveConstructors (package:front_end/src/source/source_library_builder.dart:848:38)
#6      SourceLoader.resolveConstructors (package:front_end/src/source/source_loader.dart:1869:24)
#7      KernelTarget.buildOutlines.<anonymous closure> (package:front_end/src/kernel/kernel_target.dart:617:14)
<asynchronous suspension>
#8      withCrashReporting (package:front_end/src/base/crash.dart:136:12)
<asynchronous suspension>
#9      KernelTarget.buildOutlines (package:front_end/src/kernel/kernel_target.dart:486:12)
<asynchronous suspension>
#10     _buildInternal (package:front_end/src/kernel_generator_impl.dart:180:7)
<asynchronous suspension>
#11     withCrashReporting (package:front_end/src/base/crash.dart:136:12)
<asynchronous suspension>
#12     generateKernel.<anonymous closure> (package:front_end/src/kernel_generator_impl.dart:55:12)
<asynchronous suspension>
#13     CompilerContext.clear (package:front_end/src/base/compiler_context.dart:77:3)
<asynchronous suspension>
#14     generateKernel (package:front_end/src/kernel_generator_impl.dart:53:10)
<asynchronous suspension>
#15     kernelForModule (package:front_end/src/api_prototype/kernel_generator.dart:106:11)
<asynchronous suspension>
#16     SingleShotCompilerWrapper.compileInternal (file:///tmp/tmpy_tauav4/dart-3.7.0-232.0.dev/dart/pkg/vm/bin/kernel_service.dart:405:11)
<asynchronous suspension>
#17     Compiler.compile.<anonymous closure> (file:///tmp/tmpy_tauav4/dart-3.7.0-232.0.dev/dart/pkg/vm/bin/kernel_service.dart:216:45)
<asynchronous suspension>
#18     _processLoadRequest (file:///tmp/tmpy_tauav4/dart-3.7.0-232.0.dev/dart/pkg/vm/bin/kernel_service.dart:887:37)
<asynchronous suspension>

Dart Info

#### General info

- Dart 3.7.0-232.0.dev (dev) (None) on "linux_x64"
- on linux / Linux 6.6.63 #1-NixOS SMP PREEMPT_DYNAMIC Fri Nov 22 14:38:37 UTC 2024
- locale is en_US.UTF-8

#### Project info

- sdk constraint: '3.7.0-232.0.dev'
- dependencies: json
- dev_dependencies: lints, test

Metadata

Metadata

Assignees

No one assigned

    Labels

    cfe-feature-macrosImplement macros features in the CFElegacy-area-front-endLegacy: Use area-dart-model instead.pkg-macrosThe experimental package:_macros librarytype-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