Version 2.17.0-200.0.dev
Merge commit '76bbd199a403de16320df682a5c807797d080520' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart b/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
index c729106..ccbba42 100644
--- a/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
@@ -581,9 +581,17 @@
var rewind = _constraints.length;
for (var i = 0; i < P.typeArguments.length; i++) {
+ var variance =
+ (P.element.typeParameters[i] as TypeParameterElementImpl).variance;
var M = P.typeArguments[i];
var N = Q.typeArguments[i];
- if (!trySubtypeMatch(M, N, leftSchema)) {
+ if ((variance.isCovariant || variance.isInvariant) &&
+ !trySubtypeMatch(M, N, leftSchema)) {
+ _constraints.length = rewind;
+ return false;
+ }
+ if ((variance.isContravariant || variance.isInvariant) &&
+ !trySubtypeMatch(N, M, leftSchema)) {
_constraints.length = rewind;
return false;
}
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 5ff9302..079b416 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -66,6 +66,7 @@
import 'type_inference/test_all.dart' as type_inference;
import 'type_literal_test.dart' as type_literal;
import 'type_name_test.dart' as type_name;
+import 'variance_test.dart' as variance_test;
import 'yield_statement_test.dart' as yield_statement;
main() {
@@ -128,6 +129,7 @@
type_inference.main();
type_literal.main();
type_name.main();
+ variance_test.main();
yield_statement.main();
defineReflectiveTests(UpdateNodeTextExpectations);
}, name: 'resolution');
diff --git a/pkg/analyzer/test/src/dart/resolution/variance_test.dart b/pkg/analyzer/test/src/dart/resolution/variance_test.dart
new file mode 100644
index 0000000..34067a8
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/variance_test.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(VarianceTest);
+ });
+}
+
+@reflectiveTest
+class VarianceTest extends PubPackageResolutionTest {
+ @override
+ List<String> get experiments => [
+ ...super.experiments,
+ EnableString.variance,
+ ];
+
+ test_inference_in_parameter() async {
+ await assertNoErrorsInCode('''
+class Contravariant<in T> {}
+
+class Exactly<inout T> {}
+
+class Upper {}
+class Middle extends Upper {}
+
+Exactly<T> inferContraContra<T>(Contravariant<T> x, Contravariant<T> y)
+ => new Exactly<T>();
+
+main() {
+ inferContraContra(Contravariant<Upper>(), Contravariant<Middle>());
+}
+ ''');
+ assertType(
+ findNode.methodInvocation('inferContraContra(').typeArgumentTypes![0],
+ 'Middle');
+ }
+
+ test_inference_in_parameter_downwards() async {
+ await assertErrorsInCode('''
+class B<in T> {
+ B(List<T> x);
+ void set x(T val) {}
+}
+
+main() {
+ B<int> b = new B(<num>[])..x=2.2;
+}
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 76, 1),
+ ]);
+ assertType(
+ (findNode.instanceCreation('new B').staticType as InterfaceType)
+ .typeArguments[0],
+ 'num');
+ }
+
+ test_inference_inout_parameter() async {
+ await assertErrorsInCode('''
+class Invariant<inout T> {}
+
+class Exactly<inout T> {}
+
+Exactly<T> inferInvInv<T>(Invariant<T> x, Invariant<T> y) => new Exactly<T>();
+
+main() {
+ inferInvInv(Invariant<String>(), Invariant<int>());
+}
+''', [
+ error(CompileTimeErrorCode.COULD_NOT_INFER, 147, 11),
+ error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 159, 19),
+ error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 180, 16),
+ ]);
+ }
+
+ test_inference_out_parameter() async {
+ await assertNoErrorsInCode('''
+class Covariant<out T> {}
+
+class Exactly<inout T> {}
+
+class Upper {}
+class Middle extends Upper {}
+
+Exactly<T> inferCovCov<T>(Covariant<T> x, Covariant<T> y) => new Exactly<T>();
+
+main() {
+ inferCovCov(Covariant<Upper>(), Covariant<Middle>());
+}
+''');
+ assertType(findNode.methodInvocation('inferCovCov(').typeArgumentTypes![0],
+ 'Upper');
+ }
+}
diff --git a/pkg/front_end/tool/fasta.dart b/pkg/front_end/tool/fasta.dart
index 14f8503..cdd5609 100644
--- a/pkg/front_end/tool/fasta.dart
+++ b/pkg/front_end/tool/fasta.dart
@@ -4,7 +4,19 @@
import 'dart:io';
+import "package:testing/src/run_tests.dart" as run_tests;
+import 'package:kernel/src/tool/dump.dart' as dump;
import '../test/utils/io_utils.dart' show computeRepoDir;
+import '_fasta/abcompile.dart' as abcompile;
+import '_fasta/compile.dart' as compile;
+import '_fasta/compile_platform.dart' as compile_platform;
+import '_fasta/generate_experimental_flags.dart' as generate_experimental_flags;
+import '_fasta/generate_messages.dart' as generate_messages;
+import '_fasta/log_analyzer.dart' as log_analyzer;
+import '_fasta/log_collector.dart' as log_collector;
+import '_fasta/outline.dart' as outline;
+import '_fasta/parser.dart' as parser;
+import '_fasta/scanner.dart' as scanner;
final String repoDir = computeRepoDir();
@@ -35,62 +47,86 @@
String command = args[index++];
List<String> remainingArguments = args.skip(index).toList();
+ dynamic Function(List<String>) mainFunction;
+
switch (command) {
case 'abcompile':
+ mainFunction = abcompile.main;
script = '${toolDir}/abcompile.dart';
break;
case 'compile':
+ mainFunction = compile.main;
script = '${toolDir}/compile.dart';
break;
case 'compile-platform':
+ mainFunction = compile_platform.main;
script = '${toolDir}/compile_platform.dart';
break;
case 'log':
+ mainFunction = log_analyzer.main;
script = '${toolDir}/log_analyzer.dart';
break;
case 'logd':
+ mainFunction = log_collector.main;
script = '${toolDir}/log_collector.dart';
break;
case 'outline':
+ mainFunction = outline.main;
script = '${toolDir}/outline.dart';
break;
case 'parser':
+ mainFunction = parser.main;
script = '${toolDir}/parser.dart';
break;
case 'scanner':
+ mainFunction = scanner.main;
script = '${toolDir}/scanner.dart';
break;
case 'dump-ir':
+ mainFunction = dump.main;
script = '${kernelBin}/dump.dart';
if (remainingArguments.isEmpty || remainingArguments.length > 2) {
stop("Usage: $command dillFile [output]");
}
break;
case 'testing':
+ mainFunction = run_tests.main;
script = '${repoDir}/pkg/testing/bin/testing.dart';
scriptArguments.add('--config=${repoDir}/pkg/front_end/testing.json');
break;
case 'generate-messages':
+ mainFunction = generate_messages.main;
script = '${toolDir}/generate_messages.dart';
break;
case 'generate-experimental-flags':
+ mainFunction = generate_experimental_flags.main;
script = '${toolDir}/generate_experimental_flags.dart';
break;
default:
stop("'$command' isn't a valid subcommand.");
}
- List<String> arguments = [];
- arguments.addAll(extraVmArguments);
- arguments.add('--enable-asserts');
- arguments.add(script);
- arguments.addAll(remainingArguments);
- arguments.addAll(scriptArguments);
+ if (extraVmArguments.isNotEmpty) {
+ List<String> arguments = [];
+ arguments.addAll(extraVmArguments);
+ arguments.add('--enable-asserts');
+ arguments.add(script);
+ arguments.addAll(remainingArguments);
+ arguments.addAll(scriptArguments);
- print('Running: ${dartVm} ${arguments.join(' ')}');
- Process process = await Process.start(dartVm, arguments,
- mode: ProcessStartMode.inheritStdio);
- exitCode = await process.exitCode;
+ print('Running: ${dartVm} ${arguments.join(' ')}');
+ Process process = await Process.start(dartVm, arguments,
+ mode: ProcessStartMode.inheritStdio);
+ exitCode = await process.exitCode;
+ } else {
+ // Run within the same VM if no VM arguments are provided.
+ List<String> arguments = [];
+ arguments.addAll(remainingArguments);
+ arguments.addAll(scriptArguments);
+
+ print('Running: ${script} ${arguments.join(' ')}');
+ await mainFunction(arguments);
+ }
}
Never stop(String message) {
diff --git a/pkg/kernel/bin/dump.dart b/pkg/kernel/bin/dump.dart
index 0f901a2..6ef167a 100755
--- a/pkg/kernel/bin/dump.dart
+++ b/pkg/kernel/bin/dump.dart
@@ -3,30 +3,4 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:io';
-
-import 'package:kernel/kernel.dart';
-import 'package:kernel/src/tool/command_line_util.dart';
-
-void usage() {
- print("Prints a dill file as a textual format.");
- print("");
- print("Usage: dart <script> dillFile.dill [output]");
- print("");
- print("The first given argument should be an existing file");
- print("that is valid to load as a dill file.");
- print("");
- print("The second argument is optional.");
- print("If given, output will be written to this file.");
- print("If not given, output will be written to standard out.");
- exit(1);
-}
-
-void main(List<String> args) {
- CommandLineHelper.requireVariableArgumentCount([1, 2], args, usage);
- CommandLineHelper.requireFileExists(args[0]);
- var binary = CommandLineHelper.tryLoadDill(args[0]);
- writeComponentToText(binary,
- path: args.length > 1 ? args[1] : null,
- showOffsets: const bool.fromEnvironment("showOffsets"));
-}
+export 'package:kernel/src/tool/dump.dart';
diff --git a/pkg/kernel/lib/src/tool/dump.dart b/pkg/kernel/lib/src/tool/dump.dart
new file mode 100644
index 0000000..dff0851
--- /dev/null
+++ b/pkg/kernel/lib/src/tool/dump.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import '../../kernel.dart';
+import 'command_line_util.dart';
+
+void usage() {
+ print("Prints a dill file as a textual format.");
+ print("");
+ print("Usage: dart <script> dillFile.dill [output]");
+ print("");
+ print("The first given argument should be an existing file");
+ print("that is valid to load as a dill file.");
+ print("");
+ print("The second argument is optional.");
+ print("If given, output will be written to this file.");
+ print("If not given, output will be written to standard out.");
+ exit(1);
+}
+
+void main(List<String> args) {
+ CommandLineHelper.requireVariableArgumentCount([1, 2], args, usage);
+ CommandLineHelper.requireFileExists(args[0]);
+ Component binary = CommandLineHelper.tryLoadDill(args[0]);
+ writeComponentToText(binary,
+ path: args.length > 1 ? args[1] : null,
+ showOffsets: const bool.fromEnvironment("showOffsets"));
+}
diff --git a/tests/language/variance/variance_in_inference_error_test.dart b/tests/language/variance/variance_in_inference_error_test.dart
index 34c6fb3..a4c67b7 100644
--- a/tests/language/variance/variance_in_inference_error_test.dart
+++ b/tests/language/variance/variance_in_inference_error_test.dart
@@ -48,30 +48,40 @@
//^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// [cfe] unspecified
+// ^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// String <: T <: int is not a valid constraint.
inferCovContra(Covariant<String>(), Contravariant<int>());
//^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// [cfe] unspecified
+// ^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// Middle <: T <: Lower is not a valid constraint
inferCovContra(Covariant<Middle>(), Contravariant<Lower>());
//^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// [cfe] unspecified
+// ^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// Upper <: T <: Lower is not a valid constraint
inferCovContra(Covariant<Upper>(), Contravariant<Lower>());
//^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// [cfe] unspecified
+// ^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// Upper <: T <: Middle is not a valid constraint
inferCovContra(Covariant<Upper>(), Contravariant<Middle>());
//^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// [cfe] unspecified
+// ^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// Inference for Contrabound(...) produces Lower <: T <: Upper.
// Since T is contravariant, we choose Upper as the solution.
diff --git a/tests/language/variance/variance_inout_inference_error_test.dart b/tests/language/variance/variance_inout_inference_error_test.dart
index 8bf485f..7f51119 100644
--- a/tests/language/variance/variance_inout_inference_error_test.dart
+++ b/tests/language/variance/variance_inout_inference_error_test.dart
@@ -23,6 +23,8 @@
main() {
// Middle <: T <: Middle and int <: T <: int are not valid constraints.
inferInvInv(Invariant<Middle>(), Invariant<int>());
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// ^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Object>'.
@@ -32,12 +34,16 @@
// Middle <: T <: Middle and Upper <: T <: Upper are not valid constraints.
inferInvInv(Invariant<Middle>(), Invariant<Upper>());
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// ^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Upper>'.
// Middle <: T <: Middle and Lower <: T <: Lower are not valid constraints.
inferInvInv(Invariant<Middle>(), Invariant<Lower>());
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// ^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<Lower>' can't be assigned to the parameter type 'Invariant<Middle>'.
@@ -46,6 +52,8 @@
// Middle <: T <: Middle
// Upper <: T <: Middle is not a valid constraint.
inferInvCov(Invariant<Middle>(), Covariant<Upper>());
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// ^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Upper>'.
@@ -54,6 +62,8 @@
// Middle <: T <: Lower
// Middle <: T <: Lower is not a valid constraint
inferInvContra(Invariant<Middle>(), Contravariant<Lower>());
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// ^^^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Contravariant<Lower>' can't be assigned to the parameter type 'Contravariant<Middle>'.
diff --git a/tools/VERSION b/tools/VERSION
index a3c62a0..911a64f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 199
+PRERELEASE 200
PRERELEASE_PATCH 0
\ No newline at end of file