class TypeOpsSuite(Suite): def set_up(self): self.fx = TypeFixture() # ExpandTypes def test_trivial_expand(self): for t in (self.fx.a, self.fx.o, self.fx.t, self.fx.void, self.fx.nonet, self.tuple(self.fx.a), self.callable([], self.fx.a, self.fx.a), self.fx.anyt): self.assert_expand(t, [], t) self.assert_expand(t, [], t) self.assert_expand(t, [], t) def test_expand_naked_type_var(self): self.assert_expand(self.fx.t, [(1, self.fx.a)], self.fx.a) self.assert_expand(self.fx.t, [(2, self.fx.a)], self.fx.t) def test_expand_basic_generic_types(self): self.assert_expand(self.fx.gt, [(1, self.fx.a)], self.fx.ga) # IDEA: Add test cases for # tuple types # callable types # multiple arguments def assert_expand(self, orig, map_items, result): lower_bounds = {} for id, t in map_items: lower_bounds[id] = t exp = expand_type(orig, lower_bounds) # Remove erased tags (asterisks). assert_equal(str(exp).replace('*', ''), str(result)) # ReplaceTypeVars def test_trivial_replace(self): for t in (self.fx.a, self.fx.o, self.fx.void, self.fx.nonet, self.tuple(self.fx.a), self.callable([], self.fx.a, self.fx.a), self.fx.anyt, self.fx.err): self.assert_replace(t, t) def test_replace_type_var(self): self.assert_replace(self.fx.t, self.fx.anyt) def test_replace_generic_instance(self): self.assert_replace(self.fx.ga, self.fx.ga) self.assert_replace(self.fx.gt, self.fx.gdyn) def assert_replace(self, orig, result): assert_equal(str(replace_type_vars(orig)), str(result)) # EraseType def test_trivial_erase(self): for t in (self.fx.a, self.fx.o, self.fx.void, self.fx.nonet, self.fx.anyt, self.fx.err): self.assert_erase(t, t) def test_erase_with_type_variable(self): self.assert_erase(self.fx.t, self.fx.anyt) def test_erase_with_generic_type(self): self.assert_erase(self.fx.ga, self.fx.gdyn) self.assert_erase(self.fx.hab, Instance(self.fx.hi, [self.fx.anyt, self.fx.anyt])) def test_erase_with_tuple_type(self): self.assert_erase(self.tuple(self.fx.a), self.fx.std_tuple) def test_erase_with_function_type(self): self.assert_erase(self.fx.callable(self.fx.a, self.fx.b), self.fx.callable_type(self.fx.void)) def test_erase_with_type_object(self): self.assert_erase(self.fx.callable_type(self.fx.a, self.fx.b), self.fx.callable_type(self.fx.void)) def assert_erase(self, orig, result): assert_equal(str(erase_type(orig, self.fx.basic)), str(result)) # Helpers def tuple(self, *a): return TupleType(a) Callable callable(self, vars, *a): """callable(args, a1, ..., an, r) constructs a callable with argument types a1, ... an and return type r and type arguments vars. """ tv = <TypeVarDef> [] n = -1 for v in vars: tv.append(TypeVarDef(v, n)) n -= 1 return Callable(a[:-1], [ARG_POS] * (len(a) - 1), <str> [None] * (len(a) - 1), a[-1], False, None, TypeVars(tv))
class SubtypingSuite(Suite): def set_up(self): self.fx = TypeFixture() def test_trivial_cases(self): for simple in self.fx.void, self.fx.a, self.fx.o, self.fx.b: self.assert_subtype(simple, simple) def test_instance_subtyping(self): self.assert_proper_subtype(self.fx.a, self.fx.o) self.assert_proper_subtype(self.fx.b, self.fx.o) self.assert_proper_subtype(self.fx.b, self.fx.a) self.assert_not_subtype(self.fx.a, self.fx.d) self.assert_not_subtype(self.fx.b, self.fx.c) def test_simple_generic_instance_subtyping(self): self.assert_subtype(self.fx.ga, self.fx.ga) self.assert_subtype(self.fx.hab, self.fx.hab) self.assert_not_subtype(self.fx.ga, self.fx.g2a) self.assert_not_subtype(self.fx.ga, self.fx.gb) self.assert_not_subtype(self.fx.gb, self.fx.ga) def test_generic_subtyping_with_inheritance(self): self.assert_subtype(self.fx.gsab, self.fx.gb) self.assert_not_subtype(self.fx.gsab, self.fx.ga) def test_interface_subtyping(self): self.assert_subtype(self.fx.e, self.fx.f) self.assert_equivalent(self.fx.f, self.fx.f) self.assert_not_subtype(self.fx.a, self.fx.f) def test_generic_interface_subtyping(self): # TODO make this work self.skip() fx2 = InterfaceTypeFixture() self.assert_subtype(fx2.m1, fx2.gfa) self.assert_not_subtype(fx2.m1, fx2.gfb) self.assert_equivalent(fx2.gfa, fx2.gfa) def test_basic_callable_subtyping(self): self.assert_proper_subtype(self.fx.callable(self.fx.o, self.fx.d), self.fx.callable(self.fx.a, self.fx.d)) self.assert_proper_subtype(self.fx.callable(self.fx.d, self.fx.b), self.fx.callable(self.fx.d, self.fx.a)) self.assert_unrelated(self.fx.callable(self.fx.a, self.fx.a), self.fx.callable(self.fx.a, self.fx.void)) self.assert_unrelated( self.fx.callable(self.fx.a, self.fx.a, self.fx.a), self.fx.callable(self.fx.a, self.fx.a)) def test_default_arg_callable_subtyping(self): self.assert_proper_subtype( self.fx.callable_default(1, self.fx.a, self.fx.d, self.fx.a), self.fx.callable(self.fx.a, self.fx.d, self.fx.a)) self.assert_proper_subtype( self.fx.callable_default(1, self.fx.a, self.fx.d, self.fx.a), self.fx.callable(self.fx.a, self.fx.a)) self.assert_proper_subtype( self.fx.callable_default(0, self.fx.a, self.fx.d, self.fx.a), self.fx.callable_default(1, self.fx.a, self.fx.d, self.fx.a)) self.assert_unrelated( self.fx.callable_default(1, self.fx.a, self.fx.d, self.fx.a), self.fx.callable(self.fx.d, self.fx.d, self.fx.a)) self.assert_unrelated( self.fx.callable_default(0, self.fx.a, self.fx.d, self.fx.a), self.fx.callable_default(1, self.fx.a, self.fx.a, self.fx.a)) self.assert_unrelated( self.fx.callable_default(1, self.fx.a, self.fx.a), self.fx.callable(self.fx.a, self.fx.a, self.fx.a)) def test_var_arg_callable_subtyping(self): self.assert_proper_subtype( self.fx.callable_var_arg(0, self.fx.a, self.fx.a), self.fx.callable_var_arg(0, self.fx.b, self.fx.a)) self.assert_unrelated( self.fx.callable_var_arg(0, self.fx.a, self.fx.a), self.fx.callable(self.fx.a, self.fx.a)) self.assert_proper_subtype( self.fx.callable_var_arg(0, self.fx.a, self.fx.a), self.fx.callable(self.fx.a)) self.assert_proper_subtype( self.fx.callable_var_arg(1, self.fx.a, self.fx.d, self.fx.a), self.fx.callable(self.fx.a, self.fx.a)) self.assert_proper_subtype( self.fx.callable_var_arg(0, self.fx.a, self.fx.d, self.fx.a), self.fx.callable(self.fx.a, self.fx.a)) def test_type_callable_subtyping(self): self.assert_proper_subtype( self.fx.callable_type(self.fx.d, self.fx.a), self.fx.std_type) self.assert_proper_subtype( self.fx.callable_type(self.fx.d, self.fx.b), self.fx.callable(self.fx.d, self.fx.a)) self.assert_proper_subtype(self.fx.callable_type(self.fx.a, self.fx.b), self.fx.callable(self.fx.a, self.fx.b)) # IDEA: Maybe add these test cases (they are tested pretty well in type # checker tests already): # * more interface subtyping test cases # * more generic interface subtyping test cases # * type variables # * tuple types # * void type # * None type # * any type # * generic function types def assert_subtype(self, s, t): assert_true(is_subtype(s, t), '{} not subtype of {}'.format(s, t)) def assert_not_subtype(self, s, t): assert_true(not is_subtype(s, t), '{} subtype of {}'.format(s, t)) def assert_proper_subtype(self, s, t): self.assert_subtype(s, t) self.assert_not_subtype(t, s) def assert_equivalent(self, s, t): self.assert_subtype(s, t) self.assert_subtype(t, s) def assert_unrelated(self, s, t): self.assert_not_subtype(s, t) self.assert_not_subtype(t, s)