def instantiating_type_replaces_type_in_attributes_of_instantiated_attributes(self): one = types.generic_class("one", ["A"]) two = types.generic_class("two", ["B"]) three = types.generic_class("three", ["C"], lambda C: [ types.attr("value", one(two(C))), ]) assert_equal( one(two(types.int_type)), three(types.int_type).attrs.type_of("value"), )
def instantiated_types_are_not_equal_if_they_have_the_same_substitutions_but_different_generic_type(self): class_type = types.class_type("Blah") first_generic_type = types.generic_class("List", ["T"]) second_generic_type = types.generic_class("List", ["T"]) first_instantiated_type = first_generic_type.instantiate([class_type]) second_instantiated_type = second_generic_type.instantiate([class_type]) assert_not_equal(first_instantiated_type, second_instantiated_type)
def cannot_instantiate_generic_type_with_wrong_number_of_type_parameters(self): generic_type = types.generic_class("Option", ["T"]) try: generic_type(types.int_type, types.int_type) assert False, "Expected error" except Exception as error: assert_equal("generic type requires exactly 1 type parameter(s)", str(error))
def invariant_type_parameter_cannot_have_different_values_in_same_is_sub_type_relation(self): invariant_type_param = types.invariant("T") first_class_type = types.class_type("User") second_class_type = types.class_type("Role") generic_class = types.generic_class("Pair", [invariant_type_param, invariant_type_param]) assert not types.is_sub_type( # TODO: need a reliable way of getting the underlying type (but as an instantiated type) generic_class(invariant_type_param, invariant_type_param), generic_class(first_class_type, second_class_type), unify=[invariant_type_param] )
def contravariant_type_parameter_is_substituted_with_common_sub_type_of_actual_type_params(self): contravariant_type_param = types.contravariant("T") first_class_type = types.class_type("User") second_class_type = types.class_type("Role") generic_class = types.generic_class("Pair", [contravariant_type_param, contravariant_type_param]) type_map = types.is_sub_type( # TODO: need a reliable way of getting the underlying type (but as an instantiated type) generic_class(contravariant_type_param, contravariant_type_param), generic_class(first_class_type, second_class_type), unify=[contravariant_type_param] ) assert_equal(types.bottom_type, type_map[contravariant_type_param])
def instantiated_type_includes_names_of_actual_type_parameters(self): assert_equal("Option[int]", str(types.generic_class("Option", ["T"])(int_type)))
def instantiated_types_are_equal_if_they_have_the_same_substitutions_and_generic_type(self): class_type = types.class_type("Blah") generic_type = types.generic_class("List", "T") first_instantiated_type = generic_type.instantiate([class_type]) second_instantiated_type = generic_type.instantiate([class_type]) assert_equal(first_instantiated_type, second_instantiated_type)
def unification_occurs_before_reification(self): instantiated_type = types.generic_class("blah", ["T"])(int_type) type_map = types.is_sub_type(_formal_param, instantiated_type, unify=[_formal_param]) assert_equal(instantiated_type, type_map[_formal_param])
def instantiated_type_is_not_equal_to_class_type(self): class_type = types.class_type("List") generic_type = types.generic_class("List", "T") instantiated_type = generic_type.instantiate([class_type]) assert_not_equal(class_type, instantiated_type)
def instantiated_class_is_sub_type_of_other_instantiated_class_if_formal_param_is_contravariant_and_type_params_are_supertypes(self): generic_class = types.generic_class("iterator", [types.contravariant("T")]) assert not types.is_sub_type(generic_class(types.object_type), generic_class(types.int_type)) assert types.is_sub_type(generic_class(types.int_type), generic_class(types.object_type))