Version 2.10.0-119.0.dev
Merge commit '44928c7a20a5cbe8d58046bd35ec0baa995a1f9d' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index e6e8921..adab85b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -2597,10 +2597,10 @@
void forEach_bodyBegin(Node node, Variable loopVariable, Type writtenType) {
AssignedVariablesNodeInfo<Variable> info =
_assignedVariables._getInfoForNode(node);
+ _current = _current.conservativeJoin(info._written, info._captured);
_SimpleStatementContext<Variable, Type> context =
new _SimpleStatementContext<Variable, Type>(_current);
_stack.add(context);
- _current = _current.conservativeJoin(info._written, info._captured);
if (loopVariable != null) {
_current = _current.write(loopVariable, writtenType, typeOperations);
}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/for_each.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/for_each.dart
index 0ebc102..4f1dc0a 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/for_each.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/for_each.dart
@@ -69,3 +69,14 @@
for (int i in [0, 1, 2]) i
];
}
+
+forEach_contains_unreachable_assignment() {
+ late Object v1;
+ for (var _ in [0, 1, 2]) {
+ break;
+ v1 = 0;
+ }
+ // v1 is considered potentially assigned here, for consistency with how we
+ // would analyze the equivalent desugared loop.
+ v1;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index d512956..7aee101 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -810,6 +810,29 @@
});
});
+ test('forEach_bodyBegin() pushes conservative join state', () {
+ var h = _Harness();
+ var x = h.addVar('x', 'int');
+ var forStatement = _Statement();
+ h.assignedVariables(
+ (vars) => vars.nest(forStatement, () => vars.write(x)));
+ h.run((flow) {
+ h.declare(x, initialized: false);
+ expect(flow.isUnassigned(x), true);
+ flow.forEach_bodyBegin(forStatement, null, _Type('int'));
+ // Since a write to x occurs somewhere in the loop, x should no longer
+ // be considered unassigned.
+ expect(flow.isUnassigned(x), false);
+ flow.handleBreak(forStatement);
+ flow.write(x, _Type('int'));
+ flow.forEach_end();
+ // Even though the write to x is unreachable (since it occurs after a
+ // break), x should still be considered "possibly assigned" because of
+ // the conservative join done at the top of the loop.
+ expect(flow.isUnassigned(x), false);
+ });
+ });
+
test('forEach_end() restores state before loop', () {
var h = _Harness();
var x = h.addVar('x', 'int?');
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 9e26d98..a469a99 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1919,6 +1919,7 @@
/// A concrete implementation of a [ConstructorElement].
class ConstructorElementImpl extends ExecutableElementImpl
+ with ConstructorElementMixin
implements ConstructorElement {
/// The constructor to which this constructor is redirecting.
ConstructorElement _redirectedConstructor;
@@ -2008,23 +2009,6 @@
}
@override
- bool get isDefaultConstructor {
- // unnamed
- String name = this.name;
- if (name != null && name.isNotEmpty) {
- return false;
- }
- // no required parameters
- for (ParameterElement parameter in parameters) {
- if (parameter.isNotOptional) {
- return false;
- }
- }
- // OK, can be used as default constructor
- return true;
- }
-
- @override
bool get isFactory {
if (linkedNode != null) {
ConstructorDeclaration linkedNode = this.linkedNode;
@@ -2164,6 +2148,26 @@
}
}
+/// Common implementation for methods defined in [ConstructorElement].
+mixin ConstructorElementMixin implements ConstructorElement {
+ @override
+ bool get isDefaultConstructor {
+ // unnamed
+ var name = this.name;
+ if (name != null && name.isNotEmpty) {
+ return false;
+ }
+ // no required parameters
+ for (ParameterElement parameter in parameters) {
+ if (parameter.isNotOptional) {
+ return false;
+ }
+ }
+ // OK, can be used as default constructor
+ return true;
+ }
+}
+
/// A [TopLevelVariableElement] for a top-level 'const' variable that has an
/// initializer.
class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 29c863b..a37c9d4 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -19,7 +19,9 @@
/// A constructor element defined in a parameterized type where the values of
/// the type parameters are known.
-class ConstructorMember extends ExecutableMember implements ConstructorElement {
+class ConstructorMember extends ExecutableMember
+ with ConstructorElementMixin
+ implements ConstructorElement {
/// Initialize a newly created element to represent a constructor, based on
/// the [declaration], and applied [substitution].
ConstructorMember(
@@ -46,9 +48,6 @@
bool get isConstantEvaluated => declaration.isConstantEvaluated;
@override
- bool get isDefaultConstructor => declaration.isDefaultConstructor;
-
- @override
bool get isFactory => declaration.isFactory;
@override
@@ -787,25 +786,15 @@
@override
bool get isInitializingFormal => declaration.isInitializingFormal;
- @override
- bool get isOptionalNamed {
- if (isLegacy) {
- return super.isNamed;
- }
- return super.isOptionalNamed;
- }
-
- @override
- bool get isRequiredNamed {
- if (isLegacy) {
- return false;
- }
- return super.isRequiredNamed;
- }
-
@deprecated
@override
- ParameterKind get parameterKind => declaration.parameterKind;
+ ParameterKind get parameterKind {
+ var kind = declaration.parameterKind;
+ if (isLegacy && kind == ParameterKind.NAMED_REQUIRED) {
+ return ParameterKind.NAMED;
+ }
+ return kind;
+ }
@override
List<ParameterElement> get parameters {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 75fcfb7..07891bc 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -3503,6 +3503,8 @@
// try to find default generative super constructor
ConstructorElement superUnnamedConstructor =
superElement.unnamedConstructor;
+ superUnnamedConstructor =
+ _currentLibrary.toLegacyElementIfOptOut(superUnnamedConstructor);
if (superUnnamedConstructor != null) {
if (superUnnamedConstructor.isFactory) {
_errorReporter.reportErrorForNode(
@@ -4309,6 +4311,8 @@
}
ConstructorElement superUnnamedConstructor =
superElement.unnamedConstructor;
+ superUnnamedConstructor =
+ _currentLibrary.toLegacyElementIfOptOut(superUnnamedConstructor);
if (superUnnamedConstructor != null) {
if (superUnnamedConstructor.isFactory) {
_errorReporter.reportErrorForNode(
diff --git a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
index 4995806..3643e02 100644
--- a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
@@ -10,11 +10,15 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(NoDefaultSuperConstructorTest);
+ defineReflectiveTests(NoDefaultSuperConstructorWithNullSafetyTest);
});
}
@reflectiveTest
-class NoDefaultSuperConstructorTest extends PubPackageResolutionTest {
+class NoDefaultSuperConstructorTest extends PubPackageResolutionTest
+ with NoDefaultSuperConstructorTestCases {}
+
+mixin NoDefaultSuperConstructorTestCases on PubPackageResolutionTest {
test_explicitDefaultSuperConstructor() async {
await assertNoErrorsInCode(r'''
class A {
@@ -81,3 +85,38 @@
]);
}
}
+
+@reflectiveTest
+class NoDefaultSuperConstructorWithNullSafetyTest
+ extends PubPackageResolutionTest
+ with NoDefaultSuperConstructorTestCases, WithNullSafetyMixin {
+ test_super_requiredParameter_legacySubclass_explicitConstructor() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+ A({required String s});
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart=2.8
+import 'a.dart';
+
+class B extends A {
+ B();
+}
+''');
+ }
+
+ test_super_requiredParameter_legacySubclass_implicitConstructor() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+ A({required String s});
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart=2.8
+import 'a.dart';
+
+class B extends A {}
+''');
+ }
+}
diff --git a/tools/VERSION b/tools/VERSION
index 1813698..5f4d7c5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 118
+PRERELEASE 119
PRERELEASE_PATCH 0
\ No newline at end of file