fix #26120, sideways casts no longer supported

R=vsm@google.com

Review URL: https://codereview.chromium.org/2231273002 .
This commit is contained in:
John Messerly 2016-08-12 14:32:36 -07:00
parent ee3a93a0a8
commit e36fa2b3be
6 changed files with 99 additions and 101 deletions

View file

@ -86,6 +86,9 @@
}
```
* Breaking change - sideways casts are no longer allowed
(SDK issue [26120](https://github.com/dart-lang/sdk/issues/26120)).
### Dart VM
* The dependency on BoringSSL has been rolled forward. Going forward, builds

View file

@ -354,8 +354,7 @@ class StrongTypeSystemImpl extends TypeSystem {
// Don't allow implicit downcasts between function types
// and call method objects, as these will almost always fail.
if ((fromType is FunctionType && getCallMethodType(toType) != null) ||
(toType is FunctionType && getCallMethodType(fromType) != null)) {
if (fromType is FunctionType && getCallMethodType(toType) != null) {
return false;
}
@ -373,7 +372,7 @@ class StrongTypeSystemImpl extends TypeSystem {
// If the subtype relation goes the other way, allow the implicit
// downcast.
if (isSubtypeOf(toType, fromType) || toType.isAssignableTo(fromType)) {
if (isSubtypeOf(toType, fromType)) {
// TODO(leafp,jmesserly): we emit warnings/hints for these in
// src/task/strong/checker.dart, which is a bit inconsistent. That
// code should be handled into places that use isAssignableTo, such as

View file

@ -749,14 +749,10 @@ class CodeChecker extends RecursiveAstVisitor {
// fromT <: toT, no coercion needed.
if (rules.isSubtypeOf(from, to)) return;
// TODO(vsm): We can get rid of the second clause if we disallow
// all sideways casts - see TODO below.
// -------
// Note: a function type is never assignable to a class per the Dart
// spec - even if it has a compatible call method. We disallow as
// well for consistency.
if ((from is FunctionType && rules.getCallMethodType(to) != null) ||
(to is FunctionType && rules.getCallMethodType(from) != null)) {
if (from is FunctionType && rules.getCallMethodType(to) != null) {
return;
}
@ -766,19 +762,9 @@ class CodeChecker extends RecursiveAstVisitor {
return;
}
// TODO(vsm): Once we have generic methods, we should delete this
// workaround. These sideways casts are always ones we warn about
// - i.e., we think they are likely to fail at runtime.
// -------
// Downcast if toT <===> fromT
// The intention here is to allow casts that are sideways in the restricted
// type system, but allowed in the regular dart type system, since these
// are likely to succeed. The canonical example is List<dynamic> and
// Iterable<T> for some concrete T (e.g. Object). These are unrelated
// in the restricted system, but List<dynamic> <: Iterable<T> in dart.
if (from.isAssignableTo(to)) {
_recordImplicitCast(expr, from, to);
}
// Anything else is an illegal sideways cast.
// However, these will have been reported already in error_verifier, so we
// don't need to report them again.
}
void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) {
@ -1057,7 +1043,7 @@ class CodeChecker extends RecursiveAstVisitor {
// toT <:_R fromT => to <: fromT
// NB: classes with call methods are subtypes of function
// types, but the function type is not assignable to the class
assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
assert(toType.isSubtypeOf(fromType));
// Inference "casts":
if (expression is Literal || expression is FunctionExpression) {

View file

@ -164,6 +164,7 @@ class LeastUpperBoundTest extends LeastUpperBoundTestBase {
FunctionType expected = _functionType([objectType, numType, numType]);
_checkLeastUpperBound(type1, type2, expected);
}
void test_nestedNestedFunctionsLubInnermostParamTypes() {
FunctionType type1 = _functionType([
_functionType([
@ -620,7 +621,11 @@ class StrongAssignabilityTest {
numType,
bottomType
];
List<DartType> unrelated = <DartType>[intType, stringType, interfaceType,];
List<DartType> unrelated = <DartType>[
intType,
stringType,
interfaceType,
];
_checkGroups(doubleType,
interassignable: interassignable, unrelated: unrelated);
@ -750,7 +755,10 @@ class StrongAssignabilityTest {
doubleType,
bottomType
];
List<DartType> unrelated = <DartType>[stringType, interfaceType,];
List<DartType> unrelated = <DartType>[
stringType,
interfaceType,
];
_checkGroups(numType,
interassignable: interassignable, unrelated: unrelated);
@ -780,10 +788,12 @@ class StrongAssignabilityTest {
void _checkCrossLattice(
DartType top, DartType left, DartType right, DartType bottom) {
_checkGroups(top, interassignable: <DartType>[top, left, right, bottom]);
_checkGroups(left, interassignable: <DartType>[top, left, right, bottom]);
_checkGroups(right, interassignable: <DartType>[top, left, right, bottom]);
_checkGroups(bottom, interassignable: <DartType>[top, left, right, bottom]);
_checkGroups(top, interassignable: [top, left, right, bottom]);
_checkGroups(left,
interassignable: [top, left, bottom], unrelated: [right]);
_checkGroups(right,
interassignable: [top, right, bottom], unrelated: [left]);
_checkGroups(bottom, interassignable: [top, left, right, bottom]);
}
void _checkEquivalent(DartType type1, DartType type2) {

View file

@ -807,13 +807,13 @@ void main() {
Left f;
f = /*error:STATIC_TYPE_ERROR*/top;
f = left;
f = /*error:STATIC_TYPE_ERROR*/right;
f = /*error:INVALID_ASSIGNMENT*/right;
f = bot;
}
{
Right f;
f = /*error:STATIC_TYPE_ERROR*/top;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:INVALID_ASSIGNMENT*/left;
f = right;
f = bot;
}
@ -853,13 +853,13 @@ void main() {
Left f;
f = /*warning:DOWN_CAST_COMPOSITE*/top;
f = left;
f = /*warning:DOWN_CAST_COMPOSITE*/right;
f = /*error:INVALID_ASSIGNMENT*/right;
f = bot;
}
{
Right f;
f = /*warning:DOWN_CAST_COMPOSITE*/top;
f = /*warning:DOWN_CAST_COMPOSITE*/left;
f = /*error:INVALID_ASSIGNMENT*/left;
f = right;
f = bot;
}
@ -940,14 +940,14 @@ void main() {
f = topTop;
f = aa;
f = aTop;
f = /*warning:DOWN_CAST_COMPOSITE should be error:STATIC_TYPE_ERROR*/botA;
f = /*error:INVALID_ASSIGNMENT*/botA;
f = /*warning:DOWN_CAST_COMPOSITE*/botTop;
apply/*<ATop>*/(
topA,
topTop,
aa,
aTop,
/*warning:DOWN_CAST_COMPOSITE should be error:STATIC_TYPE_ERROR*/botA,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/botA,
/*warning:DOWN_CAST_COMPOSITE*/botTop
);
apply/*<ATop>*/(
@ -955,31 +955,31 @@ void main() {
(dynamic x) => (x as Object),
(A x) => x,
(A x) => null,
/*warning:DOWN_CAST_COMPOSITE should be error:STATIC_TYPE_ERROR*/botA,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/botA,
/*warning:DOWN_CAST_COMPOSITE*/botTop
);
}
{
BotA f;
f = topA;
f = /*error:STATIC_TYPE_ERROR*/topTop;
f = /*error:INVALID_ASSIGNMENT*/topTop;
f = aa;
f = /*error:STATIC_TYPE_ERROR*/aTop;
f = /*error:INVALID_ASSIGNMENT*/aTop;
f = botA;
f = /*warning:DOWN_CAST_COMPOSITE*/botTop;
apply/*<BotA>*/(
topA,
/*error:STATIC_TYPE_ERROR*/topTop,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/topTop,
aa,
/*error:STATIC_TYPE_ERROR*/aTop,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/aTop,
botA,
/*warning:DOWN_CAST_COMPOSITE*/botTop
);
apply/*<BotA>*/(
(dynamic x) => new A(),
/*error:STATIC_TYPE_ERROR*/(dynamic x) => (x as Object),
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/(dynamic x) => (x as Object),
(A x) => x,
/*error:STATIC_TYPE_ERROR*/(A x) => (x as Object),
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/(A x) => (x as Object),
botA,
/*warning:DOWN_CAST_COMPOSITE*/botTop
);
@ -987,14 +987,14 @@ void main() {
{
AA f;
f = topA;
f = /*error:STATIC_TYPE_ERROR*/topTop;
f = /*error:INVALID_ASSIGNMENT*/topTop;
f = aa;
f = /*error:STATIC_TYPE_ERROR*/aTop; // known function
f = /*warning:DOWN_CAST_COMPOSITE*/botA;
f = /*warning:DOWN_CAST_COMPOSITE*/botTop;
apply/*<AA>*/(
topA,
/*error:STATIC_TYPE_ERROR*/topTop,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/topTop,
aa,
/*error:STATIC_TYPE_ERROR*/aTop, // known function
/*warning:DOWN_CAST_COMPOSITE*/botA,
@ -1002,7 +1002,7 @@ void main() {
);
apply/*<AA>*/(
(dynamic x) => new A(),
/*error:STATIC_TYPE_ERROR*/(dynamic x) => (x as Object),
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/(dynamic x) => (x as Object),
(A x) => x,
/*error:STATIC_TYPE_ERROR*/(A x) => (x as Object), // known function
/*warning:DOWN_CAST_COMPOSITE*/botA,
@ -1013,24 +1013,24 @@ void main() {
TopTop f;
f = topA;
f = topTop;
f = /*error:STATIC_TYPE_ERROR*/aa;
f = /*error:INVALID_ASSIGNMENT*/aa;
f = /*error:STATIC_TYPE_ERROR*/aTop; // known function
f = /*warning:DOWN_CAST_COMPOSITE should be error:STATIC_TYPE_ERROR*/botA;
f = /*error:INVALID_ASSIGNMENT*/botA;
f = /*warning:DOWN_CAST_COMPOSITE*/botTop;
apply/*<TopTop>*/(
topA,
topTop,
/*error:STATIC_TYPE_ERROR*/aa,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/aa,
/*error:STATIC_TYPE_ERROR*/aTop, // known function
/*warning:DOWN_CAST_COMPOSITE should be error:STATIC_TYPE_ERROR*/botA,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/botA,
/*warning:DOWN_CAST_COMPOSITE*/botTop
);
apply/*<TopTop>*/(
(dynamic x) => new A(),
(dynamic x) => (x as Object),
/*error:STATIC_TYPE_ERROR*/(A x) => x,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/(A x) => x,
/*error:STATIC_TYPE_ERROR*/(A x) => (x as Object), // known function
/*warning:DOWN_CAST_COMPOSITE should be error:STATIC_TYPE_ERROR*/botA,
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/botA,
/*warning:DOWN_CAST_COMPOSITE*/botTop
);
}
@ -1141,16 +1141,16 @@ void main() {
f = bot;
}
{
Function2<B, B> f;
Function2<B, B> f; // left
f = /*error:STATIC_TYPE_ERROR*/top;
f = left;
f = /*error:STATIC_TYPE_ERROR*/right;
f = /*error:INVALID_ASSIGNMENT*/right;
f = bot;
}
{
Function2<A, A> f;
Function2<A, A> f; // right
f = /*error:STATIC_TYPE_ERROR*/top;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:INVALID_ASSIGNMENT*/left;
f = right;
f = bot;
}
@ -1186,12 +1186,12 @@ void main() {
left = /*warning:DOWN_CAST_COMPOSITE*/top;
left = left;
left = /*warning:DOWN_CAST_COMPOSITE*/right; // Should we reject this?
left = /*error:INVALID_ASSIGNMENT*/right;
left = bot;
right = /*warning:DOWN_CAST_COMPOSITE*/top;
right = /*warning:DOWN_CAST_COMPOSITE*/left; // Should we reject this?
right = right;
right = /*info:INVALID_ASSIGNMENT,warning:DOWN_CAST_COMPOSITE*/top;
right = /*error:INVALID_ASSIGNMENT*/left;
right = /*info:INVALID_ASSIGNMENT*/right;
right = bot;
bot = /*warning:DOWN_CAST_COMPOSITE*/top;
@ -1231,13 +1231,13 @@ void main() {
Function2<AToB, AToB> f; // Left
f = /*error:STATIC_TYPE_ERROR*/top;
f = left;
f = /*error:STATIC_TYPE_ERROR*/right;
f = /*error:INVALID_ASSIGNMENT*/right;
f = bot;
}
{
Function2<BToA, BToA> f; // Right
f = /*error:STATIC_TYPE_ERROR*/top;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:INVALID_ASSIGNMENT*/left;
f = right;
f = bot;
}
@ -1246,7 +1246,7 @@ void main() {
f = bot;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:STATIC_TYPE_ERROR*/top;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:STATIC_TYPE_ERROR*/right;
}
}
''');
@ -1280,13 +1280,13 @@ void main() {
Function2<AToB, AToB> f; // Left
f = /*error:STATIC_TYPE_ERROR*/top;
f = left;
f = /*error:STATIC_TYPE_ERROR*/right;
f = /*error:INVALID_ASSIGNMENT*/right;
f = bot;
}
{
Function2<BToA, BToA> f; // Right
f = /*error:STATIC_TYPE_ERROR*/top;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:INVALID_ASSIGNMENT*/left;
f = right;
f = bot;
}
@ -1295,7 +1295,7 @@ void main() {
f = bot;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:STATIC_TYPE_ERROR*/top;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:STATIC_TYPE_ERROR*/right;
}
}
''');
@ -1329,13 +1329,13 @@ void main() {
Function2<AToB, AToB> f; // Left
f = /*error:STATIC_TYPE_ERROR*/top;
f = left;
f = /*error:STATIC_TYPE_ERROR*/right;
f = /*error:INVALID_ASSIGNMENT*/right;
f = bot;
}
{
Function2<BToA, BToA> f; // Right
f = /*error:STATIC_TYPE_ERROR*/top;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:INVALID_ASSIGNMENT*/left;
f = right;
f = bot;
}
@ -1344,7 +1344,7 @@ void main() {
f = bot;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:STATIC_TYPE_ERROR*/top;
f = /*error:STATIC_TYPE_ERROR*/left;
f = /*error:STATIC_TYPE_ERROR*/right;
}
}
''');
@ -1372,12 +1372,12 @@ void main() {
left = /*warning:DOWN_CAST_COMPOSITE*/top;
left = left;
left =
/*warning:DOWN_CAST_COMPOSITE should be error:STATIC_TYPE_ERROR*/right;
/*error:INVALID_ASSIGNMENT*/right;
left = bot;
right = /*warning:DOWN_CAST_COMPOSITE*/top;
right =
/*warning:DOWN_CAST_COMPOSITE should be error:STATIC_TYPE_ERROR*/left;
/*error:INVALID_ASSIGNMENT*/left;
right = right;
right = bot;
@ -1417,13 +1417,13 @@ void main() {
Function2<B, B> f;
f = /*warning:DOWN_CAST_COMPOSITE*/c.top;
f = c.left;
f = /*warning:DOWN_CAST_COMPOSITE*/c.right;
f = /*error:INVALID_ASSIGNMENT*/c.right;
f = c.bot;
}
{
Function2<A, A> f;
f = /*warning:DOWN_CAST_COMPOSITE*/c.top;
f = /*warning:DOWN_CAST_COMPOSITE*/c.left;
f = /*error:INVALID_ASSIGNMENT*/c.left;
f = c.right;
f = c.bot;
}
@ -1475,13 +1475,13 @@ void main() {
Left f;
f = /*warning:DOWN_CAST_COMPOSITE*/top;
f = left;
f = /*warning:DOWN_CAST_COMPOSITE*/right; // Should we reject this?
f = /*error:INVALID_ASSIGNMENT*/right;
f = bot;
}
{
Right f;
f = /*warning:DOWN_CAST_COMPOSITE*/top;
f = /*warning:DOWN_CAST_COMPOSITE*/left; // Should we reject this?
f = /*error:INVALID_ASSIGNMENT*/left;
f = right;
f = bot;
}
@ -1632,7 +1632,7 @@ void main() {
f = new A();
f = /*error:INVALID_ASSIGNMENT*/new B();
f = i2i;
f = /*error:STATIC_TYPE_ERROR*/n2n;
f = /*error:INVALID_ASSIGNMENT*/n2n;
f = /*warning:DOWN_CAST_COMPOSITE*/i2i as Object;
f = /*warning:DOWN_CAST_COMPOSITE*/n2n as Function;
}
@ -1640,7 +1640,7 @@ void main() {
N2N f;
f = /*error:INVALID_ASSIGNMENT*/new A();
f = new B();
f = /*error:STATIC_TYPE_ERROR*/i2i;
f = /*error:INVALID_ASSIGNMENT*/i2i;
f = n2n;
f = /*warning:DOWN_CAST_COMPOSITE*/i2i as Object;
f = /*warning:DOWN_CAST_COMPOSITE*/n2n as Function;
@ -1702,13 +1702,13 @@ void main() {
Function2<B, B> f;
f = /*error:STATIC_TYPE_ERROR*/C.top;
f = C.left;
f = /*error:STATIC_TYPE_ERROR*/C.right;
f = /*error:INVALID_ASSIGNMENT*/C.right;
f = C.bot;
}
{
Function2<A, A> f;
f = /*error:STATIC_TYPE_ERROR*/C.top;
f = /*error:STATIC_TYPE_ERROR*/C.left;
f = /*error:INVALID_ASSIGNMENT*/C.left;
f = C.right;
f = C.bot;
}
@ -1762,7 +1762,7 @@ void main() {
checkFile('''
typedef num Num2Num(num x);
void main() {
Num2Num g = /*info:INFERRED_TYPE_CLOSURE,error:STATIC_TYPE_ERROR*/(int x) { return x; };
Num2Num g = /*info:INFERRED_TYPE_CLOSURE,error:INVALID_ASSIGNMENT*/(int x) { return x; };
print(g(42));
}
''');
@ -3153,7 +3153,7 @@ void main() {
lOfOs = new L<Object>(); // Reset type propagation.
}
{
lOfAs = /*warning:DOWN_CAST_COMPOSITE*/mOfDs;
lOfAs = /*error:INVALID_ASSIGNMENT*/mOfDs;
lOfAs = /*error:INVALID_ASSIGNMENT*/mOfOs;
lOfAs = mOfAs;
lOfAs = /*warning:DOWN_CAST_COMPOSITE*/lOfDs;
@ -3167,7 +3167,7 @@ void main() {
mOfDs = mOfAs;
mOfDs = /*info:DOWN_CAST_IMPLICIT*/lOfDs;
mOfDs = /*info:DOWN_CAST_IMPLICIT*/lOfOs;
mOfDs = /*warning:DOWN_CAST_COMPOSITE*/lOfAs;
mOfDs = /*error:INVALID_ASSIGNMENT*/lOfAs;
mOfDs = new M(); // Reset type propagation.
}
{

View file

@ -1237,8 +1237,8 @@ void main() {
A<int, String> a1 = /*info:INFERRED_TYPE_ALLOCATION*/new B.named("hello", 3);
A<int, String> a2 = new B<String, int>("hello", 3);
A<int, String> a3 = new B<String, int>.named("hello", 3);
A<int, String> a4 = /*error:STATIC_TYPE_ERROR*/new B<String, dynamic>("hello", 3);
A<int, String> a5 = /*error:STATIC_TYPE_ERROR*/new B<dynamic, dynamic>.named("hello", 3);
A<int, String> a4 = /*error:INVALID_ASSIGNMENT*/new B<String, dynamic>("hello", 3);
A<int, String> a5 = /*error:INVALID_ASSIGNMENT*/new B<dynamic, dynamic>.named("hello", 3);
}
{
A<int, String> a0 = /*info:INFERRED_TYPE_ALLOCATION*/new B(
@ -1253,8 +1253,8 @@ void main() {
A<int, int> a1 = /*info:INFERRED_TYPE_ALLOCATION*/new C.named(3);
A<int, int> a2 = new C<int>(3);
A<int, int> a3 = new C<int>.named(3);
A<int, int> a4 = /*error:STATIC_TYPE_ERROR*/new C<dynamic>(3);
A<int, int> a5 = /*error:STATIC_TYPE_ERROR*/new C<dynamic>.named(3);
A<int, int> a4 = /*error:INVALID_ASSIGNMENT*/new C<dynamic>(3);
A<int, int> a5 = /*error:INVALID_ASSIGNMENT*/new C<dynamic>.named(3);
}
{
A<int, int> a0 = /*info:INFERRED_TYPE_ALLOCATION*/new C(
@ -1267,8 +1267,8 @@ void main() {
A<int, String> a1 = /*info:INFERRED_TYPE_ALLOCATION*/new D.named("hello");
A<int, String> a2 = new D<int, String>("hello");
A<int, String> a3 = new D<String, String>.named("hello");
A<int, String> a4 = /*error:STATIC_TYPE_ERROR*/new D<num, dynamic>("hello");
A<int, String> a5 = /*error:STATIC_TYPE_ERROR*/new D<dynamic, dynamic>.named("hello");
A<int, String> a4 = /*error:INVALID_ASSIGNMENT*/new D<num, dynamic>("hello");
A<int, String> a5 = /*error:INVALID_ASSIGNMENT*/new D<dynamic, dynamic>.named("hello");
}
{
A<int, String> a0 = /*info:INFERRED_TYPE_ALLOCATION*/new D(
@ -1761,11 +1761,11 @@ takeDDN(math.max);
takeIIO(math.max);
takeDDO(math.max);
takeOOI(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeIDI(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeDID(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeOON(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeOOO(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
// Also test SimpleIdentifier
takeIII(min);
@ -1778,11 +1778,11 @@ takeDDN(min);
takeIIO(min);
takeDDO(min);
takeOOI(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeIDI(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeDID(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeOON(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeOOO(/*error:STATIC_TYPE_ERROR,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
// Also PropertyAccess
takeIII(new C().m);
@ -1804,14 +1804,14 @@ takeDDO(new C().m);
//
// That's legal because we're loosening parameter types.
//
takeOON(/*warning:DOWN_CAST_COMPOSITE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
takeOOO(/*warning:DOWN_CAST_COMPOSITE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
// Note: this is a warning because a downcast of a method tear-off could work
// in "normal" Dart, due to bivariance.
takeOOI(/*warning:DOWN_CAST_COMPOSITE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
takeIDI(/*warning:DOWN_CAST_COMPOSITE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
takeDID(/*warning:DOWN_CAST_COMPOSITE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
}
void takeIII(int fn(int a, int b)) {}