Version 2.11.0-184.0.dev
Merge commit '3efed861472346c54e571d9bce61c0c791605ded' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index f088ab2..c38172a 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -755,6 +755,56 @@
return false;
}
+ /// A dynamic bounded type is either `dynamic` itself, or a type variable
+ /// whose bound is dynamic bounded, or an intersection (promoted type
+ /// parameter type) whose second operand is dynamic bounded.
+ bool isDynamicBounded(DartType type) {
+ if (identical(type, DynamicTypeImpl.instance)) {
+ return true;
+ }
+
+ if (type is TypeParameterTypeImpl) {
+ var bound = type.element.bound;
+ if (bound != null && isDynamicBounded(bound)) {
+ return true;
+ }
+
+ var promotedBound = type.promotedBound;
+ if (promotedBound != null && isDynamicBounded(promotedBound)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// A function bounded type is either `Function` itself, or a type variable
+ /// whose bound is function bounded, or an intersection (promoted type
+ /// parameter type) whose second operand is function bounded.
+ bool isFunctionBounded(DartType type) {
+ if (type is FunctionType) {
+ return type.nullabilitySuffix != NullabilitySuffix.question;
+ }
+
+ if (type is InterfaceType && type.isDartCoreFunction) {
+ return type.nullabilitySuffix != NullabilitySuffix.question;
+ }
+
+ if (type is TypeParameterTypeImpl) {
+ var bound = type.element.bound;
+ if (bound != null && isFunctionBounded(bound)) {
+ return true;
+ }
+
+ var promotedBound = type.promotedBound;
+ if (promotedBound != null && isFunctionBounded(promotedBound)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/// Defines an (almost) total order on bottom and `Null` types. This does not
/// currently consistently order two different type variables with the same
/// bound.
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 919f54d..2344a75 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -136,27 +136,14 @@
}
DartType receiverType = receiver.staticType;
- receiverType = _resolveTypeParameter(receiverType);
- if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
- _typeSystem.isNonNullableByDefault) {
- receiverType = _typeSystem.promoteToNonNull(receiverType);
- }
-
- if (receiverType is InterfaceType) {
- _resolveReceiverInterfaceType(
- node, receiver, receiverType, nameNode, name);
+ if (_typeSystem.isDynamicBounded(receiverType)) {
+ _resolveReceiverDynamicBounded(node);
return;
}
- if (receiverType is DynamicTypeImpl) {
- _resolveReceiverDynamic(node);
- return;
- }
-
- if (receiverType is FunctionType) {
- _resolveReceiverFunctionType(
- node, receiver, receiverType, nameNode, name);
+ if (receiverType is NeverTypeImpl) {
+ _resolveReceiverNever(node, receiver, receiverType);
return;
}
@@ -165,10 +152,25 @@
return;
}
- if (receiverType is NeverTypeImpl) {
- _resolveReceiverNever(node, receiver, receiverType);
+ if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
+ _typeSystem.isNonNullableByDefault) {
+ receiverType = _typeSystem.promoteToNonNull(receiverType);
+ }
+
+ if (_typeSystem.isFunctionBounded(receiverType)) {
+ _resolveReceiverFunctionBounded(
+ node, receiver, receiverType, nameNode, name);
return;
}
+
+ _resolveReceiverType(
+ node: node,
+ receiver: receiver,
+ receiverType: receiverType,
+ nameNode: nameNode,
+ name: name,
+ receiverErrorNode: receiver,
+ );
}
bool _isCoreFunction(DartType type) {
@@ -382,7 +384,7 @@
_setResolution(node, member.type);
}
- void _resolveReceiverDynamic(MethodInvocationImpl node) {
+ void _resolveReceiverDynamicBounded(MethodInvocation node) {
var nameNode = node.methodName;
var objectElement = _typeSystem.typeProvider.objectElement;
@@ -411,8 +413,13 @@
node.argumentList.accept(_resolver);
}
- void _resolveReceiverFunctionType(MethodInvocation node, Expression receiver,
- FunctionType receiverType, SimpleIdentifier nameNode, String name) {
+ void _resolveReceiverFunctionBounded(
+ MethodInvocation node,
+ Expression receiver,
+ DartType receiverType,
+ SimpleIdentifier nameNode,
+ String name,
+ ) {
if (name == FunctionElement.CALL_METHOD_NAME) {
_setResolution(node, receiverType);
// TODO(scheglov) Replace this with using FunctionType directly.
@@ -432,18 +439,6 @@
);
}
- void _resolveReceiverInterfaceType(MethodInvocation node, Expression receiver,
- InterfaceType receiverType, SimpleIdentifier nameNode, String name) {
- _resolveReceiverType(
- node: node,
- receiver: receiver,
- receiverType: receiverType,
- nameNode: nameNode,
- name: name,
- receiverErrorNode: receiver,
- );
- }
-
void _resolveReceiverNever(
MethodInvocation node,
Expression receiver,
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index 08ce229..48c20cd 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -328,7 +328,6 @@
}
var targetType = target.staticType;
- targetType = _resolveTypeParameter(targetType);
if (targetType.isVoid) {
_errorReporter.reportErrorForNode(
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
index f9ae35c..dcf0d9d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
@@ -71,9 +70,9 @@
_nameErrorEntity = nameErrorEntity;
_resetResult();
- receiverType = _resolveTypeParameter(receiverType);
+ receiverType = _resolveTypeParameter(receiverType, ifLegacy: true);
- if (receiverType is DynamicTypeImpl) {
+ if (_typeSystem.isDynamicBounded(receiverType)) {
_lookupInterfaceType(_typeProvider.objectType);
_needsGetterError = false;
_needsSetterError = false;
@@ -100,29 +99,33 @@
_reportedSetterError = true;
// Recovery, get some resolution.
+ receiverType = _resolveTypeParameter(receiverType, ifNullSafe: true);
if (receiverType is InterfaceType) {
_lookupInterfaceType(receiverType);
}
return _toResult();
} else {
- if (receiverType is InterfaceType) {
- _lookupInterfaceType(receiverType);
+ var receiverTypeResolved =
+ _resolveTypeParameter(receiverType, ifNullSafe: true);
+
+ if (receiverTypeResolved is InterfaceType) {
+ _lookupInterfaceType(receiverTypeResolved);
if (_hasGetterOrSetter) {
return _toResult();
}
- if (receiverType.isDartCoreFunction && _name == 'call') {
+ if (receiverTypeResolved.isDartCoreFunction && _name == 'call') {
_needsGetterError = false;
_needsSetterError = false;
return _toResult();
}
}
- if (receiverType is FunctionType && _name == 'call') {
+ if (receiverTypeResolved is FunctionType && _name == 'call') {
return _toResult();
}
- if (receiverType is NeverType) {
+ if (receiverTypeResolved is NeverType) {
_lookupInterfaceType(_typeProvider.objectType);
_needsGetterError = false;
_needsSetterError = false;
@@ -200,8 +203,22 @@
/// If the given [type] is a type parameter, replace it with its bound.
/// Otherwise, return the original type.
- DartType _resolveTypeParameter(DartType type) {
- return type?.resolveToBound(_typeProvider.objectType);
+ ///
+ /// See https://github.com/dart-lang/language/issues/1182
+ /// There was a bug in the analyzer (and CFE) - we were always resolving
+ /// types to bounds before searching for a property. But extensions should
+ /// be applied to original types. Fixing this would be a breaking change,
+ /// so we fix it together with null safety.
+ DartType _resolveTypeParameter(
+ DartType type, {
+ bool ifLegacy = false,
+ bool ifNullSafe = false,
+ }) {
+ if (_typeSystem.isNonNullableByDefault ? ifNullSafe : ifLegacy) {
+ return type?.resolveToBound(_typeProvider.objectType);
+ } else {
+ return type;
+ }
}
ResolutionResult _toResult() {
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index f59885f..6efd3dd 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -22,6 +22,7 @@
import 'subtype_test.dart' as subtype;
import 'top_merge_test.dart' as top_merge;
import 'type_algebra_test.dart' as type_algebra;
+import 'type_bounded_test.dart' as type_bounded;
import 'type_constraint_gatherer_test.dart' as type_constraint_gatherer;
import 'type_parameter_element_test.dart' as type_parameter_element;
import 'type_visitor_test.dart' as type_visitor;
@@ -48,6 +49,7 @@
subtype.main();
top_merge.main();
type_algebra.main();
+ type_bounded.main();
type_constraint_gatherer.main();
type_parameter_element.main();
type_visitor.main();
diff --git a/pkg/analyzer/test/src/dart/element/type_bounded_test.dart b/pkg/analyzer/test/src/dart/element/type_bounded_test.dart
new file mode 100644
index 0000000..e851ca6
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/type_bounded_test.dart
@@ -0,0 +1,240 @@
+// 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:analyzer/dart/element/type.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/type_system_test.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(DynamicBoundedTest);
+ defineReflectiveTests(FunctionBoundedTest);
+ });
+}
+
+@reflectiveTest
+class DynamicBoundedTest extends AbstractTypeSystemNullSafetyTest {
+ test_dynamic() {
+ _assertDynamicBounded(dynamicNone);
+ }
+
+ test_dynamic_typeParameter_hasBound_dynamic() {
+ var T = typeParameter('T', bound: dynamicNone);
+
+ _assertDynamicBounded(
+ typeParameterTypeNone(T),
+ );
+ }
+
+ test_dynamic_typeParameter_hasBound_notDynamic() {
+ var T = typeParameter('T', bound: intNone);
+
+ _assertNotDynamicBounded(
+ typeParameterTypeNone(T),
+ );
+ }
+
+ test_dynamic_typeParameter_hasPromotedBound_dynamic() {
+ var T = typeParameter('T');
+
+ _assertDynamicBounded(
+ typeParameterTypeNone(T, promotedBound: dynamicNone),
+ );
+ }
+
+ test_dynamic_typeParameter_hasPromotedBound_notDynamic() {
+ var T = typeParameter('T');
+
+ _assertNotDynamicBounded(
+ typeParameterTypeNone(T, promotedBound: intNone),
+ );
+ }
+
+ test_dynamic_typeParameter_noBound() {
+ var T = typeParameter('T');
+
+ _assertNotDynamicBounded(
+ typeParameterTypeNone(T),
+ );
+ }
+
+ test_functionType() {
+ _assertNotDynamicBounded(
+ functionTypeNone(returnType: voidNone),
+ );
+
+ _assertNotDynamicBounded(
+ functionTypeNone(returnType: dynamicNone),
+ );
+ }
+
+ test_interfaceType() {
+ _assertNotDynamicBounded(intNone);
+ _assertNotDynamicBounded(intQuestion);
+ _assertNotDynamicBounded(intStar);
+ }
+
+ test_never() {
+ _assertNotDynamicBounded(neverNone);
+ _assertNotDynamicBounded(neverQuestion);
+ _assertNotDynamicBounded(neverStar);
+ }
+
+ test_void() {
+ _assertNotDynamicBounded(voidNone);
+ }
+
+ void _assertDynamicBounded(DartType type) {
+ expect(typeSystem.isDynamicBounded(type), isTrue);
+ }
+
+ void _assertNotDynamicBounded(DartType type) {
+ expect(typeSystem.isDynamicBounded(type), isFalse);
+ }
+}
+
+@reflectiveTest
+class FunctionBoundedTest extends AbstractTypeSystemNullSafetyTest {
+ test_dynamic() {
+ _assertNotFunctionBounded(dynamicNone);
+ }
+
+ test_dynamic_typeParameter_hasBound_functionType_none() {
+ var T = typeParameter(
+ 'T',
+ bound: functionTypeNone(returnType: voidNone),
+ );
+
+ _assertFunctionBounded(
+ typeParameterTypeNone(T),
+ );
+ }
+
+ test_dynamic_typeParameter_hasBound_functionType_question() {
+ var T = typeParameter(
+ 'T',
+ bound: functionTypeQuestion(returnType: voidNone),
+ );
+
+ _assertNotFunctionBounded(
+ typeParameterTypeNone(T),
+ );
+ }
+
+ test_dynamic_typeParameter_hasBound_functionType_star() {
+ var T = typeParameter(
+ 'T',
+ bound: functionTypeStar(returnType: voidNone),
+ );
+
+ _assertFunctionBounded(
+ typeParameterTypeStar(T),
+ );
+ }
+
+ test_dynamic_typeParameter_hasBound_notFunction() {
+ var T = typeParameter('T', bound: intNone);
+
+ _assertNotFunctionBounded(
+ typeParameterTypeNone(T),
+ );
+ }
+
+ test_dynamic_typeParameter_hasPromotedBound_functionType_none() {
+ var T = typeParameter('T');
+
+ _assertFunctionBounded(
+ typeParameterTypeNone(
+ T,
+ promotedBound: functionTypeNone(
+ returnType: voidNone,
+ ),
+ ),
+ );
+ }
+
+ test_dynamic_typeParameter_hasPromotedBound_functionType_question() {
+ var T = typeParameter('T');
+
+ _assertNotFunctionBounded(
+ typeParameterTypeStar(
+ T,
+ promotedBound: functionTypeQuestion(
+ returnType: voidNone,
+ ),
+ ),
+ );
+ }
+
+ test_dynamic_typeParameter_hasPromotedBound_functionType_star() {
+ var T = typeParameter('T');
+
+ _assertFunctionBounded(
+ typeParameterTypeStar(
+ T,
+ promotedBound: functionTypeStar(
+ returnType: voidNone,
+ ),
+ ),
+ );
+ }
+
+ test_dynamic_typeParameter_hasPromotedBound_notFunction() {
+ var T = typeParameter('T');
+
+ _assertNotFunctionBounded(
+ typeParameterTypeNone(T, promotedBound: intNone),
+ );
+ }
+
+ test_dynamic_typeParameter_noBound() {
+ var T = typeParameter('T');
+
+ _assertNotFunctionBounded(
+ typeParameterTypeNone(T),
+ );
+ }
+
+ test_functionType() {
+ _assertFunctionBounded(
+ functionTypeNone(returnType: voidNone),
+ );
+ _assertNotFunctionBounded(
+ functionTypeQuestion(returnType: voidNone),
+ );
+ _assertFunctionBounded(
+ functionTypeStar(returnType: voidNone),
+ );
+
+ _assertFunctionBounded(
+ functionTypeNone(returnType: dynamicNone),
+ );
+ }
+
+ test_interfaceType() {
+ _assertNotFunctionBounded(intNone);
+ _assertNotFunctionBounded(intQuestion);
+ _assertNotFunctionBounded(intStar);
+ }
+
+ test_never() {
+ _assertNotFunctionBounded(neverNone);
+ _assertNotFunctionBounded(neverQuestion);
+ _assertNotFunctionBounded(neverStar);
+ }
+
+ test_void() {
+ _assertNotFunctionBounded(voidNone);
+ }
+
+ void _assertFunctionBounded(DartType type) {
+ expect(typeSystem.isFunctionBounded(type), isTrue);
+ }
+
+ void _assertNotFunctionBounded(DartType type) {
+ expect(typeSystem.isFunctionBounded(type), isFalse);
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 16de782..93ca075 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -2554,6 +2554,24 @@
);
}
+ test_hasReceiver_typeParameter_promotedToNonNullable() async {
+ await assertNoErrorsInCode('''
+void f<T>(T? t) {
+ if (t is int) {
+ t.abs();
+ }
+}
+''');
+
+ assertMethodInvocation2(
+ findNode.methodInvocation('t.abs()'),
+ element: intElement.getMethod('abs'),
+ typeArgumentTypes: [],
+ invokeType: 'int Function()',
+ type: 'int',
+ );
+ }
+
test_nullShorting_cascade_firstMethodInvocation() async {
await assertNoErrorsInCode(r'''
class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
index ed5052e..9f951dc 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -440,6 +440,62 @@
);
}
+ test_targetTypeParameter_dynamicBounded() async {
+ await assertNoErrorsInCode('''
+class A<T extends dynamic> {
+ void f(T t) {
+ (t).foo;
+ }
+}
+''');
+
+ var propertyAccess = findNode.propertyAccess('.foo');
+ assertPropertyAccess2(
+ propertyAccess,
+ element: null,
+ type: 'dynamic',
+ );
+
+ assertSimpleIdentifier(
+ propertyAccess.propertyName,
+ readElement: null,
+ writeElement: null,
+ type: 'dynamic',
+ );
+ }
+
+ test_targetTypeParameter_noBound() async {
+ await resolveTestCode('''
+class C<T> {
+ void f(T t) {
+ (t).foo;
+ }
+}
+''');
+ assertErrorsInResult(expectedErrorsByNullability(
+ nullable: [
+ error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 33, 3),
+ ],
+ legacy: [
+ error(CompileTimeErrorCode.UNDEFINED_GETTER, 37, 3),
+ ],
+ ));
+
+ var propertyAccess = findNode.propertyAccess('.foo');
+ assertPropertyAccess2(
+ propertyAccess,
+ element: null,
+ type: 'dynamic',
+ );
+
+ assertSimpleIdentifier(
+ propertyAccess.propertyName,
+ readElement: null,
+ writeElement: null,
+ type: 'dynamic',
+ );
+ }
+
test_tearOff_method() async {
await assertNoErrorsInCode('''
class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/extension_methods_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/extension_methods_test.dart
index cf8638c..d9581ac 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/extension_methods_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/extension_methods_test.dart
@@ -6,15 +6,20 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../context_collection_resolution.dart';
+import '../resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ExtensionMethodsTest);
+ defineReflectiveTests(ExtensionMethodsWithNullSafetyTest);
});
}
@reflectiveTest
-class ExtensionMethodsTest extends PubPackageResolutionTest {
+class ExtensionMethodsTest extends PubPackageResolutionTest
+ with ExtensionMethodsTestCases {}
+
+mixin ExtensionMethodsTestCases on ResolutionTest {
test_implicit_getter() async {
await assertNoErrorsInCode('''
class A<T> {}
@@ -150,6 +155,118 @@
);
}
+ test_implicit_targetTypeParameter_hasBound_methodInvocation() async {
+ await assertNoErrorsInCode('''
+extension Test<T> on T {
+ T Function(T) test() => throw 0;
+}
+
+void f<S extends num>(S x) {
+ x.test();
+}
+''');
+
+ if (result.libraryElement.isNonNullableByDefault) {
+ assertMethodInvocation2(
+ findNode.methodInvocation('test();'),
+ element: elementMatcher(
+ findElement.method('test'),
+ substitution: {'T': 'S'},
+ ),
+ typeArgumentTypes: [],
+ invokeType: 'S Function(S) Function()',
+ type: 'S Function(S)',
+ );
+ } else {
+ assertMethodInvocation2(
+ findNode.methodInvocation('test();'),
+ element: elementMatcher(
+ findElement.method('test'),
+ substitution: {'T': 'num'},
+ ),
+ typeArgumentTypes: [],
+ invokeType: 'num Function(num) Function()',
+ type: 'num Function(num)',
+ );
+ }
+ }
+
+ test_implicit_targetTypeParameter_hasBound_propertyAccess_getter() async {
+ await assertNoErrorsInCode('''
+extension Test<T> on T {
+ T Function(T) get test => throw 0;
+}
+
+void f<S extends num>(S x) {
+ (x).test;
+}
+''');
+
+ if (result.libraryElement.isNonNullableByDefault) {
+ assertPropertyAccess2(
+ findNode.propertyAccess('.test'),
+ element: elementMatcher(
+ findElement.getter('test'),
+ substitution: {'T': 'S'},
+ ),
+ type: 'S Function(S)',
+ );
+ } else {
+ assertPropertyAccess2(
+ findNode.propertyAccess('.test'),
+ element: elementMatcher(
+ findElement.getter('test'),
+ substitution: {'T': 'num'},
+ ),
+ type: 'num Function(num)',
+ );
+ }
+ }
+
+ test_implicit_targetTypeParameter_hasBound_propertyAccess_setter() async {
+ await assertNoErrorsInCode('''
+extension Test<T> on T {
+ void set test(T _) {}
+}
+
+T g<T>() => throw 0;
+
+void f<S extends num>(S x) {
+ (x).test = g();
+}
+''');
+
+ if (result.libraryElement.isNonNullableByDefault) {
+ assertPropertyAccess2(
+ findNode.propertyAccess('.test'),
+ element: elementMatcher(
+ findElement.setter('test'),
+ substitution: {'T': 'S'},
+ ),
+ type: 'S',
+ );
+
+ assertTypeArgumentTypes(
+ findNode.methodInvocation('g()'),
+ ['S'],
+ );
+ } else {
+ assertPropertyAccess2(
+ findNode.propertyAccess('.test'),
+ element: elementMatcher(
+ findElement.setter('test'),
+ substitution: {'T': 'num'},
+ ),
+ type: 'num',
+ );
+
+ assertTypeArgumentTypes(
+ findNode.methodInvocation('g()'),
+ ['num'],
+ );
+ }
+ }
+
test_override_downward_hasTypeArguments() async {
await assertNoErrorsInCode('''
extension E<T> on Set<T> {
@@ -425,3 +542,7 @@
);
}
}
+
+@reflectiveTest
+class ExtensionMethodsWithNullSafetyTest extends PubPackageResolutionTest
+ with WithNullSafetyMixin, ExtensionMethodsTestCases {}
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 9c2d399..c5ec2e9 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -964,11 +964,6 @@
js_ast.ClassExpression(
_emitTemporaryId(mixinName), baseClass, forwardingMethodStubs)
]));
- // Emit a deferred superclass statement for virtual mixin classes since
- // dart.mixinOn requires the virtual object to have a valid prototype.
- var virtualSupertype = baseClass ?? emitDeferredType(supertype);
- body.add(
- runtimeStatement('setBaseClass(#, #)', [mixinId, virtualSupertype]));
emitMixinConstructors(mixinId, mixinType);
hasUnnamedSuper = hasUnnamedSuper || _hasUnnamedConstructor(mixinClass);
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index 321cac5..340d7da 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -208,6 +208,9 @@
"process": {
ExperimentalFlag.nonNullable,
},
+ "pub_semver": {
+ ExperimentalFlag.nonNullable,
+ },
"sky_engine": {
ExperimentalFlag.nonNullable,
},
diff --git a/sdk/lib/_internal/allowed_experiments.json b/sdk/lib/_internal/allowed_experiments.json
index 8fe425f..c967d66 100644
--- a/sdk/lib/_internal/allowed_experiments.json
+++ b/sdk/lib/_internal/allowed_experiments.json
@@ -100,6 +100,9 @@
"process": {
"experimentSet": "nullSafety"
},
+ "pub_semver": {
+ "experimentSet": "nullSafety"
+ },
"sky_engine": {
"experimentSet": "nullSafety"
},
diff --git a/tests/language/mixin/regress_flutter_66859_test.dart b/tests/language/mixin/regress_flutter_66859_test.dart
deleted file mode 100644
index 544da53..0000000
--- a/tests/language/mixin/regress_flutter_66859_test.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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.
-
-// Verifies that mixin supertypes are properly maintained even if marked as
-// deferred (e.g., in a circular hierarchy).
-// Regression test for: https://github.com/flutter/flutter/issues/66859
-
-import "package:expect/expect.dart";
-
-mixin M {}
-
-mixin N {}
-
-class A extends B<C> with M, N {}
-
-class B<T> {}
-
-class C extends A {}
-
-class Z extends B<Z> with M {}
-
-main() {
- var z = Z();
- Expect.isTrue(z is B<Z>);
- Expect.isTrue(z is M);
- var a = A();
- Expect.isTrue(a is M);
- Expect.isTrue(a is N);
- Expect.isTrue(a is B<C>);
-}
diff --git a/tools/VERSION b/tools/VERSION
index 590277c..c38dcce 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 183
+PRERELEASE 184
PRERELEASE_PATCH 0
\ No newline at end of file