| // Copyright (c) 2021, 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 the new context type rules for number operators, | |
| // as modified by Null Safety | |
| import "package:expect/static_type_helper.dart"; | |
| // The context rules for `e` of the form: | |
| // For e1 + e2, e1 - e2, e1 * e2, e1 % e2 or e1.remainder(e2),, | |
| // if the static type of e1 is a non-`Never` subtype of `int`, | |
| // and the context type of the entire expression is `int`, | |
| // then the context type of e2 is `int`. | |
| // If the static type of e1 is a non-`Never` subtype of `num` | |
| // that is not a subtype of `double`, | |
| // and the context type of the entire expression is `double`, | |
| // then the context type of e2 is `double`. | |
| // If the context type of `e1.clamp(e2, e3)`, *C*, | |
| // and the the static type of `e1`, *T*, | |
| // are both is a non-`Never` subtypes of `num`, | |
| // then the context types of `e2` and `e3` are both *C*. | |
| // Otherwise the context types of `e2` and `e3` are `num`. | |
| void main() { | |
| testIntContext<int, Object>(1, 1); | |
| testDoubleContext<int, double, num, Object>(1, 1.1, 1.1, 1.1); | |
| testNumContext<num, Object>(1, 1); | |
| } | |
| void testIntContext<I extends int, O extends Object>(I i, O o) { | |
| context<int>(1 + (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(1 - (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(1 * (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(1 % (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(1.remainder(contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(i + (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(i - (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(i * (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(i % (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(i.remainder(contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<num>(1 + (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(1 - (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(1 * (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(1 % (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(1.remainder(contextType(1)..expectStaticType<Exactly<num>>())); | |
| O oi = 1 as O; | |
| if (oi is! int) throw "promote oi to O&int"; | |
| context<int>(oi + (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(oi - (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(oi * (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(oi % (contextType(1)..expectStaticType<Exactly<int>>())); | |
| context<int>(oi.remainder(contextType(1)..expectStaticType<Exactly<int>>())); | |
| int ii = 0; | |
| ii += contextType(1)..expectStaticType<Exactly<int>>(); | |
| ii -= contextType(1)..expectStaticType<Exactly<int>>(); | |
| ii *= contextType(1)..expectStaticType<Exactly<int>>(); | |
| ii %= contextType(1)..expectStaticType<Exactly<int>>(); | |
| if (ii != 0) throw "use ii"; | |
| context<int>( | |
| 1.clamp( | |
| contextType(1)..expectStaticType<Exactly<int>>(), | |
| contextType(1)..expectStaticType<Exactly<int>>(), | |
| ), | |
| ); | |
| context<int>( | |
| i.clamp( | |
| contextType(1)..expectStaticType<Exactly<int>>(), | |
| contextType(1)..expectStaticType<Exactly<int>>(), | |
| ), | |
| ); | |
| context<int>( | |
| oi.clamp( | |
| contextType(1)..expectStaticType<Exactly<int>>(), | |
| contextType(1)..expectStaticType<Exactly<int>>(), | |
| ), | |
| ); | |
| } | |
| void testDoubleContext< | |
| I extends int, | |
| D extends double, | |
| N extends num, | |
| O extends Object | |
| >(I i, D d, N n, O o) { | |
| context<double>(1 + (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(1 - (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(1 * (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(1 % (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>( | |
| 1.remainder(contextType(1.0)..expectStaticType<Exactly<double>>()), | |
| ); | |
| context<double>(n + (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(n - (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(n * (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(n % (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>( | |
| n.remainder(contextType(1.0)..expectStaticType<Exactly<double>>()), | |
| ); | |
| context<double>(i + (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(i - (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(i * (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>(i % (contextType(1.0)..expectStaticType<Exactly<double>>())); | |
| context<double>( | |
| i.remainder(contextType(1.0)..expectStaticType<Exactly<double>>()), | |
| ); | |
| context<double>(d + (contextType(1.0)..expectStaticType<Exactly<num>>())); | |
| context<double>(d - (contextType(1.0)..expectStaticType<Exactly<num>>())); | |
| context<double>(d * (contextType(1.0)..expectStaticType<Exactly<num>>())); | |
| context<double>(d % (contextType(1.0)..expectStaticType<Exactly<num>>())); | |
| context<double>( | |
| d.remainder(contextType(1.0)..expectStaticType<Exactly<num>>()), | |
| ); | |
| var od = (1.0 as O); | |
| if (od is! double) throw "promote od to O&double"; | |
| context<double>(od + (contextType(1.0)..expectStaticType<Exactly<num>>())); | |
| context<double>(od - (contextType(1.0)..expectStaticType<Exactly<num>>())); | |
| context<double>(od * (contextType(1.0)..expectStaticType<Exactly<num>>())); | |
| context<double>(od % (contextType(1.0)..expectStaticType<Exactly<num>>())); | |
| context<double>( | |
| od.remainder(contextType(1.0)..expectStaticType<Exactly<num>>()), | |
| ); | |
| // The context type also causes double literals. | |
| context<double>(1 + (1..expectStaticType<Exactly<double>>())); | |
| context<double>(1 - (1..expectStaticType<Exactly<double>>())); | |
| context<double>(1 * (1..expectStaticType<Exactly<double>>())); | |
| context<double>(1 % (1..expectStaticType<Exactly<double>>())); | |
| context<double>(1.remainder(1..expectStaticType<Exactly<double>>())); | |
| double dd = 0.0; | |
| dd += contextType(1)..expectStaticType<Exactly<num>>(); | |
| dd -= contextType(1)..expectStaticType<Exactly<num>>(); | |
| dd *= contextType(1)..expectStaticType<Exactly<num>>(); | |
| dd %= contextType(2)..expectStaticType<Exactly<num>>(); | |
| context<double>( | |
| 1.1.clamp( | |
| contextType(1.0)..expectStaticType<Exactly<double>>(), | |
| contextType(1.0)..expectStaticType<Exactly<double>>(), | |
| ), | |
| ); | |
| context<double>( | |
| d.clamp( | |
| contextType(1.0)..expectStaticType<Exactly<double>>(), | |
| contextType(1.0)..expectStaticType<Exactly<double>>(), | |
| ), | |
| ); | |
| context<double>( | |
| od.clamp( | |
| contextType(1.0)..expectStaticType<Exactly<double>>(), | |
| contextType(1.0)..expectStaticType<Exactly<double>>(), | |
| ), | |
| ); | |
| } | |
| void testNumContext<N extends num, O extends Object>(N n, O o) { | |
| var i1 = 1; | |
| var d1 = 1.0; | |
| num n1 = 1; | |
| if (o is! num) throw "promote o to O&num"; | |
| context<num>(i1 + (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(i1 - (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(i1 * (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(i1 % (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(i1.remainder(contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(d1 + (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(d1 - (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(d1 * (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(d1 % (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(d1.remainder(contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n1 + (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n1 - (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n1 * (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n1 % (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n1.remainder(contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n + (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n - (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n * (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n % (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(n.remainder(contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(o + (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(o - (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(o * (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(o % (contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>(o.remainder(contextType(1)..expectStaticType<Exactly<num>>())); | |
| context<num>( | |
| o.clamp( | |
| contextType(1)..expectStaticType<Exactly<num>>(), | |
| contextType(1)..expectStaticType<Exactly<num>>(), | |
| ), | |
| ); | |
| } |