mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:19:48 +00:00
5222bfd90c
This CL moves the bounds checking into the TypeBuilder instead of performing it from the outside on the computed DartType node. This solves several problems: 1) Errors are now reported on the type in the code instead of the declaration which holds the type. 2) Checking of type aliases (both function and nonfunction type aliases) is now handled correctly in all cases. This achieved by computed the aliased type (containing TypedefType nodes) internally and performing the checking on this type, and only convert the type into the unaliased version (without TypedefType nodes) after checks have been performed. Previously this handled through the FunctionType.typedefType property for function type aliases and through and incomplete work-around for nonfunction type aliases. 3) With 2) FunctionType.typedefType is no longer needed and is removed. TEST=general/bounds_* Change-Id: I7653bca5ccb0ebf4b3553828a298d1ad918ef235 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243722 Reviewed-by: Mayank Patke <fishythefish@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Chloe Stefantsova <cstefantsova@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
81 lines
3.1 KiB
Dart
81 lines
3.1 KiB
Dart
// Copyright (c) 2019, 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.
|
|
|
|
// Tests erroneous subtyping for the `in` variance modifier.
|
|
|
|
// SharedOptions=--enable-experiment=variance
|
|
|
|
class Contravariant<in T> {}
|
|
|
|
class Upper {}
|
|
class Middle extends Upper {}
|
|
class Lower extends Middle {}
|
|
|
|
class A {
|
|
Contravariant<Middle> method1() {
|
|
return new Contravariant<Middle>();
|
|
}
|
|
|
|
void method2(Contravariant<Middle> x) {}
|
|
}
|
|
|
|
class B extends A {
|
|
@override
|
|
Contravariant<Lower> method1() {
|
|
// ^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
|
|
// [cfe] The return type of the method 'B.method1' is 'Contravariant<Lower>', which does not match the return type, 'Contravariant<Middle>', of the overridden method, 'A.method1'.
|
|
return new Contravariant<Lower>();
|
|
}
|
|
|
|
@override
|
|
void method2(Contravariant<Upper> x) {}
|
|
// ^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
|
|
// ^
|
|
// [cfe] The parameter 'x' of the method 'B.method2' has type 'Contravariant<Upper>', which does not match the corresponding type, 'Contravariant<Middle>', in the overridden method, 'A.method2'.
|
|
}
|
|
|
|
class C<out T extends Contravariant<Middle>> {}
|
|
|
|
class D {
|
|
C<Contravariant<Lower>> method1() {
|
|
//^
|
|
// [cfe] Type argument 'Contravariant<Lower>' doesn't conform to the bound 'Contravariant<Middle>' of the type variable 'T' on 'C'.
|
|
//^^^^^^^^^^^^^^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
|
|
return C<Contravariant<Lower>>();
|
|
// ^
|
|
// [cfe] Type argument 'Contravariant<Lower>' doesn't conform to the bound 'Contravariant<Middle>' of the type variable 'T' on 'C'.
|
|
// ^^^^^^^^^^^^^^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
|
|
}
|
|
}
|
|
|
|
void testCall(Iterable<Contravariant<Middle>> x) {}
|
|
|
|
main() {
|
|
C<Contravariant<Lower>> c = new C<Contravariant<Lower>>();
|
|
//^
|
|
// [cfe] Type argument 'Contravariant<Lower>' doesn't conform to the bound 'Contravariant<Middle>' of the type variable 'T' on 'C'.
|
|
//^^^^^^^^^^^^^^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
|
|
// ^
|
|
// [cfe] Type argument 'Contravariant<Lower>' doesn't conform to the bound 'Contravariant<Middle>' of the type variable 'T' on 'C'.
|
|
// ^^^^^^^^^^^^^^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
|
|
|
|
Iterable<Contravariant<Middle>> iterableMiddle = [new Contravariant<Middle>()];
|
|
List<Contravariant<Lower>> listLower = [new Contravariant<Lower>()];
|
|
iterableMiddle = listLower;
|
|
// ^^^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
|
|
// [cfe] A value of type 'List<Contravariant<Lower>>' can't be assigned to a variable of type 'Iterable<Contravariant<Middle>>'.
|
|
|
|
testCall(listLower);
|
|
// ^^^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
|
|
// [cfe] The argument type 'List<Contravariant<Lower>>' can't be assigned to the parameter type 'Iterable<Contravariant<Middle>>'.
|
|
}
|