Exemple #1
0
def apply_generic_arguments(callable: CallableType, types: List[Type],
                            msg: MessageBuilder,
                            context: Context) -> CallableType:
    """Apply generic type arguments to a callable type.

    For example, applying [int] to 'def [T] (T) -> T' results in
    'def (int) -> int'.

    Note that each type can be None; in this case, it will not be applied.
    """
    tvars = callable.variables
    assert len(tvars) == len(types)
    # Check that inferred type variable values are compatible with allowed
    # values and bounds.  Also, promote subtype values to allowed values.
    types = types[:]
    for i, type in enumerate(types):
        values = callable.variables[i].values
        if values and type:
            if isinstance(type, AnyType):
                continue
            if isinstance(type, TypeVarType) and type.values:
                # Allow substituting T1 for T if every allowed value of T1
                # is also a legal value of T.
                if all(
                        any(is_same_type(v, v1) for v in values)
                        for v1 in type.values):
                    continue
            for value in values:
                if isinstance(type, PartialType) or mypy.subtypes.is_subtype(
                        type, value):
                    types[i] = value
                    break
            else:
                msg.incompatible_typevar_value(callable, type,
                                               callable.variables[i].name,
                                               context)
        upper_bound = callable.variables[i].upper_bound
        if (type and not isinstance(type, PartialType)
                and not mypy.subtypes.is_subtype(type, upper_bound)):
            msg.incompatible_typevar_value(callable, type,
                                           callable.variables[i].name, context)

    # Create a map from type variable id to target type.
    id_to_type = {}  # type: Dict[TypeVarId, Type]
    for i, tv in enumerate(tvars):
        if types[i]:
            id_to_type[tv.id] = types[i]

    # Apply arguments to argument types.
    arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]

    # The callable may retain some type vars if only some were applied.
    remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]

    return callable.copy_modified(
        arg_types=arg_types,
        ret_type=expand_type(callable.ret_type, id_to_type),
        variables=remaining_tvars,
    )
Exemple #2
0
def apply_generic_arguments(callable: CallableType, types: List[Type],
                            msg: MessageBuilder, context: Context) -> Type:
    """Apply generic type arguments to a callable type.

    For example, applying [int] to 'def [T] (T) -> T' results in
    'def (int) -> int'.

    Note that each type can be None; in this case, it will not be applied.
    """
    tvars = callable.variables
    if len(tvars) != len(types):
        msg.incompatible_type_application(len(tvars), len(types), context)
        return AnyType()

    # Check that inferred type variable values are compatible with allowed
    # values and bounds.  Also, promote subtype values to allowed values.
    types = types[:]
    for i, type in enumerate(types):
        values = callable.variables[i].values
        if values and type:
            if isinstance(type, AnyType):
                continue
            if isinstance(type, TypeVarType) and type.values:
                # Allow substituting T1 for T if every allowed value of T1
                # is also a legal value of T.
                if all(any(is_same_type(v, v1) for v in values)
                       for v1 in type.values):
                    continue
            for value in values:
                if mypy.subtypes.is_subtype(type, value):
                    types[i] = value
                    break
            else:
                msg.incompatible_typevar_value(callable, i + 1, type, context)

        upper_bound = callable.variables[i].upper_bound
        if type and not mypy.subtypes.satisfies_upper_bound(type, upper_bound):
            msg.incompatible_typevar_value(callable, i + 1, type, context)

    # Create a map from type variable id to target type.
    id_to_type = {}  # type: Dict[TypeVarId, Type]
    for i, tv in enumerate(tvars):
        if types[i]:
            id_to_type[tv.id] = types[i]

    # Apply arguments to argument types.
    arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]

    # The callable may retain some type vars if only some were applied.
    remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]

    return callable.copy_modified(
        arg_types=arg_types,
        ret_type=expand_type(callable.ret_type, id_to_type),
        variables=remaining_tvars,
    )
