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.08k stars 1.56k forks source link

Macro application error when passing a list in a macro parameter #56510

Open alexeyinkin opened 4 weeks ago

alexeyinkin commented 4 weeks ago

Looks like a macro can't accept lists as parameters although it can declare such parameters and have default values for them.

macro.dart:

import 'dart:async';

import 'package:macros/macros.dart';

macro class MyMacro implements ClassDeclarationsMacro {
  final int intValue;
  final List<int> listValue;

  const MyMacro({
    this.intValue = 1,
    this.listValue = const [1, 2, 3],
  });

  @override
  FutureOr<void> buildDeclarationsForClass(ClassDeclaration clazz, MemberDeclarationBuilder builder) {
    builder.declareInLibrary(
      DeclarationCode.fromParts([
        'augment class ${clazz.identifier.name} {',
        '  static const intValue = $intValue;',
        '  static const listValue = [', listValue.join(', '), '];',
        '}',
      ]),
    );
  }
}

main.dart:

import 'macro.dart';

@MyMacro(
  intValue: 3,
  listValue: [1, 2, 3], // Comment this out, and it works.
)
class Foo {
  void printList() {
    for (int i = 0; i < intValue; i++)
      print(listValue);
  }
}

void main() {
  Foo().printList();
}
pubspec.yaml

```yaml name: temp1 environment: sdk: ^3.5.0 dependencies: macros: ^0.1.2-main.4 ```

Expected

dart run --enable-experiment=macros main.dart:

[1, 2, 3]
[1, 2, 3]
[1, 2, 3]

Actual

dart run --enable-experiment=macros main.dart:

main.dart:3:2: Error: This macro application didn't apply correctly.
@MyMacro(
 ^
main.dart:9:25: Error: The getter 'intValue' isn't defined for the class 'Foo'.
 - 'Foo' is from 'package:temp1/macro-list/main.dart' ('main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named 'intValue'.
    for (int i = 0; i < intValue; i++)
                        ^^^^^^^^
main.dart:10:13: Error: The getter 'listValue' isn't defined for the class 'Foo'.
 - 'Foo' is from 'package:temp1/macro-list/main.dart' ('main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named 'listValue'.
      print(listValue);
            ^^^^^^^^^

dart analyze:

Analyzing macro-list...                0.6s
No issues found!
dart info

``` If providing this information as part of reporting a bug, please review the information below to ensure it only contains things you're comfortable posting publicly. #### General info - Dart 3.5.0 (stable) (Tue Jul 30 02:17:59 2024 -0700) on "macos_arm64" - on macos / Version 13.6 (Build 22G120) - locale is es-GE #### Process info | Memory | CPU | Elapsed time | Command line | | -----: | ---: | -----------: | ------------------------------------------------------------------------------------------ | | 9 MB | 0.0% | 17-16:40:39 | dart devtools --machine --dtd-uri=ws:/0vhzmGQ5d7QlMnqZ | | 9 MB | 0.0% | 18-20:30:28 | dart devtools --machine --dtd-uri=ws:/563fXWb9URFyRWt8 | | 9 MB | 0.0% | 18-16:10:02 | dart devtools --machine --dtd-uri=ws:/Sirkb3N4HiIZqC0o | | 21 MB | 0.0% | 11-20:36:24 | dart devtools --machine --dtd-uri=ws:/WJznnf2YzxNfAhSj | | 12 MB | 0.0% | 07-04:39:38 | dart devtools --machine --dtd-uri=ws:/avMNibCriCl4KAP1 | | 9 MB | 0.0% | 11-23:42:09 | dart devtools --machine --dtd-uri=ws:/c63FmgSoOQfej1L7 | | 9 MB | 0.0% | 13-17:40:17 | dart devtools --machine --dtd-uri=ws:/cqTYO8HCTYfhQ6HT | | 12 MB | 0.0% | 07-04:56:07 | dart devtools --machine --dtd-uri=ws:/jelJf82ZLvdCIEgf | | 21 MB | 0.0% | 11-18:06:40 | dart devtools --machine --dtd-uri=ws:/uQrwA41naeX5UEfQ | | 38 MB | 0.0% | 07-04:56:08 | dart language-server --client-id=Android-Studio --client-version=AI-241.15989.150 --protocol=analyzer | | 166 MB | 0.0% | 11-20:36:25 | dart language-server --client-id=Android-Studio --client-version=AI-241.15989.150 --protocol=analyzer | | 72 MB | 0.0% | 07-04:16:02 | dart language-server --client-id=Android-Studio --client-version=AI-241.15989.150 --protocol=analyzer | | 31 MB | 0.0% | 11-23:42:09 | dart language-server --client-id=Android-Studio --client-version=AI-241.15989.150 --protocol=analyzer | | 133 MB | 0.0% | 10-23:59:39 | dart language-server --client-id=Android-Studio --client-version=AI-241.15989.150 --protocol=analyzer | | 50 MB | 0.0% | 17-16:40:41 | dart language-server --client-id=Android-Studio --client-version=AI-241.15989.150 --protocol=analyzer | | 49 MB | 0.0% | 12-17:59:10 | dart language-server --client-id=Android-Studio --client-version=AI-241.15989.150 --protocol=analyzer | | 249 MB | 0.0% | 11-18:06:41 | dart language-server --client-id=Android-Studio --client-version=AI-241.15989.150 --protocol=analyzer | | 13 MB | 0.0% | 07-04:56:07 | dart tooling-daemon --machine | | 25 MB | 0.0% | 11-20:36:24 | dart tooling-daemon --machine | | 13 MB | 0.0% | 07-04:39:38 | dart tooling-daemon --machine | | 10 MB | 0.0% | 13-17:40:17 | dart tooling-daemon --machine | | 9 MB | 0.0% | 11-23:42:09 | dart tooling-daemon --machine | | 9 MB | 0.0% | 18-20:30:28 | dart tooling-daemon --machine | | 9 MB | 0.0% | 17-16:40:39 | dart tooling-daemon --machine | | 24 MB | 0.0% | 11-18:06:40 | dart tooling-daemon --machine | | 9 MB | 0.0% | 18-16:10:02 | dart tooling-daemon --machine | | 46 MB | 0.0% | 11-20:36:25 | flutter_tools.snapshot daemon | | 47 MB | 0.0% | 11-22:48:41 | flutter_tools.snapshot daemon | | 46 MB | 0.1% | 11-22:48:41 | flutter_tools.snapshot daemon | | 46 MB | 0.0% | 11-22:48:41 | flutter_tools.snapshot daemon | | 46 MB | 0.0% | 11-22:48:41 | flutter_tools.snapshot daemon | | 41 MB | 0.1% | 11-18:06:45 | flutter_tools.snapshot daemon | ```

Looks like

dart-github-bot commented 4 weeks ago

Summary: The macro application fails when passing a list as a parameter to a macro. The macro can declare list parameters and have default values, but it cannot accept them during application. This results in errors during compilation and prevents the macro from generating the expected code.

alexeyinkin commented 4 weeks ago

When I add const like this:

listValue: const [1, 2, 3]

The errors change:

main.dart:9:25: Error: The getter 'intValue' isn't defined for the class 'Foo'.
 - 'Foo' is from 'package:temp1/macro-list/main.dart' ('main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named 'intValue'.
    for (int i = 0; i < intValue; i++)
                        ^^^^^^^^
main.dart:10:13: Error: The getter 'listValue' isn't defined for the class 'Foo'.
 - 'Foo' is from 'package:temp1/macro-list/main.dart' ('main.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named 'listValue'.
      print(listValue);
            ^^^^^^^^^
main.dart:3:2: Error: This macro application didn't apply correctly due to an unhandled const literal.
@MyMacro(
 ^