Add a TypeVar.constrain_types() function.

This reduces the set of types a type variable can assume.

This implementation is not complete yet, so it may yield type sets that
are too large.
This commit is contained in:
Jakob Stoklund Olesen
2016-11-09 15:19:03 -08:00
parent 129fd4b06e
commit 38f4b9a7c8

View File

@@ -379,6 +379,9 @@ class TypeVar(object):
def free_typevar(self):
# type: () -> TypeVar
"""
Get the free type variable controlling this one.
"""
if self.is_derived:
return self.base
elif self.singleton_type:
@@ -386,3 +389,32 @@ class TypeVar(object):
return None
else:
return self
def constrain_types(self, other):
# type: (TypeVar) -> None
"""
Constrain the range of types this variable can assume to a subset of
those `other` can assume.
If this is a SAMEAS-derived type variable, constrain the base instead.
"""
a = self.strip_sameas()
b = other.strip_sameas()
if a is b:
return
if not a.is_derived and not b.is_derived:
a.type_set &= b.type_set
# TODO: What if a.type_set becomes empty?
if not a.singleton_type:
a.singleton_type = b.singleton_type
return
# TODO: Implement constraints for derived type variables.
#
# If a and b are both derived with the same derived_func, we could say
# `a.base.constrain_types(b.base)`, but unless the derived_func is
# injective, that may constrain `a.base` more than necessary.
#
# For the fully general case, we would need to compute an image typeset
# for `b` and propagate a `a.derived_func` pre-image to `a.base`.