Exemple #3
0
def apply_generic_arguments(callable: CallableType, types: List[Type],
                            msg: MessageBuilder, context: Context) -> Type:
    """Apply generic type arguments to a callable type.

    For example, applying [int] to 'def [T] (T) -> T' results in
    'def [-1:int] (int) -> int'. Here '[-1:int]' is an implicit bound type
    variable.

    Note that each type can be None; in this case, it will not be applied.
    """
    tvars = callable.variables
    if len(tvars) != len(types):
        msg.incompatible_type_application(len(tvars), len(types), context)
        return AnyType()

    # Check that inferred type variable values are compatible with allowed
    # values.  Also, promote subtype values to allowed values.
    types = types[:]
    for i, type in enumerate(types):
        values = callable.variables[i].values
        if values and type:
            if isinstance(type, AnyType):
                continue
            for value in values:
                if mypy.subtypes.is_subtype(type, value):
                    types[i] = value
                    break
            else:
                msg.incompatible_typevar_value(callable, i + 1, type, context)

    # Create a map from type variable id to target type.
    id_to_type = {}  # type: Dict[int, Type]
    for i, tv in enumerate(tvars):
        if types[i]:
            id_to_type[tv.id] = types[i]

    # Apply arguments to argument types.
    arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]

    bound_vars = [(tv.id, id_to_type[tv.id])
                  for tv in tvars
                  if tv.id in id_to_type]

    # The callable may retain some type vars if only some were applied.
    remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]

    return CallableType(arg_types,
                    callable.arg_kinds,
                    callable.arg_names,
                    expand_type(callable.ret_type, id_to_type),
                    callable.fallback,
                    callable.name,
                    remaining_tvars,
                    callable.bound_vars + bound_vars,
                    callable.line, callable.repr)
Exemple #4
0
def apply_generic_arguments(
        callable: CallableType, orig_types: Sequence[Optional[Type]],
        report_incompatible_typevar_value: Callable[[CallableType, Type, str, Context], None],
        context: Context,
        skip_unsatisfied: bool = False) -> CallableType:
    """Apply generic type arguments to a callable type.

    For example, applying [int] to 'def [T] (T) -> T' results in
    'def (int) -> int'.

    Note that each type can be None; in this case, it will not be applied.

    If `skip_unsatisfied` is True, then just skip the types that don't satisfy type variable
    bound or constraints, instead of giving an error.
    """
    tvars = callable.variables
    assert len(tvars) == len(orig_types)
    # Check that inferred type variable values are compatible with allowed
    # values and bounds.  Also, promote subtype values to allowed values.
    types = get_proper_types(orig_types)

    # Create a map from type variable id to target type.
    id_to_type: Dict[TypeVarId, Type] = {}

    for tvar, type in zip(tvars, types):
        assert not isinstance(type, PartialType), "Internal error: must never apply partial type"
        if type is None:
            continue

        target_type = get_target_type(
            tvar, type, callable, report_incompatible_typevar_value, context, skip_unsatisfied
        )
        if target_type is not None:
            id_to_type[tvar.id] = target_type

    param_spec = callable.param_spec()
    if param_spec is not None:
        nt = id_to_type.get(param_spec.id)
        if nt is not None:
            nt = get_proper_type(nt)
            if isinstance(nt, CallableType):
                callable = callable.expand_param_spec(nt)

    # Apply arguments to argument types.
    arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]

    # The callable may retain some type vars if only some were applied.
    remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]

    return callable.copy_modified(
        arg_types=arg_types,
        ret_type=expand_type(callable.ret_type, id_to_type),
        variables=remaining_tvars,
    )
