mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 13:47:50 +00:00
restrict generic function type subtyping
R=leafp@google.com Review URL: https://codereview.chromium.org/2540903003 .
This commit is contained in:
parent
db8782f6e6
commit
7a1b6e75b3
|
@ -1026,16 +1026,12 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
|
|||
// This type cast is safe, because we checked it above.
|
||||
FunctionType s = other as FunctionType;
|
||||
if (t.typeFormals.isNotEmpty) {
|
||||
if (s.typeFormals.isEmpty) {
|
||||
t = instantiateToBounds(t);
|
||||
} else {
|
||||
List<DartType> freshVariables = relateTypeFormals(t, s, returnRelation);
|
||||
if (freshVariables == null) {
|
||||
return false;
|
||||
}
|
||||
t = t.instantiate(freshVariables);
|
||||
s = s.instantiate(freshVariables);
|
||||
List<DartType> freshVariables = relateTypeFormals(t, s, returnRelation);
|
||||
if (freshVariables == null) {
|
||||
return false;
|
||||
}
|
||||
t = t.instantiate(freshVariables);
|
||||
s = s.instantiate(freshVariables);
|
||||
} else if (s.typeFormals.isNotEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1434,15 +1434,7 @@ class _OverrideChecker {
|
|||
]);
|
||||
}
|
||||
}
|
||||
FunctionType concreteSubType = subType;
|
||||
FunctionType concreteBaseType = baseType;
|
||||
if (concreteSubType.typeFormals.isNotEmpty) {
|
||||
if (concreteBaseType.typeFormals.isEmpty) {
|
||||
concreteSubType = rules.instantiateToBounds(concreteSubType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!rules.isOverrideSubtypeOf(concreteSubType, concreteBaseType)) {
|
||||
if (!rules.isOverrideSubtypeOf(subType, baseType)) {
|
||||
ErrorCode errorCode;
|
||||
if (errorLocation is ExtendsClause) {
|
||||
errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE;
|
||||
|
|
|
@ -1608,7 +1608,34 @@ class StrongSubtypingTest {
|
|||
DartType u = TypeBuilder.variable("U", bound: intType);
|
||||
DartType v = TypeBuilder.variable("V", bound: u);
|
||||
|
||||
DartType a = TypeBuilder.variable("A");
|
||||
DartType b = TypeBuilder.variable("B", bound: a);
|
||||
DartType c = TypeBuilder.variable("C", bound: intType);
|
||||
DartType d = TypeBuilder.variable("D", bound: c);
|
||||
|
||||
_checkIsStrictSubtypeOf(
|
||||
TypeBuilder.function(types: [s, t], required: [s], result: t),
|
||||
TypeBuilder.function(
|
||||
types: [a, b], required: [dynamicType], result: dynamicType));
|
||||
|
||||
_checkIsNotSubtypeOf(
|
||||
TypeBuilder.function(types: [u, v], required: [u], result: v),
|
||||
TypeBuilder.function(
|
||||
types: [c, d], required: [objectType], result: objectType));
|
||||
|
||||
_checkIsNotSubtypeOf(
|
||||
TypeBuilder.function(types: [u, v], required: [u], result: v),
|
||||
TypeBuilder
|
||||
.function(types: [c, d], required: [intType], result: intType));
|
||||
}
|
||||
|
||||
void test_genericFunction_genericDoesNotSubtypeNonGeneric() {
|
||||
DartType s = TypeBuilder.variable("S");
|
||||
DartType t = TypeBuilder.variable("T", bound: s);
|
||||
DartType u = TypeBuilder.variable("U", bound: intType);
|
||||
DartType v = TypeBuilder.variable("V", bound: u);
|
||||
|
||||
_checkIsNotSubtypeOf(
|
||||
TypeBuilder.function(types: [s, t], required: [s], result: t),
|
||||
TypeBuilder.function(required: [dynamicType], result: dynamicType));
|
||||
|
||||
|
@ -1616,7 +1643,7 @@ class StrongSubtypingTest {
|
|||
TypeBuilder.function(types: [u, v], required: [u], result: v),
|
||||
TypeBuilder.function(required: [objectType], result: objectType));
|
||||
|
||||
_checkIsStrictSubtypeOf(
|
||||
_checkIsNotSubtypeOf(
|
||||
TypeBuilder.function(types: [u, v], required: [u], result: v),
|
||||
TypeBuilder.function(required: [intType], result: intType));
|
||||
}
|
||||
|
|
|
@ -3991,6 +3991,27 @@ void main() {
|
|||
''');
|
||||
}
|
||||
|
||||
void test_universalFunctionSubtyping() {
|
||||
checkFile(r'''
|
||||
dynamic foo<T>(dynamic x) => x;
|
||||
|
||||
void takesDtoD(dynamic f(dynamic x)) {}
|
||||
|
||||
void test() {
|
||||
// here we currently infer an instantiation.
|
||||
takesDtoD(/*pass should be error:INVALID_ASSIGNMENT*/foo);
|
||||
}
|
||||
|
||||
class A {
|
||||
dynamic method(dynamic x) => x;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
/*error:INVALID_METHOD_OVERRIDE*/T method<T>(T x) => x;
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
void test_voidSubtyping() {
|
||||
// Regression test for https://github.com/dart-lang/sdk/issues/25069
|
||||
checkFile('''
|
||||
|
|
|
@ -2263,26 +2263,8 @@ class C {
|
|||
dynamic g(int x) => x;
|
||||
}
|
||||
class D extends C {
|
||||
T m<T>(T x) => x;
|
||||
T g<T>(T x) => x;
|
||||
}
|
||||
main() {
|
||||
int y = /*info:DYNAMIC_CAST*/(/*info:UNNECESSARY_CAST*/new D() as C).m(42);
|
||||
print(y);
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
void test_genericMethods_handleOverrideOfNonGenericWithGeneric_comment() {
|
||||
// Regression test for crash when adding genericity
|
||||
checkFile('''
|
||||
class C {
|
||||
m(x) => x;
|
||||
dynamic g(int x) => x;
|
||||
}
|
||||
class D extends C {
|
||||
/*=T*/ m/*<T>*/(/*=T*/ x) => x;
|
||||
/*=T*/ g/*<T>*/(/*=T*/ x) => x;
|
||||
/*error:INVALID_METHOD_OVERRIDE*/T m<T>(T x) => x;
|
||||
/*error:INVALID_METHOD_OVERRIDE*/T g<T>(T x) => x;
|
||||
}
|
||||
main() {
|
||||
int y = /*info:DYNAMIC_CAST*/(/*info:UNNECESSARY_CAST*/new D() as C).m(42);
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
[error] Couldn't infer type parameter 'T'; '_ControllerEventSinkWrapper<dynamic>' must be of type 'EventSink<T>'. (dart:async/stream.dart, line 1346, col 16)
|
||||
[error] The argument type '_ControllerEventSinkWrapper' can't be assigned to the parameter type 'EventSink<T>'. (dart:async/stream.dart, line 1346, col 53)
|
||||
[error] A value of type '<R>(Zone, ZoneDelegate, Zone, () → R) → R' can't be assigned to a parameter of type '(Zone, ZoneDelegate, Zone, () → dynamic) → dynamic'. (dart:async/zone.dart, line 1071, col 51)
|
||||
[error] A value of type '<R,T>(Zone, ZoneDelegate, Zone, (T) → R, T) → R' can't be assigned to a parameter of type '(Zone, ZoneDelegate, Zone, (dynamic) → dynamic, dynamic) → dynamic'. (dart:async/zone.dart, line 1073, col 56)
|
||||
[error] A value of type '<R,T1,T2>(Zone, ZoneDelegate, Zone, (T1, T2) → R, T1, T2) → R' can't be assigned to a parameter of type '(Zone, ZoneDelegate, Zone, (dynamic, dynamic) → dynamic, dynamic, dynamic) → dynamic'. (dart:async/zone.dart, line 1075, col 57)
|
||||
[error] A value of type '<R>(Zone, ZoneDelegate, Zone, () → R) → () → R' can't be assigned to a parameter of type '(Zone, ZoneDelegate, Zone, () → dynamic) → () → dynamic'. (dart:async/zone.dart, line 1078, col 23)
|
||||
[error] A value of type '<R,T>(Zone, ZoneDelegate, Zone, (T) → R) → (T) → R' can't be assigned to a parameter of type '(Zone, ZoneDelegate, Zone, (dynamic) → dynamic) → (dynamic) → dynamic'. (dart:async/zone.dart, line 1081, col 23)
|
||||
[error] A value of type '<R,T1,T2>(Zone, ZoneDelegate, Zone, (T1, T2) → R) → (T1, T2) → R' can't be assigned to a parameter of type '(Zone, ZoneDelegate, Zone, (dynamic, dynamic) → dynamic) → (dynamic, dynamic) → dynamic'. (dart:async/zone.dart, line 1084, col 23)
|
||||
[error] A value of type '<R>(Zone, ZoneDelegate, Zone, dynamic, StackTrace) → R' can't be assigned to a parameter of type '(Zone, ZoneDelegate, Zone, dynamic, StackTrace) → dynamic'. (dart:async/zone.dart, line 1100, col 23)
|
||||
[error] Invalid override. The type of 'ChunkedConverter.bind' ('(dynamic) → dynamic') isn't a subtype of 'Converter<S, T>.bind' ('(Stream<S>) → Stream<T>'). (dart:convert/chunked_conversion.dart, line 14, col 3)
|
||||
[error] Invalid override. The type of 'ChunkedConverter.bind' ('(dynamic) → dynamic') isn't a subtype of 'StreamTransformer<S, T>.bind' ('(Stream<S>) → Stream<T>'). (dart:convert/chunked_conversion.dart, line 14, col 3)
|
||||
[error] Invalid override. The type of 'ChunkedConverter.startChunkedConversion' ('(dynamic) → dynamic') isn't a subtype of 'Converter<S, T>.startChunkedConversion' ('(Sink<T>) → Sink<S>'). (dart:convert/chunked_conversion.dart, line 15, col 3)
|
||||
|
|
Loading…
Reference in a new issue