dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.12k stars 1.57k forks source link

Macros: Failure to compile redirecting factories #55807

Open helightdev opened 4 months ago

helightdev commented 4 months ago

While working on a port of my serialization library, I found following compiler crash while implementing a redirecting factory.

Crash when compiling:
org-dartlang-augmentation:/REDACTED/factories_minimal_report/bin/factories_minimal_report.dart-1:4:18: Internal problem: Expected 'null', but got 'ReturnStatement'.
int? arg;factory Test({int? arg}) = TestImpl;Test.name({this.arg});
                 ^

#0      internalProblem (package:front_end/src/fasta/problems.dart:52:5)
#1      unexpected (package:front_end/src/fasta/problems.dart:78:10)
#2      RedirectingFactoryBuilder.setRedirectingFactoryBody (package:front_end/src/fasta/source/source_factory_builder.dart:388:7)
#3      ClassDeclarationMixin.resolveConstructors (package:front_end/src/fasta/source/class_declaration.dart:161:25)
#4      SourceLibraryBuilder.resolveConstructors (package:front_end/src/fasta/source/source_library_builder.dart:1618:24)
#5      SourceLibraryBuilder.resolveConstructors (package:front_end/src/fasta/source/source_library_builder.dart:1611:38)
#6      SourceLoader.resolveConstructors (package:front_end/src/fasta/source/source_loader.dart:1688:24)
#7      KernelTarget.buildOutlines.<anonymous closure> (package:front_end/src/fasta/kernel/kernel_target.dart:522:14)
<asynchronous suspension>
#8      withCrashReporting (package:front_end/src/fasta/crash.dart:133:12)
<asynchronous suspension>
#9      KernelTarget.buildOutlines (package:front_end/src/fasta/kernel/kernel_target.dart:427:12)
<asynchronous suspension>
#10     _buildInternal (package:front_end/src/kernel_generator_impl.dart:152:7)
<asynchronous suspension>
#11     withCrashReporting (package:front_end/src/fasta/crash.dart:133:12)
<asynchronous suspension>
#12     generateKernel.<anonymous closure> (package:front_end/src/kernel_generator_impl.dart:50:12)
<asynchronous suspension>
#13     CompilerContext.clear (package:front_end/src/fasta/compiler_context.dart:130:3)
<asynchronous suspension>
#14     generateKernel (package:front_end/src/kernel_generator_impl.dart:49:10)
<asynchronous suspension>
#15     kernelForModule (package:front_end/src/api_prototype/kernel_generator.dart:106:11)
<asynchronous suspension>
#16     SingleShotCompilerWrapper.compileInternal (file:///REDACTED/dart-sdk/sdk/pkg/vm/bin/kernel_service.dart:405:11)
<asynchronous suspension>
#17     Compiler.compile.<anonymous closure> (file:///REDACTED/dart-sdk/sdk/pkg/vm/bin/kernel_service.dart:216:45)
<asynchronous suspension>
#18     _processLoadRequest (file:///REDACTED/dart-sdk/sdk/pkg/vm/bin/kernel_service.dart:887:37)
<asynchronous suspension>

While the analyzer runs without any errors and also recognized the constructor, trying to run the code via dart run results in the previously included crash. Using non redirecting factories works like expected.

Isolated example: https://github.com/helightdev/FactoriesIssueMinimal

dart --version:

Dart SDK version: 3.5.0-edge.fb057ea4e07de2af624688455925c0ca07afe04f (main) (Wed May 22 05:18:52 2024 +0000) on "linux_x64"
helightdev commented 4 months ago

Macro Definition

macro class TestMacro implements ClassTypesMacro, ClassDeclarationsMacro  {

  const TestMacro();

  @override
  FutureOr<void> buildTypesForClass(ClassDeclaration clazz, ClassTypeBuilder builder) {
    var implName = "${clazz.identifier.name}Impl";
    builder.declareType(implName, DeclarationCode.fromParts([
      "class $implName extends ${clazz.identifier.name} {",
      "  factory $implName({Object? arg = #default_value}) {",
      "    return $implName._(arg: arg == #default_value ? 5 : arg as int?);",
      "  }",
      "  $implName._({int? arg}) : super.name(arg: arg);",
      "}"
    ]));
  }

  @override
  FutureOr<void> buildDeclarationsForClass(ClassDeclaration clazz, MemberDeclarationBuilder builder) {
    builder.declareInType(DeclarationCode.fromParts([
      "int? arg;",
      "factory ${clazz.identifier.name}({int? arg}) = ${clazz.identifier.name}Impl;",
      "${clazz.identifier.name}.name({this.arg});"
    ]));
  }
}

Usage


void main() {
  Test(arg: 5);
}

@TestMacro()
class Test {}
helightdev commented 4 months ago

Similar problem as in #55432