Exemple #5
0
def apply_generic_arguments(callable: CallableType, types: List[Type],
                            msg: MessageBuilder, context: Context) -> Type:
    """Apply generic type arguments to a callable type.

    For example, applying [int] to 'def [T] (T) -> T' results in
    'def [-1:int] (int) -> int'. Here '[-1:int]' is an implicit bound type
    variable.

    Note that each type can be None; in this case, it will not be applied.
    """
    tvars = callable.variables
    if len(tvars) != len(types):
        msg.incompatible_type_application(len(tvars), len(types), context)
        return AnyType()

    # Check that inferred type variable values are compatible with allowed
    # values.  Also, promote subtype values to allowed values.
    types = types[:]
    for i, type in enumerate(types):
        values = callable.variables[i].values
        if values and type:
            if isinstance(type, AnyType):
                continue
            for value in values:
                if mypy.subtypes.is_subtype(type, value):
                    types[i] = value
                    break
            else:
                msg.incompatible_typevar_value(callable, i + 1, type, context)

    # Create a map from type variable id to target type.
    id_to_type = {}  # type: Dict[int, Type]
    for i, tv in enumerate(tvars):
        if types[i]:
            id_to_type[tv.id] = types[i]

    # Apply arguments to argument types.
    arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]

    bound_vars = [(tv.id, id_to_type[tv.id]) for tv in tvars
                  if tv.id in id_to_type]

    # The callable may retain some type vars if only some were applied.
    remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]

    return callable.copy_modified(
        arg_types=arg_types,
        ret_type=expand_type(callable.ret_type, id_to_type),
        variables=remaining_tvars,
        bound_vars=callable.bound_vars + bound_vars,
    )
Exemple #6
0
 def _create_partial_case(
     self,
     case_function: CallableType,
     intermediate: CallableType,
     constraints: _Constraints,
 ) -> CallableType:
     partial = cast(
         CallableType,
         expand_type(
             _Functions(case_function, intermediate).diff(),
             constraints,
         ))
     if case_function.is_generic():
         # We can deal with really different `case_function` over here.
         # The first one is regular `generic` function
         # that has variables and typevars in its spec.
         # In this case, we process `partial` the same way.
         # It should be generic also.
         #
         # The second possible type of `case_function` is pseudo-generic.
         # These are functions that contain typevars in its spec,
         # but variables are empty.
         # Probably these functions are already used in a generic context.
         # So, we ignore them and do not add variables back.
         #
         # Regular functions are also untouched by this.
         return detach_callable(partial)
     return partial.copy_modified(variables=[])
Exemple #7
0
 def from_usage(
     self,
     applied_args: List[FuncArg],
 ) -> CallableType:
     """Infers function constrains from its usage: passed arguments."""
     constraints = self._infer_constraints(applied_args)
     infered = expand_type(self._case_function, constraints)
     return cast(CallableType, infered)
Exemple #8
0
    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))
Exemple #9
0
    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))
Exemple #10
0
def map_instance_to_direct_supertype(instance, supertype):
    typ = instance.type
    
    for b in typ.bases:
        # The cast below cannot fail since we require that semantic analysis
        # was successful, so bases cannot contain unbound types.
        if b and (b).type == supertype:
            map = type_var_map(typ, instance.args)
            return expand_type(b, map)
    
    # Relationship with the supertype not specified explicitly. Use dynamic
    # type arguments implicitly.
    return Instance(typ.base, [Any()] * len(typ.base.type_vars))
Exemple #11
0
def map_instance_to_direct_supertype(instance: Instance,
                                     supertype: TypeInfo) -> Instance:
    typ = instance.type
    
    for base in typ.bases:
        if base.type == supertype:
            map = type_var_map(typ, instance.args)
            return cast(Instance, expand_type(base, map))
    
    # Relationship with the supertype not specified explicitly. Use AnyType
    # type arguments implicitly.
    # TODO Should this be an error instead?
    return Instance(supertype, [AnyType()] * len(supertype.type_vars))
Exemple #12
0
    def assert_expand(self,
                      orig: Type,
                      map_items: List[Tuple[TypeVarId, Type]],
                      result: Type,
                      ) -> None:
        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))
Exemple #13
0
    def assert_expand(self,
                      orig: Type,
                      map_items: List[Tuple[TypeVarId, Type]],
                      result: Type,
                      ) -> None:
        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))
