Version 2.10.0-57.0.dev
Merge commit 'ce494e791024936b30911bde38d6979fd458aece' into 'dev'
diff --git a/benchmarks/MD5/dart/md5.dart b/benchmarks/MD5/dart/md5.dart
new file mode 100644
index 0000000..30dd6d4
--- /dev/null
+++ b/benchmarks/MD5/dart/md5.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, 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:benchmark_harness/benchmark_harness.dart';
+import 'package:convert/convert.dart';
+import 'package:crypto/crypto.dart';
+
+const size = 8 * 1024;
+const expected = '6556112372898c69e1de0bf689d8db26';
+
+class MD5Bench extends BenchmarkBase {
+ List<int> data;
+
+ MD5Bench()
+ : data = List<int>.generate(size, (i) => i % 256, growable: false),
+ super('MD5');
+
+ @override
+ void warmup() {
+ for (int i = 0; i < 4; i++) {
+ run();
+ }
+ }
+
+ @override
+ void run() {
+ final hash = md5.convert(data);
+ if (hex.encode(hash.bytes) != expected) {
+ throw 'Incorrect HASH computed.';
+ }
+ }
+}
+
+void main() {
+ MD5Bench().report();
+}
diff --git a/benchmarks/MD5/dart2/md5.dart b/benchmarks/MD5/dart2/md5.dart
new file mode 100644
index 0000000..a65803d
--- /dev/null
+++ b/benchmarks/MD5/dart2/md5.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2020, 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:benchmark_harness/benchmark_harness.dart';
+import 'package:convert/convert.dart';
+import 'package:crypto/crypto.dart';
+
+const size = 8 * 1024;
+const expected = '6556112372898c69e1de0bf689d8db26';
+
+class MD5Bench extends BenchmarkBase {
+ List<int> data;
+
+ MD5Bench() : super('MD5') {
+ data = List<int>(size);
+ for (int i = 0; i < data.length; i++) {
+ data[i] = i % 256;
+ }
+ }
+
+ @override
+ void warmup() {
+ for (int i = 0; i < 4; i++) {
+ run();
+ }
+ }
+
+ @override
+ void run() {
+ final hash = md5.convert(data);
+ if (hex.encode(hash.bytes) != expected) {
+ throw 'Incorrect HASH computed.';
+ }
+ }
+}
+
+void main() {
+ MD5Bench().report();
+}
diff --git a/benchmarks/SHA1/dart/sha1.dart b/benchmarks/SHA1/dart/sha1.dart
new file mode 100644
index 0000000..713cb87
--- /dev/null
+++ b/benchmarks/SHA1/dart/sha1.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, 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:benchmark_harness/benchmark_harness.dart';
+import 'package:convert/convert.dart';
+import 'package:crypto/crypto.dart';
+
+const size = 8 * 1024;
+const expected = 'ecca46e1a1d0a6012713b09a870d84f695b6d9b0';
+
+class SHA1Bench extends BenchmarkBase {
+ List<int> data;
+
+ SHA1Bench()
+ : data = List<int>.generate(size, (i) => i % 256, growable: false),
+ super('SHA1');
+
+ @override
+ void warmup() {
+ for (int i = 0; i < 4; i++) {
+ run();
+ }
+ }
+
+ @override
+ void run() {
+ final hash = sha1.convert(data);
+ if (hex.encode(hash.bytes) != expected) {
+ throw 'Incorrect HASH computed.';
+ }
+ }
+}
+
+void main() {
+ SHA1Bench().report();
+}
diff --git a/benchmarks/SHA1/dart2/sha1.dart b/benchmarks/SHA1/dart2/sha1.dart
new file mode 100644
index 0000000..4ce65f5
--- /dev/null
+++ b/benchmarks/SHA1/dart2/sha1.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2020, 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:benchmark_harness/benchmark_harness.dart';
+import 'package:convert/convert.dart';
+import 'package:crypto/crypto.dart';
+
+const size = 8 * 1024;
+const expected = 'ecca46e1a1d0a6012713b09a870d84f695b6d9b0';
+
+class SHA1Bench extends BenchmarkBase {
+ List<int> data;
+
+ SHA1Bench() : super('SHA1') {
+ data = List<int>(size);
+ for (int i = 0; i < data.length; i++) {
+ data[i] = i % 256;
+ }
+ }
+
+ @override
+ void warmup() {
+ for (int i = 0; i < 4; i++) {
+ run();
+ }
+ }
+
+ @override
+ void run() {
+ final hash = sha1.convert(data);
+ if (hex.encode(hash.bytes) != expected) {
+ throw 'Incorrect HASH computed.';
+ }
+ }
+}
+
+void main() {
+ SHA1Bench().report();
+}
diff --git a/benchmarks/SHA256/dart/sha256.dart b/benchmarks/SHA256/dart/sha256.dart
new file mode 100644
index 0000000..83ae27d
--- /dev/null
+++ b/benchmarks/SHA256/dart/sha256.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, 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:benchmark_harness/benchmark_harness.dart';
+import 'package:convert/convert.dart';
+import 'package:crypto/crypto.dart';
+
+const size = 8 * 1024;
+const expected =
+ 'dc404a613fedaeb54034514bc6505f56b933caa5250299ba7d094377a51caa46';
+
+class SHA256Bench extends BenchmarkBase {
+ List<int> data;
+
+ SHA256Bench()
+ : data = List<int>.generate(size, (i) => i % 256, growable: false),
+ super('SHA256');
+
+ @override
+ void warmup() {
+ for (int i = 0; i < 4; i++) {
+ run();
+ }
+ }
+
+ @override
+ void run() {
+ final hash = sha256.convert(data);
+ if (hex.encode(hash.bytes) != expected) {
+ throw 'Incorrect HASH computed.';
+ }
+ }
+}
+
+void main() {
+ SHA256Bench().report();
+}
diff --git a/benchmarks/SHA256/dart2/sha256.dart b/benchmarks/SHA256/dart2/sha256.dart
new file mode 100644
index 0000000..c138387
--- /dev/null
+++ b/benchmarks/SHA256/dart2/sha256.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2020, 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:benchmark_harness/benchmark_harness.dart';
+import 'package:convert/convert.dart';
+import 'package:crypto/crypto.dart';
+
+const size = 8 * 1024;
+const expected =
+ 'dc404a613fedaeb54034514bc6505f56b933caa5250299ba7d094377a51caa46';
+
+class SHA256Bench extends BenchmarkBase {
+ List<int> data;
+
+ SHA256Bench() : super('SHA256') {
+ data = List<int>(size);
+ for (int i = 0; i < data.length; i++) {
+ data[i] = i % 256;
+ }
+ }
+
+ @override
+ void warmup() {
+ for (int i = 0; i < 4; i++) {
+ run();
+ }
+ }
+
+ @override
+ void run() {
+ final hash = sha256.convert(data);
+ if (hex.encode(hash.bytes) != expected) {
+ throw 'Incorrect HASH computed.';
+ }
+ }
+}
+
+void main() {
+ SHA256Bench().report();
+}
diff --git a/benchmarks/SkeletalAnimation/dart/SkeletalAnimation.dart b/benchmarks/SkeletalAnimation/dart/SkeletalAnimation.dart
new file mode 100644
index 0000000..adda3d3
--- /dev/null
+++ b/benchmarks/SkeletalAnimation/dart/SkeletalAnimation.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, 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.
+
+/// A Dart implementation of two computation kernels used for skeletal
+/// animation.
+
+import 'dart:typed_data';
+
+import 'package:benchmark_harness/benchmark_harness.dart';
+import 'package:vector_math/vector_math_operations.dart';
+
+void main() {
+ SkeletalAnimation().report();
+}
+
+class SkeletalAnimation extends BenchmarkBase {
+ SkeletalAnimation() : super('SkeletalAnimation');
+
+ final Float32List A = Float32List(16);
+ final Float32List B = Float32List(16);
+ final Float32List C = Float32List(16);
+ final Float32List D = Float32List(4);
+ final Float32List E = Float32List(4);
+
+ @override
+ void run() {
+ for (int i = 0; i < 100; i++) {
+ Matrix44Operations.multiply(C, 0, A, 0, B, 0);
+ Matrix44Operations.transform4(E, 0, A, 0, D, 0);
+ }
+ }
+}
diff --git a/benchmarks/SkeletalAnimation/dart2/SkeletalAnimation.dart b/benchmarks/SkeletalAnimation/dart2/SkeletalAnimation.dart
new file mode 100644
index 0000000..adda3d3
--- /dev/null
+++ b/benchmarks/SkeletalAnimation/dart2/SkeletalAnimation.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, 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.
+
+/// A Dart implementation of two computation kernels used for skeletal
+/// animation.
+
+import 'dart:typed_data';
+
+import 'package:benchmark_harness/benchmark_harness.dart';
+import 'package:vector_math/vector_math_operations.dart';
+
+void main() {
+ SkeletalAnimation().report();
+}
+
+class SkeletalAnimation extends BenchmarkBase {
+ SkeletalAnimation() : super('SkeletalAnimation');
+
+ final Float32List A = Float32List(16);
+ final Float32List B = Float32List(16);
+ final Float32List C = Float32List(16);
+ final Float32List D = Float32List(4);
+ final Float32List E = Float32List(4);
+
+ @override
+ void run() {
+ for (int i = 0; i < 100; i++) {
+ Matrix44Operations.multiply(C, 0, A, 0, B, 0);
+ Matrix44Operations.transform4(E, 0, A, 0, D, 0);
+ }
+ }
+}
diff --git a/benchmarks/SkeletalAnimationSIMD/dart/SkeletalAnimationSIMD.dart b/benchmarks/SkeletalAnimationSIMD/dart/SkeletalAnimationSIMD.dart
new file mode 100644
index 0000000..fc7727e
--- /dev/null
+++ b/benchmarks/SkeletalAnimationSIMD/dart/SkeletalAnimationSIMD.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, 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.
+
+/// A Dart implementation of two computation kernels used for skeletal
+/// animation. SIMD version.
+
+import 'dart:typed_data';
+
+import 'package:benchmark_harness/benchmark_harness.dart';
+import 'package:vector_math/vector_math_operations.dart';
+
+void main() {
+ SkeletalAnimationSIMD().report();
+}
+
+class SkeletalAnimationSIMD extends BenchmarkBase {
+ SkeletalAnimationSIMD() : super('SkeletalAnimationSIMD');
+
+ final Float32x4List A = Float32x4List(4);
+ final Float32x4List B = Float32x4List(4);
+ final Float32x4List C = Float32x4List(4);
+ final Float32x4List D = Float32x4List(1);
+ final Float32x4List E = Float32x4List(1);
+
+ @override
+ void run() {
+ for (int i = 0; i < 100; i++) {
+ Matrix44SIMDOperations.multiply(C, 0, A, 0, B, 0);
+ Matrix44SIMDOperations.transform4(E, 0, A, 0, D, 0);
+ }
+ }
+}
diff --git a/benchmarks/SkeletalAnimationSIMD/dart2/SkeletalAnimationSIMD.dart b/benchmarks/SkeletalAnimationSIMD/dart2/SkeletalAnimationSIMD.dart
new file mode 100644
index 0000000..fc7727e
--- /dev/null
+++ b/benchmarks/SkeletalAnimationSIMD/dart2/SkeletalAnimationSIMD.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, 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.
+
+/// A Dart implementation of two computation kernels used for skeletal
+/// animation. SIMD version.
+
+import 'dart:typed_data';
+
+import 'package:benchmark_harness/benchmark_harness.dart';
+import 'package:vector_math/vector_math_operations.dart';
+
+void main() {
+ SkeletalAnimationSIMD().report();
+}
+
+class SkeletalAnimationSIMD extends BenchmarkBase {
+ SkeletalAnimationSIMD() : super('SkeletalAnimationSIMD');
+
+ final Float32x4List A = Float32x4List(4);
+ final Float32x4List B = Float32x4List(4);
+ final Float32x4List C = Float32x4List(4);
+ final Float32x4List D = Float32x4List(1);
+ final Float32x4List E = Float32x4List(1);
+
+ @override
+ void run() {
+ for (int i = 0; i < 100; i++) {
+ Matrix44SIMDOperations.multiply(C, 0, A, 0, B, 0);
+ Matrix44SIMDOperations.transform4(E, 0, A, 0, D, 0);
+ }
+ }
+}
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index 391b46b..1e68c39 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -152,16 +152,11 @@
var file = message.filePath;
var offset = message.offset;
var length = message.length;
- var startLine = -1;
- var startColumn = -1;
- var lineInfo = result.session.getFile(file).lineInfo;
- if (lineInfo != null) {
- CharacterLocation lineLocation = lineInfo.getLocation(offset);
- if (lineLocation != null) {
- startLine = lineLocation.lineNumber;
- startColumn = lineLocation.columnNumber;
- }
- }
+
+ var lineLocation = result.lineInfo.getLocation(offset);
+ var startLine = lineLocation.lineNumber;
+ var startColumn = lineLocation.columnNumber;
+
return DiagnosticMessage(
message.message, Location(file, offset, length, startLine, startColumn));
}
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index b0b3a9cc..19a3d5f 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -1348,8 +1348,9 @@
DartType refineBinaryExpressionType(DartType leftType, TokenType operator,
DartType rightType, DartType currentType, MethodElement operatorElement) {
if (isNonNullableByDefault) {
- return _refineBinaryExpressionTypeNullSafe(
- leftType, operator, rightType, currentType);
+ if (operatorElement == null) return currentType;
+ return _refineNumericInvocationTypeNullSafe(
+ leftType, operatorElement, [rightType], currentType);
} else {
return _refineBinaryExpressionTypeLegacy(
leftType, operator, rightType, currentType);
@@ -1513,74 +1514,117 @@
return currentType;
}
- DartType _refineBinaryExpressionTypeNullSafe(DartType leftType,
- TokenType operator, DartType rightType, DartType currentType) {
- if (leftType is TypeParameterType && leftType.bound.isDartCoreNum) {
- if (rightType == leftType || rightType.isDartCoreInt) {
- if (operator == TokenType.PLUS ||
- operator == TokenType.MINUS ||
- operator == TokenType.STAR ||
- operator == TokenType.PLUS_EQ ||
- operator == TokenType.MINUS_EQ ||
- operator == TokenType.STAR_EQ ||
- operator == TokenType.PLUS_PLUS ||
- operator == TokenType.MINUS_MINUS) {
- return promoteToNonNull(leftType as TypeImpl);
- }
- }
- if (rightType.isDartCoreDouble) {
- if (operator == TokenType.PLUS ||
- operator == TokenType.MINUS ||
- operator == TokenType.STAR ||
- operator == TokenType.SLASH) {
- InterfaceTypeImpl doubleType = typeProvider.doubleType;
- return promoteToNonNull(doubleType);
- }
- }
- return currentType;
- }
- // bool
- if (operator == TokenType.AMPERSAND_AMPERSAND ||
- operator == TokenType.BAR_BAR ||
- operator == TokenType.EQ_EQ ||
- operator == TokenType.BANG_EQ) {
- return promoteToNonNull(typeProvider.boolType);
- }
- if (leftType.isDartCoreInt) {
- // int op double
- if (operator == TokenType.MINUS ||
- operator == TokenType.PERCENT ||
- operator == TokenType.PLUS ||
- operator == TokenType.STAR ||
- operator == TokenType.MINUS_EQ ||
- operator == TokenType.PERCENT_EQ ||
- operator == TokenType.PLUS_EQ ||
- operator == TokenType.STAR_EQ) {
- if (rightType.isDartCoreDouble) {
- InterfaceTypeImpl doubleType = typeProvider.doubleType;
- return promoteToNonNull(doubleType);
- }
- }
- // int op int
- if (operator == TokenType.MINUS ||
- operator == TokenType.PERCENT ||
- operator == TokenType.PLUS ||
- operator == TokenType.STAR ||
- operator == TokenType.TILDE_SLASH ||
- operator == TokenType.MINUS_EQ ||
- operator == TokenType.PERCENT_EQ ||
- operator == TokenType.PLUS_EQ ||
- operator == TokenType.STAR_EQ ||
- operator == TokenType.TILDE_SLASH_EQ ||
- operator == TokenType.PLUS_PLUS ||
- operator == TokenType.MINUS_MINUS) {
- if (rightType.isDartCoreInt) {
- InterfaceTypeImpl intType = typeProvider.intType;
- return promoteToNonNull(intType);
+ DartType _refineNumericInvocationTypeNullSafe(
+ DartType targetType,
+ MethodElement methodElement,
+ List<DartType> argumentTypes,
+ DartType currentType) {
+ // Let e be an expression of one of the forms e1 + e2, e1 - e2, e1 * e2,
+ // e1 % e2 or e1.remainder(e2)...
+ if (const {'+', '-', '*', '%', 'remainder'}.contains(methodElement.name)) {
+ // ...where the static type of e1 is a non-Never type T and T <: num...
+ // Notes:
+ // - We don't have to check for Never because if T is Never, the method
+ // element will fail to resolve so we'll never reach here.
+ // - We actually check against `num?` rather than `num`. It's equivalent
+ // from the standpoint of correctness (since it's illegal to call these
+ // methods on nullable types, and that's checked for elsewhere), but
+ // better from the standpoint of error recovery (since it allows e.g.
+ // `int? + int` to resolve to `int` rather than `num`).
+ var t = targetType;
+ assert(!t.isBottom);
+ var numType = typeProvider.numType;
+ var numTypeQuestion = makeNullable(numType as InterfaceTypeImpl);
+ if (isSubtypeOf(t, numTypeQuestion)) {
+ // ...and where the static type of e2 is S and S is assignable to num.
+ // (Note: we don't have to check that S is assignable to num because
+ // this is required by the signature of the method.)
+ if (argumentTypes.length == 1) {
+ var s = argumentTypes[0];
+ // Then:
+ // - If T <: double then the static type of e is double. This includes
+ // S being dynamic or Never.
+ // (Note: as above, we check against `double?` because it's equivalent
+ // and leads to better error recovery.)
+ var doubleType = typeProvider.doubleType;
+ var doubleTypeQuestion =
+ makeNullable(doubleType as InterfaceTypeImpl);
+ if (isSubtypeOf(t, doubleTypeQuestion)) {
+ return doubleType;
+ }
+ // - If S <: double and not S <: Never, then the static type of e is
+ // double.
+ // (Again, we check against `double?` for error recovery.)
+ if (!s.isBottom && isSubtypeOf(s, doubleTypeQuestion)) {
+ return doubleType;
+ }
+ // - If T <: int, S <: int and not S <: Never, then the static type of
+ // e is int.
+ // (As above, we check against `int?` for error recovery.)
+ var intType = typeProvider.intType;
+ var intTypeQuestion = makeNullable(intType as InterfaceTypeImpl);
+ if (!s.isBottom &&
+ isSubtypeOf(t, intTypeQuestion) &&
+ isSubtypeOf(s, intTypeQuestion)) {
+ return intType;
+ }
+ // - Otherwise the static type of e is num.
+ return numType;
}
}
}
- // default
+ // Let e be a normal invocation of the form e1.clamp(e2, e3)...
+ if (methodElement.name == 'clamp') {
+ // ...where the static types of e1, e2 and e3 are T1, T2 and T3
+ // respectively...
+ var t1 = targetType;
+ if (argumentTypes.length == 2) {
+ var t2 = argumentTypes[0];
+ var t3 = argumentTypes[1];
+ // ...and where T1, T2, and T3 are all non-Never subtypes of num.
+ // (Note: we actually check against `num?` rather than `num`. It's
+ // equivalent from the standpoint of correctness (since it's illegal to
+ // call `num.clamp` on a nullable type or to pass it a nullable type
+ // as an argument, and that's checked for elsewhere), but better from
+ // the standpoint of error recovery (since it allows e.g.
+ // `int?.clamp(int, int)` to resolve to `int` rather than `num`).
+ var numType = typeProvider.numType;
+ var numTypeQuestion = makeNullable(numType as InterfaceTypeImpl);
+ if (!t1.isBottom &&
+ isSubtypeOf(t1, numTypeQuestion) &&
+ !t2.isBottom &&
+ isSubtypeOf(t2, numTypeQuestion) &&
+ !t3.isBottom &&
+ isSubtypeOf(t3, numTypeQuestion)) {
+ // Then:
+ // - If T1, T2 and T3 are all subtypes of int, the static type of e is
+ // int.
+ // (Note: as above, we check against `int?` because it's equivalent
+ // and leads to better error recovery.)
+ var intType = typeProvider.intType;
+ var intTypeQuestion = makeNullable(intType as InterfaceTypeImpl);
+ if (isSubtypeOf(t1, intTypeQuestion) &&
+ isSubtypeOf(t2, intTypeQuestion) &&
+ isSubtypeOf(t3, intTypeQuestion)) {
+ return intType;
+ }
+ // If T1, T2 and T3 are all subtypes of double, the static type of e
+ // is double.
+ // (As above, we check against `double?` for error recovery.)
+ var doubleType = typeProvider.doubleType;
+ var doubleTypeQuestion =
+ makeNullable(doubleType as InterfaceTypeImpl);
+ if (isSubtypeOf(t1, doubleTypeQuestion) &&
+ isSubtypeOf(t2, doubleTypeQuestion) &&
+ isSubtypeOf(t3, doubleTypeQuestion)) {
+ return doubleType;
+ }
+ // Otherwise the static type of e is num.
+ return numType;
+ }
+ }
+ }
+ // No special rules apply.
return currentType;
}
}
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index 7e2636a..fe58576 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -117,7 +117,13 @@
currentClassElement,
getterName,
);
- overriddenGetters ??= const [];
+ if (overriddenGetters != null) {
+ overriddenGetters = overriddenGetters.where((e) {
+ return e is PropertyAccessorElement && e.isGetter;
+ }).toList();
+ } else {
+ overriddenGetters = const [];
+ }
var setterName = Name(elementLibraryUri, '$elementName=');
var overriddenSetters = inheritance.getOverridden2(
diff --git a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
index 33ce9bf..482672b 100644
--- a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
@@ -2,7 +2,9 @@
// 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/src/dart/error/hint_codes.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'context_collection_resolution.dart';
@@ -115,6 +117,91 @@
);
}
+ test_minus_int_double() async {
+ await assertNoErrorsInCode(r'''
+f(int a, double b) {
+ a - b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a - b'),
+ element: elementMatcher(
+ numElement.getMethod('-'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'double',
+ );
+ }
+
+ test_minus_int_int() async {
+ await assertNoErrorsInCode(r'''
+f(int a, int b) {
+ a - b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a - b'),
+ element: elementMatcher(
+ numElement.getMethod('-'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'int',
+ );
+ }
+
+ test_mod_int_double() async {
+ await assertNoErrorsInCode(r'''
+f(int a, double b) {
+ a % b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a % b'),
+ element: elementMatcher(
+ numElement.getMethod('%'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'double',
+ );
+ }
+
+ test_mod_int_int() async {
+ await assertNoErrorsInCode(r'''
+f(int a, int b) {
+ a % b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a % b'),
+ element: elementMatcher(
+ numElement.getMethod('%'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'int',
+ );
+ }
+
+ test_plus_double_dynamic() async {
+ await assertNoErrorsInCode(r'''
+f(double a, dynamic b) {
+ a + b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a + b'),
+ element: elementMatcher(
+ doubleElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'double',
+ );
+ }
+
test_plus_int_double() async {
await assertNoErrorsInCode(r'''
f(int a, double b) {
@@ -132,6 +219,23 @@
);
}
+ test_plus_int_dynamic() async {
+ await assertNoErrorsInCode(r'''
+f(int a, dynamic b) {
+ a + b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a + b'),
+ element: elementMatcher(
+ numElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'num',
+ );
+ }
+
test_plus_int_int() async {
await assertNoErrorsInCode(r'''
f(int a, int b) {
@@ -149,6 +253,124 @@
);
}
+ test_plus_int_int_target_rewritten() async {
+ await assertNoErrorsInCode('''
+f(int Function() a, int b) {
+ a() + b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a() + b'),
+ element: elementMatcher(
+ numElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'int',
+ );
+ }
+
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/43114')
+ test_plus_int_int_via_extension_explicit() async {
+ await assertNoErrorsInCode('''
+extension E on int {
+ String operator+(int other) => '';
+}
+f(int a, int b) {
+ E(a) + b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('E(a) + b'),
+ element: elementMatcher(
+ findElement.method('+', of: 'E'),
+ isLegacy: false,
+ ),
+ type: 'String',
+ );
+ }
+
+ test_plus_int_num() async {
+ await assertNoErrorsInCode(r'''
+f(int a, num b) {
+ a + b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a + b'),
+ element: elementMatcher(
+ numElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'num',
+ );
+ }
+
+ test_plus_other_double() async {
+ await assertNoErrorsInCode('''
+abstract class A {
+ String operator+(double other);
+}
+f(A a, double b) {
+ a + b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a + b'),
+ element: elementMatcher(
+ findElement.method('+', of: 'A'),
+ isLegacy: false,
+ ),
+ type: 'String',
+ );
+ }
+
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/43114')
+ test_plus_other_int_via_extension_explicit() async {
+ await assertNoErrorsInCode('''
+class A {}
+extension E on A {
+ String operator+(int other) => '';
+}
+f(A a, int b) {
+ E(a) + b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('E(a) + b'),
+ element: elementMatcher(
+ findElement.method('+', of: 'E'),
+ isLegacy: false,
+ ),
+ type: 'String',
+ );
+ }
+
+ test_plus_other_int_via_extension_implicit() async {
+ await assertNoErrorsInCode('''
+class A {}
+extension E on A {
+ String operator+(int other) => '';
+}
+f(A a, int b) {
+ a + b;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('a + b'),
+ element: elementMatcher(
+ findElement.method('+', of: 'E'),
+ isLegacy: false,
+ ),
+ type: 'String',
+ );
+ }
+
test_receiverTypeParameter_bound_dynamic() async {
await assertNoErrorsInCode(r'''
f<T extends dynamic>(T a) {
@@ -299,4 +521,32 @@
type: 'int?',
);
}
+
+ test_plus_int_never() async {
+ await assertErrorsInCode('''
+f(int a, Never b) {
+ a + b;
+}
+''', []);
+
+ assertBinaryExpression(findNode.binary('a + b'),
+ element: numElement.getMethod('+'), type: 'num');
+ }
+
+ test_plus_never_int() async {
+ await assertErrorsInCode(r'''
+f(Never a, int b) {
+ a + b;
+}
+''', [
+ error(HintCode.RECEIVER_OF_TYPE_NEVER, 22, 1),
+ error(HintCode.DEAD_CODE, 26, 2),
+ ]);
+
+ assertBinaryExpression(
+ findNode.binary('a + b'),
+ element: isNull,
+ type: 'Never',
+ );
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
index 4cf9ec2..0ea4180 100644
--- a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
@@ -106,7 +106,7 @@
numPlusElement,
isLegacy: isNullSafetySdkAndLegacyLibrary,
),
- type: 'num',
+ type: typeToStringWithNullability ? 'double' : 'num',
);
assertParameterElement(
assignment.rightHandSide,
@@ -322,7 +322,7 @@
assertAssignment(
assignment,
operatorElement: numPlusElement,
- type: 'num?',
+ type: 'double?',
);
assertParameterElement(
assignment.rightHandSide,
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart
index a4d9df5..ac4be3b 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart
@@ -386,6 +386,20 @@
_assertGetterTypeDynamic(foo);
}
+ test_invalid_field_overrides_method() async {
+ await resolveTestCode('''
+abstract class A {
+ List<T> foo<T>() {}
+}
+
+class B implements A {
+ var foo = <String, int>{};
+}
+''');
+ var foo = findElement.field('foo', of: 'B');
+ _assertFieldType(foo, 'Map<String, int>');
+ }
+
test_invalid_inheritanceCycle() async {
await resolveTestCode('''
class A extends C {}
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index dfd1530..1fa1328 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -34,6 +34,23 @@
);
}
+ test_inc_double() async {
+ await assertNoErrorsInCode(r'''
+f(double x) {
+ x++;
+}
+''');
+
+ assertPostfixExpression(
+ findNode.postfix('x++'),
+ element: elementMatcher(
+ doubleElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'double',
+ );
+ }
+
test_inc_localVariable() async {
await assertNoErrorsInCode(r'''
f(int x) {
@@ -51,6 +68,23 @@
);
}
+ test_inc_num() async {
+ await assertNoErrorsInCode(r'''
+f(num x) {
+ x++;
+}
+''');
+
+ assertPostfixExpression(
+ findNode.postfix('x++'),
+ element: elementMatcher(
+ numElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'num',
+ );
+ }
+
test_inc_property_differentTypes() async {
await assertNoErrorsInCode(r'''
int get x => 0;
diff --git a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
index 2cb17f3..2900aa3 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
@@ -90,6 +90,23 @@
);
}
+ test_plusPlus_double() async {
+ await assertNoErrorsInCode(r'''
+f(double x) {
+ ++x;
+}
+''');
+
+ assertPrefixExpression(
+ findNode.prefix('++x'),
+ element: elementMatcher(
+ doubleElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'double',
+ );
+ }
+
test_plusPlus_extensionOverride() async {
await assertErrorsInCode(r'''
class C {}
@@ -152,6 +169,23 @@
);
}
+ test_plusPlus_num() async {
+ await assertNoErrorsInCode(r'''
+f(num x) {
+ ++x;
+}
+''');
+
+ assertPrefixExpression(
+ findNode.prefix('++x'),
+ element: elementMatcher(
+ numElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'num',
+ );
+ }
+
test_tilde_int_localVariable() async {
await assertNoErrorsInCode(r'''
f(int x) {
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index e6f5143..2c2acf8 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -858,11 +858,11 @@
}
}
- _ElementMatcher _elementMatcher(Object elementOrMatcher) {
+ Matcher _elementMatcher(Object elementOrMatcher) {
if (elementOrMatcher is Element) {
return _ElementMatcher(this, declaration: elementOrMatcher);
} else {
- return elementOrMatcher;
+ return wrapMatcher(elementOrMatcher);
}
}
diff --git a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
index 1abf518..bf80618 100644
--- a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
@@ -3,6 +3,8 @@
ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1659|7|5|Superinterfaces don't have a valid override for '>>': JSNumber.>> (num Function(num)), int.>> (int Function(int)).
ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1659|7|5|Superinterfaces don't have a valid override for '\|': JSNumber.\| (num Function(num)), int.\| (int Function(int)).
ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1659|7|5|Superinterfaces don't have a valid override for '^': JSNumber.^ (num Function(num)), int.^ (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_runtime/lib/interceptors.dart|1514|14|45|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
+ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_runtime/lib/interceptors.dart|1516|14|45|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1676|28|1|The operator '&' isn't defined for the type 'JSInt'.
ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1678|27|1|The operator '&' isn't defined for the type 'JSInt'.
ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1681|17|1|The operator '&' isn't defined for the type 'JSInt'.
diff --git a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
index 004f021..b77ed3f 100644
--- a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
@@ -2,6 +2,9 @@
ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|7913|5|97|Const constructors can't throw exceptions.
ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|939|5|95|Const constructors can't throw exceptions.
ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|972|5|94|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|INVALID_ASSIGNMENT|lib/_internal/js_dev_runtime/private/interceptors.dart|1348|18|27|A value of type 'double' can't be assigned to a variable of type 'int'.
+ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_dev_runtime/private/interceptors.dart|1215|14|38|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
+ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_dev_runtime/private/interceptors.dart|1217|14|38|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|3723|3|5|Only redirecting factory constructors can be declared to be 'const'.
ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|7911|3|5|Only redirecting factory constructors can be declared to be 'const'.
ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|937|3|5|Only redirecting factory constructors can be declared to be 'const'.
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 930cd9a..37d7bb3 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -1125,7 +1125,7 @@
}
''');
var assignment = findNode.assignment('+=');
- visitSubexpression(assignment, 'T',
+ visitSubexpression(assignment, 'num',
changes: {assignment: isNullableSource});
}
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index c30ee49..6ad304e 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -12,9 +12,9 @@
#include <stdint.h>
#include <fuchsia/deprecatedtimezone/cpp/fidl.h>
-#include <lib/async/default.h>
-#include <lib/async-loop/loop.h>
#include <lib/async-loop/default.h>
+#include <lib/async-loop/loop.h>
+#include <lib/async/default.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/sys/cpp/service_directory.h>
@@ -22,6 +22,7 @@
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
+#include <zircon/time.h>
#include <zircon/types.h>
#include "platform/assert.h"
@@ -115,6 +116,15 @@
return true;
}
+int64_t GetCurrentTimeNanos() {
+ struct timespec ts;
+ if (timespec_get(&ts, TIME_UTC) == 0) {
+ FATAL("timespec_get failed");
+ return 0;
+ }
+ return zx_time_add_duration(ZX_SEC(ts.tv_sec), ZX_NSEC(ts.tv_nsec));
+}
+
} // namespace
namespace dart {
@@ -177,21 +187,18 @@
int OS::GetLocalTimeZoneAdjustmentInSeconds() {
int32_t local_offset, dst_offset;
- zx_time_t now = 0;
- zx_clock_get(ZX_CLOCK_UTC, &now);
- zx_status_t status = GetLocalAndDstOffsetInSeconds(
- now / ZX_SEC(1), &local_offset, &dst_offset);
+ int64_t now_seconds = GetCurrentTimeNanos() / ZX_SEC(1);
+ zx_status_t status =
+ GetLocalAndDstOffsetInSeconds(now_seconds, &local_offset, &dst_offset);
return status == ZX_OK ? local_offset : 0;
}
int64_t OS::GetCurrentTimeMillis() {
- return GetCurrentTimeMicros() / 1000;
+ return GetCurrentTimeNanos() / ZX_MSEC(1);
}
int64_t OS::GetCurrentTimeMicros() {
- zx_time_t now = 0;
- zx_clock_get(ZX_CLOCK_UTC, &now);
- return now / kNanosecondsPerMicrosecond;
+ return GetCurrentTimeNanos() / ZX_USEC(1);
}
int64_t OS::GetCurrentMonotonicTicks() {
diff --git a/tests/language/inference/dynamic_nullable_test.dart b/tests/language/inference/dynamic_nullable_test.dart
new file mode 100644
index 0000000..6bcb121
--- /dev/null
+++ b/tests/language/inference/dynamic_nullable_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, 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:expect/expect.dart";
+
+// Tests that inference can solve for T? ~ dynamic or void.
+
+class C<T extends Object> {
+ final T? value;
+ const C(this.value);
+ C.list(List<T?> list) : value = list.first;
+ void set nonNullValue(T value) {}
+}
+
+List<T> foo<T extends Object>(T? value) => [value!];
+
+List<T> bar<T extends Object>(List<T?> value) => [
+ for (var element in value)
+ if (element != null) element
+ ];
+
+extension Ext<T extends Object> on List<T?> {
+ List<T> whereNotNull() => [
+ for (var element in this)
+ if (element != null) element
+ ];
+}
+
+main() {
+ {
+ // Testing for dynamic.
+ const dynamic o = 42;
+
+ var c = const C(o);
+ var f = foo(o);
+ var l = [o].whereNotNull();
+
+ c.expectStaticType<Exactly<C<Object>>>();
+ Expect.type<C<Object>>(c); // Run-time type is subtype of C<Object>.
+ c.nonNullValue = Object(); // And supertype.
+
+ f.expectStaticType<Exactly<List<Object>>>();
+ Expect.type<List<Object>>(f); // Run-time type is subtype of List<Object>.
+ f[0] = Object(); // And supertype.
+
+ l.expectStaticType<Exactly<List<Object>>>();
+ Expect.type<List<Object>>(l); // Run-time type is subtype of List<Object>.
+ l[0] = Object(); // And supertype.
+ }
+
+ {
+ // Testing for void
+ List<void> o = <void>[42];
+
+ var c = C.list(o);
+ var f = bar(o);
+ var l = o.whereNotNull;
+
+ c.expectStaticType<Exactly<C<Object>>>();
+ Expect.type<C<Object>>(c); // Run-time type is subtype of C<Object>.
+ c.nonNullValue = Object(); // And supertype.
+
+ f.expectStaticType<Exactly<List<Object>>>();
+ Expect.type<List<Object>>(f); // Run-time type is subtype of List<Object>.
+ f[0] = Object(); // And supertype.
+
+ l.expectStaticType<Exactly<List<Object>>>();
+ Expect.type<List<Object>>(l); // Run-time type is subtype of List<Object>.
+ l[0] = Object(); // And supertype.
+ }
+}
+
+// Captures and checks static type of expression.
+extension TypeCheck<T> on T {
+ T expectStaticType<R extends Exactly<T>>() {
+ return this;
+ }
+}
+
+typedef Exactly<T> = T Function(T);
diff --git a/tools/VERSION b/tools/VERSION
index 6978f1f..befae4f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 56
+PRERELEASE 57
PRERELEASE_PATCH 0
\ No newline at end of file