| // 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. |
| |
| // SharedOptions=--enable-experiment=extension-methods |
| |
| // Tests bounds checking for extension methods |
| |
| extension E1<T extends num> on T { |
| int get e1 => 1; |
| } |
| |
| extension E2<T extends S, S extends num> on T { |
| int get e2 => 2; |
| } |
| |
| extension E3<T> on T { |
| S f3<S extends T>(S x) => x; |
| } |
| |
| extension E4<T extends Rec<T>> on T { |
| int get e4 => 4; |
| } |
| |
| class Rec<T extends Rec<T>> {} |
| |
| class RecSolution extends Rec<RecSolution> {} |
| |
| void main() { |
| String s = "s"; |
| int i = 0; |
| double d = 1.0; |
| |
| // Inferred type of String does not satisfy the bound. |
| s.e1; |
| // ^^ |
| // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER |
| // [cfe] unspecified |
| E1(s).e1; |
| //^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| E1<String>(s).e1; |
| // ^^^^^^ |
| // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS |
| // [cfe] unspecified |
| |
| // Inferred types of int and double are ok |
| i.e1; |
| E1(i).e1; |
| E1<int>(i).e1; |
| d.e1; |
| E1(d).e1; |
| E1<double>(d).e1; |
| |
| // Inferred type of String does not satisfy the bound. |
| s.e2; |
| // ^^ |
| // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER |
| // [cfe] unspecified |
| E2(s).e2; |
| //^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| E2<String, num>(s).e2; |
| // ^^^^^^ |
| // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS |
| // [cfe] unspecified |
| |
| // Inferred types of int and double are ok |
| i.e2; |
| E2(i).e2; |
| E2<int, num>(i).e2; |
| d.e2; |
| E2(d).e2; |
| E2<double, num>(d).e2; |
| |
| // Inferred type int for method type parameter doesn't match the inferred |
| // bound of String |
| s.f3(3); |
| // ^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| E3(s).f3(3); |
| // ^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| E3<String>(s).f3(3); |
| // ^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| |
| // Inferred type int for method type parameter is ok |
| i.f3(3); |
| E3(i).f3(3); |
| E3<int>(i).f3(3); |
| |
| // Inferred type int for method type parameter doesn't match the inferred |
| // bound of double |
| d.f3(3); |
| // ^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| E3(d).f3(3); |
| // ^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| E3<double>(d).f3(3); |
| // ^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| |
| RecSolution recs = RecSolution(); |
| Rec<dynamic> superRec = RecSolution(); // Super-bounded type. |
| |
| // Inferred type of RecSolution is ok |
| recs.e4; |
| E4(recs).e4; |
| E4<RecSolution>(recs).e4; |
| |
| // Inferred super-bounded type is invalid as type argument |
| superRec.e4; |
| // ^^ |
| // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER |
| // [cfe] unspecified |
| E4(superRec).e4; |
| //^^ |
| // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER |
| // [cfe] unspecified |
| E4<Rec<dynamic>>(superRec).e4; |
| // ^^^^^^^^^^^^ |
| // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS |
| // [cfe] unspecified |
| } |