Exemple #14
0
def map_instance_to_direct_supertype(instance: Instance,
                                     supertype: TypeInfo) -> Instance:
    typ = instance.type

    for base in typ.bases:
        if base.type == supertype:
            map = type_var_map(typ, instance.args)
            return cast(Instance, expand_type(base, map))

    # Relationship with the supertype not specified explicitly. Use AnyType
    # type arguments implicitly.
    # TODO Should this be an error instead?
    return Instance(supertype, [AnyType()] * len(supertype.type_vars))
Exemple #15
0
def map_instance_to_direct_supertypes(instance: Instance,
                                      supertype: TypeInfo) -> List[Instance]:
    # FIX: There should only be one supertypes, always.
    typ = instance.type
    result = [] # type: List[Instance]
    
    for b in typ.bases:
        if b.type == supertype:
            map = type_var_map(typ, instance.args)
            result.append(cast(Instance, expand_type(b, map)))
    
    if result:
        return result
    else:
        # Relationship with the supertype not specified explicitly. Use dynamic
        # type arguments implicitly.
        return [Instance(supertype, [AnyType()] * len(supertype.type_vars))]
Exemple #16
0
def map_instance_to_direct_supertypes(instance: Instance,
                                      supertype: TypeInfo) -> List[Instance]:
    # FIX: There should only be one supertypes, always.
    typ = instance.type
    result = []  # type: List[Instance]

    for b in typ.bases:
        if b.type == supertype:
            env = instance_to_type_environment(instance)
            result.append(cast(Instance, expand_type(b, env)))

    if result:
        return result
    else:
        # Relationship with the supertype not specified explicitly. Use dynamic
        # type arguments implicitly.
        return [Instance(supertype, [AnyType()] * len(supertype.type_vars))]
Exemple #17
0
def map_instance_to_direct_supertypes(instance, supertype):
    # FIX: There should only be one supertypes, always.
    typ = instance.type
    result = []
    
    for b in typ.bases:
        # The cast below cannot fail since we require that semantic analysis
        # was successful, so bases cannot contain unbound types.
        if b and (b).type == supertype:
            map = type_var_map(typ, instance.args)
            result.append(expand_type(b, map))
    
    if result:
        return result
    else:
        # Relationship with the supertype not specified explicitly. Use dynamic
        # type arguments implicitly.
        return [Instance(supertype, [Any()] * len(supertype.type_vars))]
Exemple #18
0
def map_instance_to_direct_supertypes(instance: Instance,
                                      supertype: TypeInfo) -> List[Instance]:
    # FIX: There should only be one supertypes, always.
    typ = instance.type
    result = []  # type: List[Instance]

    for b in typ.bases:
        if b.type == supertype:
            env = instance_to_type_environment(instance)
            t = expand_type(b, env)
            assert isinstance(t, Instance)
            result.append(t)

    if result:
        return result
    else:
        # Relationship with the supertype not specified explicitly. Use dynamic
        # type arguments implicitly.
        return [Instance(supertype, [AnyType()] * len(supertype.type_vars))]
Exemple #19
0
def map_instance_to_direct_supertypes(instance: Instance,
                                      supertype: TypeInfo) -> List[Instance]:
    # FIX: There should only be one supertypes, always.
    typ = instance.type
    result = []  # type: List[Instance]

    for b in typ.bases:
        if b.type == supertype:
            env = instance_to_type_environment(instance)
            t = expand_type(b, env)
            assert isinstance(t, ProperType)
            assert isinstance(t, Instance)
            result.append(t)

    if result:
        return result
    else:
        # Relationship with the supertype not specified explicitly. Use dynamic
        # type arguments implicitly.
        any_type = AnyType(TypeOfAny.unannotated)
        return [Instance(supertype, [any_type] * len(supertype.type_vars))]
Exemple #20
0
 def expand(target: Type) -> Type:
     return expand_type(target,
                        {id: to_apply[all_ids.index(id)]
                         for id in ids})
