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:
@@ -379,6 +379,9 @@ class TypeVar(object):
|
|||||||
|
|
||||||
def free_typevar(self):
|
def free_typevar(self):
|
||||||
# type: () -> TypeVar
|
# type: () -> TypeVar
|
||||||
|
"""
|
||||||
|
Get the free type variable controlling this one.
|
||||||
|
"""
|
||||||
if self.is_derived:
|
if self.is_derived:
|
||||||
return self.base
|
return self.base
|
||||||
elif self.singleton_type:
|
elif self.singleton_type:
|
||||||
@@ -386,3 +389,32 @@ class TypeVar(object):
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return self
|
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`.
|
||||||
|
|||||||
Reference in New Issue
Block a user