// Copyright (c) 2023, 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. // Test that the type arguments of object patterns are properly inferred. import "package:expect/expect.dart"; import "package:expect/static_type_helper.dart"; sealed class B {} class C extends B { final T t; // Note: we use this getter to obtain values for `expectStaticType` (rather // than a getter returning simply `T`) to ensure that an error is reported if // `T` gets inferred to be `dynamic`. List get listOfT => [t]; C(this.t); } bool explicitTypeArguments(B b) { switch (b) { case C(listOfT: var x): x.expectStaticType>>(); // Since C isn't a subtype of B, `b` is not promoted. b.expectStaticType>>(); return true; } // No need for a `return` since the switch is exhaustive. } bool simpleInference(B b) { switch (b) { case C(listOfT: var x): x.expectStaticType>>(); b.expectStaticType>>(); return true; } // No need for a `return` since the switch is exhaustive. } bool inferDynamic(Object o) { switch (o) { case C(listOfT: var x, t: var t): x.expectStaticType>>(); t.isEven; // Should be ok since T is `dynamic`. o.expectStaticType>>(); return true; default: return false; } } class D { final T t; // Note: we use this getter to obtain values for `expectStaticType` (rather // than a getter returning simply `T`) to ensure that an error is reported if // `T` gets inferred to be `dynamic`. List get listOfT => [t]; D(this.t); } bool inferBound(Object o) { switch (o) { case D(listOfT: var x): x.expectStaticType>>(); o.expectStaticType>>(); return true; default: return false; } } class E { final T t; final U u; List get listOfT => [t]; List get listOfU => [u]; E(this.t, this.u); bool inferEnclosingTypeParameters(E, Set> e) { // This test verifies that the inference logic properly distinguishes // between the type parameters of the enclosing class and those that are // part of the type of `e`. if (e case E(listOfT: var x, listOfU: var y)) { x.expectStaticType>>>(); y.expectStaticType>>>(); return true; } // No need for a `return` since the case fully covers the type of `e`. } } class F1> { late final T t; List get listOfT => [t]; } class F2 extends F1 { F2() { t = this; } } bool fBounded(Object o) { switch (o) { case F1(listOfT: var x): x.expectStaticType>>>(); o.expectStaticType>>>(); return true; default: return false; } } class G1 { final T t; List get listOfT => [t]; G1(this.t); } class G2> extends G1 { final U u; List get listOfU => [u]; G2(super.t, this.u); } bool partialInference(G1 g) { switch (g) { case G2(listOfT: var x, listOfU: var y): x.expectStaticType>>(); y.expectStaticType>>>(); g.expectStaticType>>>(); return true; default: return false; } } class H1 { final T t; final U u; List get listOfT => [t]; List get listOfU => [u]; H1(this.t, this.u); } typedef H2 = H1; bool typedefResolvingToInterfaceType(Object o) { switch (o) { case H2(listOfT: var x, listOfU: var y): x.expectStaticType>>(); y.expectStaticType>>(); o.expectStaticType>>(); return true; default: return false; } } typedef I = String Function(S); bool typedefResolvingToFunctionType(Object o) { switch (o) { case I(): o.expectStaticType>>(); return true; default: return false; } } main() { Expect.isTrue(explicitTypeArguments(C(0))); Expect.isTrue(simpleInference(C(0))); Expect.isTrue(inferDynamic(C(0))); Expect.isFalse(inferDynamic(0)); Expect.isTrue(inferBound(D(0))); Expect.isFalse(inferBound(0)); Expect.isTrue( E( 0, '', ).inferEnclosingTypeParameters(E, Set>({''}, {0})), ); Expect.isTrue(fBounded(F2())); Expect.isFalse(fBounded(0)); Expect.isTrue(partialInference(G2(0, {0}))); Expect.isFalse(partialInference(G1(0))); Expect.isTrue(typedefResolvingToInterfaceType(H1(0, ''))); Expect.isTrue(typedefResolvingToInterfaceType(H1(0, ''))); Expect.isFalse(typedefResolvingToInterfaceType(H1(0, ''))); Expect.isTrue(typedefResolvingToFunctionType((Object o) => o.toString())); Expect.isTrue(typedefResolvingToFunctionType((num n) => n.toString())); Expect.isFalse(typedefResolvingToFunctionType((int i) => i.toString())); }