Exemple #21
0
 def expand(target: Type) -> Type:
     return expand_type(target, {func.variables[0].id: typearg})
Exemple #22
0
                                                    instance.type.base)
        if instance.type == supertype: break
    
    return instance


Instance map_instance_to_direct_supertype(Instance instance,
                                          TypeInfo supertype):
    typ = instance.type
    
    for b in typ.bases:
        # The cast below cannot fail since we require that semantic analysis
        # was successful, so bases cannot contain unbound types.
        if b and ((Instance)b).type == supertype:
            map = type_var_map(typ, instance.args)
            return (Instance)expand_type(b, map)
    
    # Relationship with the supertype not specified explicitly. Use dynamic
    # type arguments implicitly.
    return Instance(typ.base, <Type> [Any()] * len(typ.base.type_vars))


dict<int, Type> type_var_map(TypeInfo typ, Type[] args):
    if not args:
        return None
    else:
        tvars = <int, Type> {}
        for i in range(len(args)):
            tvars[i + 1] = args[i]
        return tvars
Exemple #23
0
 def expand(target: Type) -> Type:
     return expand_type(target, {func.variables[0].id: typearg})
Exemple #24
0
 def expand(target: Type) -> Type:
     assert typearg is not None
     return expand_type(target, {func.variables[0].id: typearg})
Exemple #25
0
 def expand(target: Type) -> Type:
     assert typearg is not None
     return expand_type(target, {func.variables[0].id: typearg})
Exemple #26
0
def apply_generic_arguments(callable: CallableType, orig_types: Sequence[Optional[Type]],
                            msg: MessageBuilder, context: Context,
                            skip_unsatisfied: bool = False) -> CallableType:
    """Apply generic type arguments to a callable type.

    For example, applying [int] to 'def [T] (T) -> T' results in
    'def (int) -> int'.

    Note that each type can be None; in this case, it will not be applied.

    If `skip_unsatisfied` is True, then just skip the types that don't satisfy type variable
    bound or constraints, instead of giving an error.
    """
    tvars = callable.variables
    assert len(tvars) == len(orig_types)
    # Check that inferred type variable values are compatible with allowed
    # values and bounds.  Also, promote subtype values to allowed values.
    types = list(orig_types)
    for i, type in enumerate(types):
        assert not isinstance(type, PartialType), "Internal error: must never apply partial type"
        values = callable.variables[i].values
        if type is None:
            continue
        if values:
            if isinstance(type, AnyType):
                continue
            if isinstance(type, TypeVarType) and type.values:
                # Allow substituting T1 for T if every allowed value of T1
                # is also a legal value of T.
                if all(any(is_same_type(v, v1) for v in values)
                       for v1 in type.values):
                    continue
            matching = []
            for value in values:
                if mypy.subtypes.is_subtype(type, value):
                    matching.append(value)
            if matching:
                best = matching[0]
                # If there are more than one matching value, we select the narrowest
                for match in matching[1:]:
                    if mypy.subtypes.is_subtype(match, best):
                        best = match
                types[i] = best
            else:
                if skip_unsatisfied:
                    types[i] = None
                else:
                    msg.incompatible_typevar_value(callable, type, callable.variables[i].name,
                                                   context)
        else:
            upper_bound = callable.variables[i].upper_bound
            if not mypy.subtypes.is_subtype(type, upper_bound):
                if skip_unsatisfied:
                    types[i] = None
                else:
                    msg.incompatible_typevar_value(callable, type, callable.variables[i].name,
                                                   context)

    # Create a map from type variable id to target type.
    id_to_type = {}  # type: Dict[TypeVarId, Type]
    for i, tv in enumerate(tvars):
        typ = types[i]
        if typ:
            id_to_type[tv.id] = typ

    # Apply arguments to argument types.
    arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]

    # The callable may retain some type vars if only some were applied.
    remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]

    return callable.copy_modified(
        arg_types=arg_types,
        ret_type=expand_type(callable.ret_type, id_to_type),
        variables=remaining_tvars,
    )