Issue 43462. Compute constant values in libraries with contain them.
R=brianwilkerson@google.com
Bug: https://github.com/dart-lang/sdk/issues/43462
Change-Id: I82200c06b1a77f634b7c7f30fd3ad7e10eb01ad4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163280
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
index 81df16c..229cb78 100644
--- a/pkg/analyzer/lib/src/dart/constant/compute.dart
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -82,7 +82,6 @@
library.typeProvider,
declaredVariables,
typeSystem: library.typeSystem,
- experimentStatus: experimentStatus,
);
}
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index ffccab6..e6ebdd3 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -80,7 +80,7 @@
_intType = _typeProvider.intType,
_evaluationEngine = ConstantEvaluationEngine(
_typeProvider, declaredVariables,
- typeSystem: _typeSystem, experimentStatus: featureSet);
+ typeSystem: _typeSystem);
bool get _isNonNullableByDefault => _currentLibrary.isNonNullableByDefault;
@@ -139,7 +139,7 @@
ConstructorElement constructor = node.constructorName.staticElement;
if (constructor != null) {
ConstantVisitor constantVisitor =
- ConstantVisitor(_evaluationEngine, _errorReporter);
+ ConstantVisitor(_evaluationEngine, _currentLibrary, _errorReporter);
_evaluationEngine.evaluateConstructorCall(
node,
node.argumentList.arguments,
@@ -421,8 +421,8 @@
_errorReporter.source,
isNonNullableByDefault: _currentLibrary.isNonNullableByDefault,
);
- DartObjectImpl result =
- expression.accept(ConstantVisitor(_evaluationEngine, subErrorReporter));
+ DartObjectImpl result = expression.accept(
+ ConstantVisitor(_evaluationEngine, _currentLibrary, subErrorReporter));
_reportErrors(errorListener.errors, errorCode);
return result;
}
@@ -520,8 +520,8 @@
_errorReporter.source,
isNonNullableByDefault: _currentLibrary.isNonNullableByDefault,
);
- DartObjectImpl result = initializer
- .accept(ConstantVisitor(_evaluationEngine, subErrorReporter));
+ DartObjectImpl result = initializer.accept(ConstantVisitor(
+ _evaluationEngine, _currentLibrary, subErrorReporter));
if (result == null) {
_errorReporter.reportErrorForToken(
CompileTimeErrorCode
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index ead4938..cd54de6 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -5,6 +5,7 @@
import 'dart:collection';
import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
@@ -17,7 +18,6 @@
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/constant/from_environment_evaluator.dart';
import 'package:analyzer/src/dart/constant/has_type_parameter_reference.dart';
import 'package:analyzer/src/dart/constant/potentially_constant.dart';
@@ -74,9 +74,6 @@
/// using '-D', and represented as [DeclaredVariables].
FromEnvironmentEvaluator _fromEnvironmentEvaluator;
- /// Return the object representing the state of active experiments.
- final ExperimentStatus experimentStatus;
-
/// Validator used to verify correct dependency analysis when running unit
/// tests.
final ConstantEvaluationValidator validator;
@@ -89,7 +86,6 @@
ConstantEvaluationEngine(
TypeProvider typeProvider, DeclaredVariables declaredVariables,
{ConstantEvaluationValidator validator,
- ExperimentStatus experimentStatus,
TypeSystem typeSystem,
// TODO(brianwilkerson) Remove the unused parameter `forAnalysisDriver`.
@deprecated bool forAnalysisDriver})
@@ -101,8 +97,7 @@
isNonNullableByDefault: false,
strictInference: false,
typeProvider: typeProvider,
- ),
- experimentStatus = experimentStatus ?? ExperimentStatus() {
+ ) {
_fromEnvironmentEvaluator = FromEnvironmentEvaluator(
typeSystem,
declaredVariables,
@@ -203,8 +198,8 @@
constant.source,
isNonNullableByDefault: _isNonNullableByDefault,
);
- DartObjectImpl dartObject =
- defaultValue.accept(ConstantVisitor(this, errorReporter));
+ DartObjectImpl dartObject = defaultValue
+ .accept(ConstantVisitor(this, constant.library, errorReporter));
constant.evaluationResult =
EvaluationResultImpl(dartObject, errorListener.errors);
} else {
@@ -220,8 +215,8 @@
constant.source,
isNonNullableByDefault: _isNonNullableByDefault,
);
- DartObjectImpl dartObject =
- constantInitializer.accept(ConstantVisitor(this, errorReporter));
+ DartObjectImpl dartObject = constantInitializer
+ .accept(ConstantVisitor(this, constant.library, errorReporter));
// Only check the type for truly const declarations (don't check final
// fields with initializers, since their types may be generic. The type
// of the final field will be checked later, when the constructor is
@@ -274,7 +269,8 @@
constant.source,
isNonNullableByDefault: _isNonNullableByDefault,
);
- ConstantVisitor constantVisitor = ConstantVisitor(this, errorReporter);
+ ConstantVisitor constantVisitor =
+ ConstantVisitor(this, constant.library, errorReporter);
DartObjectImpl result = evaluateConstructorCall(
constNode,
constNode.arguments.arguments,
@@ -653,6 +649,7 @@
}
ConstantVisitor initializerVisitor = ConstantVisitor(
this,
+ constructor.library,
externalErrorReporter,
lexicalEnvironment: parameterMap,
substitution: Substitution.fromInterfaceType(definingClass),
@@ -953,6 +950,9 @@
/// type provider.
final ConstantEvaluationEngine evaluationEngine;
+ /// The library that contains the constant expression being evaluated.
+ final LibraryElement _library;
+
final Map<String, DartObjectImpl> _lexicalEnvironment;
final Substitution _substitution;
@@ -973,6 +973,7 @@
/// The [substitution] is specified for instance creations.
ConstantVisitor(
this.evaluationEngine,
+ this._library,
this._errorReporter, {
Map<String, DartObjectImpl> lexicalEnvironment,
Substitution substitution,
@@ -981,12 +982,13 @@
_dartObjectComputer = DartObjectComputer(_errorReporter, evaluationEngine);
}
- /// Return the object representing the state of active experiments.
- ExperimentStatus get experimentStatus => evaluationEngine.experimentStatus;
-
/// Convenience getter to gain access to the [evaluationEngine]'s type system.
TypeSystemImpl get typeSystem => evaluationEngine.typeSystem;
+ bool get _isEnabledConstantUpdate2018 {
+ return _library.featureSet.isEnabled(Feature.constant_update_2018);
+ }
+
bool get _isNonNullableByDefault => typeSystem.isNonNullableByDefault;
/// Convenience getter to gain access to the [evaluationEngine]'s type
@@ -1009,7 +1011,7 @@
@override
DartObjectImpl visitAsExpression(AsExpression node) {
- if (experimentStatus.constant_update_2018) {
+ if (_isEnabledConstantUpdate2018) {
DartObjectImpl expressionResult = node.expression.accept(this);
DartObjectImpl typeResult = node.type.accept(this);
return _dartObjectComputer.castToType(node, expressionResult, typeResult);
@@ -1031,7 +1033,7 @@
return _dartObjectComputer.lazyOr(
node, leftResult, () => node.rightOperand.accept(this));
} else if (operatorType == TokenType.QUESTION_QUESTION) {
- if (experimentStatus.constant_update_2018) {
+ if (_isEnabledConstantUpdate2018) {
return _dartObjectComputer.lazyQuestionQuestion(
node, leftResult, () => node.rightOperand.accept(this));
} else {
@@ -1043,17 +1045,17 @@
DartObjectImpl rightResult = node.rightOperand.accept(this);
if (operatorType == TokenType.AMPERSAND) {
return _dartObjectComputer.eagerAnd(
- node, leftResult, rightResult, experimentStatus.constant_update_2018);
+ node, leftResult, rightResult, _isEnabledConstantUpdate2018);
} else if (operatorType == TokenType.BANG_EQ) {
return _dartObjectComputer.notEqual(node, leftResult, rightResult);
} else if (operatorType == TokenType.BAR) {
return _dartObjectComputer.eagerOr(
- node, leftResult, rightResult, experimentStatus.constant_update_2018);
+ node, leftResult, rightResult, _isEnabledConstantUpdate2018);
} else if (operatorType == TokenType.CARET) {
return _dartObjectComputer.eagerXor(
- node, leftResult, rightResult, experimentStatus.constant_update_2018);
+ node, leftResult, rightResult, _isEnabledConstantUpdate2018);
} else if (operatorType == TokenType.EQ_EQ) {
- if (experimentStatus.constant_update_2018) {
+ if (_isEnabledConstantUpdate2018) {
return _dartObjectComputer.lazyEqualEqual(
node, leftResult, rightResult);
}
@@ -1106,7 +1108,7 @@
DartObjectImpl visitConditionalExpression(ConditionalExpression node) {
Expression condition = node.condition;
DartObjectImpl conditionResult = condition.accept(this);
- if (experimentStatus.constant_update_2018) {
+ if (_isEnabledConstantUpdate2018) {
if (conditionResult == null) {
return conditionResult;
} else if (!conditionResult.isBool) {
@@ -1228,7 +1230,7 @@
@override
DartObjectImpl visitIsExpression(IsExpression node) {
- if (experimentStatus.constant_update_2018) {
+ if (_isEnabledConstantUpdate2018) {
DartObjectImpl expressionResult = node.expression.accept(this);
DartObjectImpl typeResult = node.type.accept(this);
return _dartObjectComputer.typeTest(node, expressionResult, typeResult);
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 90abe81..e79ed4e 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -4,11 +4,12 @@
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/value.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart' show TypeSystemImpl;
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/engine.dart' show RecordingErrorListener;
@@ -99,25 +100,17 @@
/// The source containing the expression(s) that will be evaluated.
final Source _source;
- /// The type provider used to access the known types.
- final TypeProvider _typeProvider;
-
- /// The type system primitives.
- final TypeSystemImpl _typeSystem;
+ /// The library containing the expression(s) that will be evaluated.
+ final LibraryElement _library;
/// Initialize a newly created evaluator to evaluate expressions in the given
/// [source]. The [typeProvider] is the type provider used to access known
/// types.
- ConstantEvaluator(this._source, TypeProvider typeProvider,
- {TypeSystemImpl typeSystem})
- : _typeSystem = typeSystem ??
- TypeSystemImpl(
- implicitCasts: true,
- isNonNullableByDefault: false,
- strictInference: false,
- typeProvider: typeProvider,
- ),
- _typeProvider = typeProvider;
+ ConstantEvaluator(this._source, LibraryElement library) : _library = library;
+
+ TypeProviderImpl get _typeProvider => _library.typeProvider;
+
+ TypeSystemImpl get _typeSystem => _library.typeSystem;
EvaluationResult evaluate(Expression expression) {
RecordingErrorListener errorListener = RecordingErrorListener();
@@ -129,6 +122,7 @@
DartObjectImpl result = expression.accept(ConstantVisitor(
ConstantEvaluationEngine(_typeProvider, DeclaredVariables(),
typeSystem: _typeSystem),
+ _library,
errorReporter));
List<AnalysisError> errors = errorListener.errors;
if (errors.isNotEmpty) {
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index edabdfa..0f81810 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -359,6 +359,7 @@
declaredVariables,
typeSystem: typeSystem,
),
+ libraryElement,
errorReporter,
);
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 097479c..996f5cc 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -501,8 +501,7 @@
var file = getFile(result.path);
var evaluator = ConstantEvaluator(
file.createSource(result.uri),
- result.typeProvider,
- typeSystem: result.typeSystem,
+ result.libraryElement,
);
return evaluator.evaluate(expression);
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 6cd1ae9..1c5816f 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -306,8 +305,6 @@
Map<String, String> declaredVariables = const {},
Map<String, DartObjectImpl> lexicalEnvironment,
}) {
- var analysisContext = contextFor(this.result.path);
- var options = analysisContext.analysisOptions as AnalysisOptionsImpl;
var expression = findNode.topVariableDeclarationByName(name).initializer;
var source = this.result.unit.declaredElement.source;
@@ -323,9 +320,9 @@
ConstantEvaluationEngine(
typeProvider,
DeclaredVariables.fromMap(declaredVariables),
- experimentStatus: options.experimentStatus,
typeSystem: this.result.typeSystem,
),
+ this.result.libraryElement,
errorReporter,
lexicalEnvironment: lexicalEnvironment,
),
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
index cfe11e5..34b271d 100644
--- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -232,6 +232,25 @@
var a = findElement.topVar('a') as ConstVariableElement;
expect(a.computeConstantValue().toIntValue(), 42);
}
+
+ /// See https://github.com/dart-lang/sdk/issues/43462
+ test_useLanguageVersionOfEnclosingLibrary() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class Wrapper {
+ final int value;
+ const Wrapper(Object value) : value = value as int;
+}
+''');
+
+ await assertNoErrorsInCode(r'''
+// @dart = 2.4
+import 'a.dart';
+
+void f() {
+ const Wrapper(0);
+}
+''');
+ }
}
@reflectiveTest