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

Dart analyzer fails to analyze condition in a list construction in enhanced enum constructor #56456

Open ueman opened 1 month ago

ueman commented 1 month ago

The dart analyze command fails for the following (invalid) Dart code snippet:

final bool loggingEnabled = true;

enum Foo {
  bar(const <String>[]),
  baz([
    'foo',
    'bar',
    if (loggingEnabled) 'baz',
  ]);

  const Foo(this.list);

  final List<String> list;
}

The analyzer also fails for the following Dart code, which, to my understanding, should be valid Dart code:

const bool loggingEnabled = bool.fromEnvironment("logging");

enum Foo {
  bar(const <String>[]),
  baz([
    'foo',
    'bar',
    if (loggingEnabled) 'baz',
  ]);

  const Foo(this.list);

  final List<String> list;
}

The following code however, seems to be fine:

const bool loggingEnabled = bool.fromEnvironment("logging");

enum Foo {
  bar(const <String>[]),
  baz(loggingEnabled
      ? [
          'foo',
          'bar',
          'baz',
        ]
      : [
          'foo',
          'bar',
        ]);

  const Foo(this.list);

  final List<String> list;
}

Locally, I use

- Dart 3.4.4 (stable) (Wed Jun 12 15:54:31 2024 +0000) on "macos_arm64"
- on macos / Version 14.6 (Build 23G80)
- locale is en-DE

but I can also reproduce it on DartPad with Dart SDK 3.5.0 and Flutter SDK 3.24.0, with Version 127.0.6533.100 (Official Build) (arm64). On DartPad I get the following error message:

analyze: [Analyzer RequestError method: analysis.getErrors, code: GET_ERRORS_INVALID_FILE, message: Error during `analysis.getErrors`: invalid file.]

