def types_to_proto(self, valuetype: type) -> proto.MIL_pb2.ValueType:
        """
        Return proto.MIL_pb2.ValueType from PyMIL types.
        """
        if types.is_tensor(valuetype):
            primitive = types_to_proto_primitive(valuetype.get_primitive())
            return create_valuetype_tensor(valuetype.get_shape(), primitive)
        elif types.is_tuple(valuetype):
            v_type = proto.MIL_pb2.ValueType()
            t_type = v_type.tupleType
            for t in valuetype.T:
                new_v_type = t_type.types.add()
                new_v_type.CopyFrom(self.types_to_proto(t))
            return v_type
        elif types.is_list(valuetype):
            elem = valuetype.T[0]
            length = valuetype.T[1]
            if types.is_tensor(elem):
                dtype = types_to_proto_primitive(elem.get_primitive())
                elem_shape = elem.get_shape()
            elif types.is_scalar(elem):
                dtype = types_to_proto_primitive(valuetype)
                elem_shape = ()
            elif types.is_str(elem):
                dtype = types_to_proto_primitive(elem)
                elem_shape = ()
            else:
                raise NotImplementedError(
                    "Only list of either tensors or scalars supported. "
                    "Got element of type {}".format(elem.__type_info__())
                )
            return create_valuetype_list(length=length, elem_shape=elem_shape, dtype=dtype)
        elif types.is_dict(valuetype):
            return self.create_valuetype_dict(valuetype.T[0], valuetype.T[1])
        elif types.is_state(valuetype):
            wrapped_type = valuetype.wrapped_type()
            v_type = proto.MIL_pb2.ValueType()
            v_type.stateType.wrappedType.CopyFrom(self.types_to_proto(wrapped_type))
            return v_type
        else:
            return create_valuetype_scalar(types_to_proto_primitive(valuetype))

        Return proto.MIL_pb2.ValueType from PyMIL types.
        
coremltools/converters/mil/backend/mil/load.py