dart-lang / sdk

The Dart SDK, including the VM, dart2js, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
9.93k stars 1.53k forks source link

Types declared by a macro are not visible outside the library where the macro was applied #56040

Open alexeyinkin opened 1 week ago

alexeyinkin commented 1 week ago

When a macro is applied in a library application.dart and generates a class there, this class can only be used inside that library. When importing application.dart in another library, the generated class can't be used there.

macro.dart:

import 'package:macros/macros.dart';

macro class MyMacro implements ClassTypesMacro {
  const MyMacro();

  @override
  Future<void> buildTypesForClass(ClassDeclaration clazz, ClassTypeBuilder builder) async {
    builder.declareType('GeneratedClass', DeclarationCode.fromString('class GeneratedClass {}'));
  }
}

application.dart:

import 'macro.dart';

@MyMacro()
class MyClass {}

final generatedInstanceSameLibrary = GeneratedClass(); // OK.

main.dart:

import 'application.dart';

final generatedInstanceDifferentLibrary = GeneratedClass(); // Error.

void main() {
  print(generatedInstanceSameLibrary);
}
pubspec.yaml

```yaml name: temp1 environment: sdk: ^3.5.0-180 dependencies: macros: ^0.1.0-main.5 # For 3.5.0-180 ```

% dart run --enable-experiment=macros lib/main.dart
lib/main.dart:3:43: Error: Method not found: 'GeneratedClass'.
final generatedInstanceDifferentLibrary = GeneratedClass();
                                          ^^^^^^^^^^^^^^

The expected behavior is that GeneratedClass is available everywhere application.dart is imported. Quoting the augmentation feature specification:

  • Like a part file, all of the top-level declarations it produces end up in the top-level scope of the augmented library.

If the erroneous line in main.dart is commented out, the program runs as expected.

dart info

``` #### General info - Dart 3.5.0-180.3.beta (beta) (Wed Jun 5 15:06:15 2024 +0000) on "macos_arm64" - on macos / Version 13.6 (Build 22G120) - locale is en-GE #### Project info - sdk constraint: '^3.5.0-180' - dependencies: macros - dev_dependencies: #### Process info | Memory | CPU | Elapsed time | Command line | | -----: | ---: | -----------: | ------------------------------------------------------------------------------------------ | | 124 MB | 0.0% | 05:57:34 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 110 MB | 0.0% | 12:14:41 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 88 MB | 0.0% | 01-10:36:02 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 112 MB | 0.0% | 04:56:23 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 101 MB | 0.0% | 04:41:48 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 107 MB | 0.0% | 01-08:01:56 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 89 MB | 0.0% | 04:31:30 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 73 MB | 0.0% | 04:30:53 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 111 MB | 0.0% | 04:58 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 240 MB | 0.0% | 07:40:44 | dart language-server --client-id=Android-Studio --client-version=AI-223.8836.35 --protocol=analyzer | | 57 MB | 0.0% | 04-11:59:25 | dart language-server --protocol=lsp --client-id=VS-Code --client-version=3.90.0 | | 27 MB | 0.0% | 04-11:59:25 | dart tooling-daemon --machine | | 49 MB | 0.0% | 05:57:34 | flutter_tools.snapshot daemon | | 41 MB | 0.0% | 12:14:40 | flutter_tools.snapshot daemon | | 47 MB | 0.0% | 04:56:23 | flutter_tools.snapshot daemon | | 48 MB | 0.0% | 04:41:48 | flutter_tools.snapshot daemon | | 41 MB | 0.0% | 01-08:01:56 | flutter_tools.snapshot daemon | | 47 MB | 0.0% | 07:40:44 | flutter_tools.snapshot daemon | ```

dart-github-bot commented 1 week ago

Labels: area-language, type-bug Summary: Types generated by a macro within a library are not visible outside that library, even when the library is imported. This contradicts the expected behavior where generated types should be accessible in the augmented library's top-level scope.

alexeyinkin commented 4 days ago

No, that one concerned using macros from a different package. This one is within the same project. By library I mean just a .dart file.

Also, with this issue a macro works (this is seen by application.dart having no errors) but what it declares on the top level is not merged into the augmented library's top-level scope from the standpoint of anyone importing it.

And there's no workaround for this I could find. I just have to declare empty classes and let a macro fill them instead of fully creating them. It's OK for playing around but I can't release my betas with this.

jakemac53 commented 4 days ago

@alexeyinkin Does the analyzer give an error, or do you only see the error when running dart run?

alexeyinkin commented 4 days ago

@jakemac53 as of 3.5.0-292 the analyzer is showing no issues, just dart run.

jakemac53 commented 4 days ago

Sounds like a CFE issue then (already categorized as such).