This also crashes the custom_lint (0.6.3, I haven't tested 0.6.4) package with the following error message:

{
    "code": "PLUGIN_ERROR",
    "message": "A request threw the exception:Null check operator used on a null value\n#0      ResolverVisitor.flow (package:analyzer/src/generated/resolver.dart:399:36)\n#1      TypeAnalyzer.analyzeIfElement (package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart:711:5)\n#2      ResolverVisitor.visitIfElement (package:analyzer/src/generated/resolver.dart:2618:7)\n#3      IfElementImpl.resolveElement (package:analyzer/src/dart/ast/ast.dart:9177:14)\n#4      TypedLiteralResolver._resolveElements (package:analyzer/src/dart/resolver/typed_literal_resolver.dart:589:42)\n#5      TypedLiteralResolver.resolveListLiteral (package:analyzer/src/dart/resolver/typed_literal_resolver.dart:105:5)\n#6      ResolverVisitor.visitListLiteral (package:analyzer/src/generated/resolver.dart:2805:27)\n#7      ListLiteralImpl.resolveExpression (package:analyzer/src/dart/ast/ast.dart:10936:14)\n#8      ResolverVisitor.dispatchExpression (package:analyzer/src/generated/resolver.dart:724:16)\n#9      TypeAnalyzer.analyzeExpression (package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart:546:9)\n#10     ResolverVisitor.visitNamedExpression (package:analyzer/src/generated/resolver.dart:2930:5)\n#11     NamedExpressionImpl.resolveExpression (package:analyzer/src/dart/ast/ast.dart:12137:14)\n#12     ResolverVisitor.dispatchExpression (package:analyzer/src/generated/resolver.dart:724:16)\n#13     TypeAnalyzer.analyzeExpression (package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart:546:9)\n#14     ResolverVisitor.visitEnumConstantDeclaration (package:analyzer/src/generated/resolver.dart:2281:9)\n#15     EnumConstantDeclarationImpl.accept (package:analyzer/src/dart/ast/ast.dart:5576:15)\n#16     NodeListImpl.accept (package:analyzer/src/dart/ast/ast.dart:12543:20)\n#17     EnumDeclarationImpl.visitChildren (package:analyzer/src/dart/ast/ast.dart:5748:16)\n#18     ResolverVisitor.visitEnumDeclaration (package:analyzer/src/generated/resolver.dart:2306:12)\n#19     EnumDeclarationImpl.accept (package:analyzer/src/dart/ast/ast.dart:5740:50)\n#20     ResolverVisitor.visitCompilationUnit (package:analyzer/src/generated/resolver.dart:1986:23)\n#21     CompilationUnitImpl.accept (package:analyzer/src/dart/ast/ast.dart:3627:50)\n#22     LibraryAnalyzer._resolveFile (package:analyzer/src/dart/analysis/library_analyzer.dart:897:10)\n#23     LibraryAnalyzer._parseAndResolve (package:analyzer/src/dart/analysis/library_analyzer.dart:594:7)\n#24     LibraryAnalyzer.analyze (package:analyzer/src/dart/analysis/library_analyzer.dart:105:5)\n#25     AnalysisDriver._analyzeFileImpl.<anonymous closure> (package:analyzer/src/dart/analysis/driver.dart:1386:11)\n<asynchronous suspension>\n#26     PerformanceLog.runAsync (package:analyzer/src/dart/analysis/performance_logger.dart:50:14)\n<asynchronous suspension>\n#27     AnalysisDriver._analyzeFile.<anonymous closure> (package:analyzer/src/dart/analysis/driver.dart:1299:9)\n<asynchronous suspension>\n#28     OperationPerformanceImpl.runAsync (package:analyzer/src/util/performance/operation_performance.dart:172:14)\n<asynchronous suspension>\n#29     AnalysisDriver._analyzeFile (package:analyzer/src/dart/analysis/driver.dart:1296:5)\n<asynchronous suspension>\n#30     AnalysisDriver.performWork (package:analyzer/src/dart/analysis/driver.dart:1186:7)\n<asynchronous suspension>\n#31     AnalysisDriverScheduler._run (package:analyzer/src/dart/analysis/driver.dart:2433:7)\n<asynchronous suspension>\n",
    "stackTrace": "#0      SocketCustomLintServerToClientChannel.sendCustomLintRequest.<anonymous closure> (package:custom_lint/src/v2/server_to_client_channel.dart:268:11)\n#1      _$CustomLintResponseAnalyzerPluginResponseImpl.map (package:custom_lint/src/v2/protocol.freezed.dart:928:34)\n#2      SocketCustomLintServerToClientChannel.sendCustomLintRequest (package:custom_lint/src/v2/server_to_client_channel.dart:262:14)\n<asynchronous suspension>\n#3      SocketCustomLintServerToClientChannel.sendAnalyzerPluginRequest (package:custom_lint/src/v2/server_to_client_channel.dart:234:22)\n<asynchronous suspension>\n#4      Future.wait.<anonymous closure> (dart:async/future.dart:524:21)\n<asynchronous suspension>\n#5      SocketCustomLintServerToClientChannel.init (package:custom_lint/src/v2/server_to_client_channel.dart:126:5)\n<asynchronous suspension>\n#6      CustomLintServer._maybeSpawnCustomLintPlugin (package:custom_lint/src/v2/custom_lint_analyzer_plugin.dart:392:5)\n<asynchronous suspension>\n#7      CustomLintServer._handleAnalysisSetContextRoots.<anonymous closure> (package:custom_lint/src/v2/custom_lint_analyzer_plugin.dart:339:9)\n<asynchronous suspension>\n#8      PendingOperation.run (package:custom_lint/src/async_operation.dart:22:14)\n<asynchronous suspension>\n#9      CustomLintServer._handleRequest (package:custom_lint/src/v2/custom_lint_analyzer_plugin.dart:171:22)\n<asynchronous suspension>\n"
}

Which, to me, indicates it's also an issue in the analyzer.

dart-github-bot commented 1 month ago

Summary: The Dart analyzer incorrectly fails to analyze a conditional expression within a list construction in an enhanced enum constructor. This occurs when the condition is a variable, but works when the condition is a ternary expression. The analyzer also throws an error on DartPad, preventing analysis.

eernstg commented 1 month ago

Good catch!

I guess boolean should have been loggingEnabled, but the examples do in any case show that the analyzer gets confused about encountering an <ifElement> in an <enumEntry>, which is clearly a bug.

The common front end does not have any issues with these examples.