Example #1
0
    def matches_signature(self, arg_types, is_var_arg, callee):
        """Determine whether argument types match the signature.

        If is_var_arg is True, the caller uses varargs.
        """
        if not is_valid_argc(len(arg_types), False, callee):
            return False
        
        if is_var_arg:
            if not self.is_valid_var_arg(arg_types[-1]):
                return False
            arg_types, rest = expand_caller_var_args(arg_types,
                                                     callee.max_fixed_args())

        # Fixed function arguments.
        func_fixed = callee.max_fixed_args()
        for i in range(min(len(arg_types), func_fixed)):
            if not is_subtype(self.erase(arg_types[i]),
                              self.erase(
                                  callee.arg_types[i])):
                return False
        # Function varargs.
        if callee.is_var_arg:
            for i in range(func_fixed, len(arg_types)):
                if not is_subtype(self.erase(arg_types[i]),
                                  self.erase(callee.arg_types[func_fixed])):
                    return False
        return True
Example #2
0
def join_instances(t, s, allow_interfaces, basic):
    """Calculate the join of two instance types. If allow_interfaces is
    True, also consider interface-type results for non-interface
    types.
    
    Return ErrorType if the result is ambiguous.
    """
    if t.typ == s.typ:
        # Simplest case: join two types with the same base type (but
        # potentially different arguments).
        if is_subtype(t, s):
            # Compatible; combine type arguments.
            args = []
            for i in range(len(t.args)):
                args.append(join_types(t.args[i], s.args[i], basic))
            return Instance(t.typ, args)
        else:
            # Incompatible; return trivial result object.
            return basic.object
    elif t.typ.is_interface != s.typ.is_interface:
        return join_instances_as_interface(t, s, basic)
    elif t.typ.base is not None and is_subtype(t, s):
        return join_instances_via_supertype(t, s, allow_interfaces, basic)
    elif s.typ.base is not None:
        return join_instances_via_supertype(s, t, allow_interfaces, basic)
    elif allow_interfaces and not t.typ.is_interface:
        return join_instances_as_interface(t, s, basic)
    else:
        return basic.object
Example #3
0
 def is_valid_cast(self, source_type, target_type):
     """Is a cast from source_type to target_type valid (i.e. can succeed at
     runtime)?
     """
     return (is_subtype(target_type, source_type) or
             is_subtype(source_type, target_type) or
             (isinstance(target_type, Instance) and
                  (target_type).typ.is_interface) or
             (isinstance(source_type, Instance) and
                  (source_type).typ.is_interface))
Example #4
0
 def assert_simple_join(self, s, t, join):
     result = join_types(s, t, self.fx.basic)
     actual = str(result)
     expected = str(join)
     assert_equal(actual, expected,
                  'join({}, {}) == {{}} ({{}} expected)'.format(s, t))
     if not isinstance(s, ErrorType) and not isinstance(result, ErrorType):
         assert_true(is_subtype(s, result),
                     '{} not subtype of {}'.format(s, result))
     if not isinstance(t, ErrorType) and not isinstance(result, ErrorType):
         assert_true(is_subtype(t, result),
                     '{} not subtype of {}'.format(t, result))
Example #5
0
 def assert_simple_meet(self, s, t, meet):
     result = meet_types(s, t, self.fx.basic)
     actual = str(result)
     expected = str(meet)
     assert_equal(actual, expected,
                  'meet({}, {}) == {{}} ({{}} expected)'.format(s, t))
     if not isinstance(s, ErrorType) and not isinstance(result, ErrorType):
         assert_true(is_subtype(result, s),
                     '{} not subtype of {}'.format(result, s))
     if not isinstance(t, ErrorType) and not isinstance(result, ErrorType):
         assert_true(is_subtype(result, t),
                     '{} not subtype of {}'.format(result, t))
Example #6
0
 def check_exception_type(self, info, context):
     t = Instance(info, [])
     if is_subtype(t, self.named_type('builtins.BaseException')):
         return t
     else:
         self.fail(messages.INVALID_EXCEPTION_TYPE, context)
         return Any()
Example #7
0
 def visit_instance(self, t):
     if isinstance(self.s, Instance):
         return join_instances(t, self.s, True, self.basic)
     elif t.typ == self.basic.std_type.typ and is_subtype(self.s, t):
         return t
     else:
         return self.default(self.s)
Example #8
0
 def check_arg(self, caller_type, original_caller_type, callee_type, n, callee, context):
     """Check the type of a single argument in a call."""
     if isinstance(caller_type, Void):
         self.msg.does_not_return_value(caller_type, context)
     elif not is_subtype(caller_type, callee_type):
         self.msg.incompatible_argument(n, callee, original_caller_type,
                                        context)
Example #9
0
def solve_constraints( vars, constraints, basic):
    """Solve type constraints.

    Return lower bound for each type variable or None if the variable could
    not be solved.
    """
    # Collect a list of constraints for each type variable.
    cmap = {}
    for con in constraints:
        a = cmap.get(con.type_var, [])
        a.append(con)
        cmap[con.type_var] = a
    
    res = []

    # Solve each type variable separately.
    for tvar in vars:
        bottom = None
        top = None
        
        # Process each contraint separely, and calculate the lower and upper
        # bounds based on constraints. Note that we assume that the contraint
        # targets do not have contraint references.
        for c in cmap.get(tvar, []):
            if c.op == SUPERTYPE_OF:
                if bottom is None:
                    bottom = c.target
                else:
                    bottom = join_types(bottom, c.target, basic)
            else:
                if top is None:
                    top = c.target
                else:
                    top = meet_types(top, c.target, basic)
        
        if top is None:
            if isinstance(bottom, Void):
                top = Void()
            else:
                top = basic.object
        
        if bottom is None:
            if isinstance(top, Void):
                bottom = Void()
            else:
                bottom = NoneTyp()
        
        if isinstance(top, Any) or isinstance(bottom, Any):
            top = Any()
            bottom = Any()
        
        # Pick the most specific type if it satisfies the constraints.
        if (not top or not bottom or is_subtype(bottom, top)) and (
                not isinstance(top, ErrorType) and
                not isinstance(bottom, ErrorType)):
            res.append(bottom)
        else:
            res.append(None)
    
    return res
Example #10
0
 def check_subtype(self, subtype, supertype, context, msg=messages.INCOMPATIBLE_TYPES):
     """Generate an error if the subtype is not compatible with
     supertype."""
     if not is_subtype(subtype, supertype):
         if isinstance(subtype, Void):
             self.msg.does_not_return_value(subtype, context)
         else:
             self.fail(msg, context)
Example #11
0
 def visit_callable(self, t):
     if isinstance(self.s, Callable) and is_similar_callables(
                                                 t, self.s):
         return combine_similar_callables(t, self.s, self.basic)
     elif t.is_type_obj() and is_subtype(self.s, self.basic.std_type):
         return self.basic.std_type
     elif (isinstance(self.s, Instance) and
               (self.s).typ == self.basic.std_type.typ and
               t.is_type_obj()):
         return self.basic.std_type
     else:
         return self.default(self.s)
Example #12
0
 def visit_operator_assignment_stmt(self, s):
     """Type check an operator assignment statement, e.g. x += 1."""
     lvalue_type = self.accept(s.lvalue)
     rvalue_type = self.expr_checker.check_op(op_methods[s.op], lvalue_type,
                                              s.rvalue, s)
     
     if isinstance(s.lvalue, IndexExpr):
         lv = s.lvalue
         self.check_single_assignment(None,
                                      (self.accept(lv.base), lv.index),
                                      s.rvalue, s.rvalue)
     else:
         if not is_subtype(rvalue_type, lvalue_type):
             self.msg.incompatible_operator_assignment(s.op, s)
Example #13
0
 def visit_instance(self, t):
     if isinstance(self.s, Instance):
         si = self.s
         if t.typ == si.typ:
             if is_subtype(t, self.s):
                 # Combine type arguments. We could have used join below
                 # equivalently.
                 args = []
                 for i in range(len(t.args)):
                     args.append(self.meet(t.args[i], si.args[i]))
                 return Instance(t.typ, args)
             else:
                 return NoneTyp()
         else:
             if is_subtype(t, self.s):
                 return t
             elif is_subtype(self.s, t):
                 # See also above comment.
                 return self.s
             else:
                 return NoneTyp()
     else:
         return self.default(self.s)
Example #14
0
    def check_override(self, override, original, name, supertype, node):
        """Check a method override with given signatures.

        Arguments:
          override:  The signature of the overriding method.
          original:  The signature of the original supertype method.
          name:      The name of the subtype. This and the next argument are
                     only used for generating error messages.
          supertype: The name of the supertype.
        """
        if (isinstance(override, Overloaded) or
                isinstance(original, Overloaded) or
                len((override).arg_types) !=
                    len((original).arg_types) or
                (override).min_args !=
                    (original).min_args):
            if not is_subtype(override, original):
                self.msg.signature_incompatible_with_supertype(
                    name, supertype, node)
            return
        else:
            # Give more detailed messages for the common case of both
            # signatures having the same number of arguments and no
            # intersection types.
            
            coverride = override
            coriginal = original
            
            for i in range(len(coverride.arg_types)):
                if not is_equivalent(coriginal.arg_types[i],
                                     coverride.arg_types[i]):
                    self.msg.argument_incompatible_with_supertype(
                        i + 1, name, supertype, node)
            
            if not is_subtype(coverride.ret_type, coriginal.ret_type):
                self.msg.return_type_incompatible_with_supertype(
                    name, supertype, node)
Example #15
0
File: meet.py Project: khukri/mypy
            return ErrorType()

    Typ visit_erased_type(self, ErasedType t):
        return self.s
    
    Typ visit_type_var(self, TypeVar t):
        if isinstance(self.s, TypeVar) and ((TypeVar)self.s).id == t.id:
            return self.s
        else:
            return self.default(self.s)
    
    Typ visit_instance(self, Instance t):
        if isinstance(self.s, Instance):
            si = (Instance)self.s
            if t.typ == si.typ:
                if is_subtype(t, self.s):
                    # Combine type arguments. We could have used join below
                    # equivalently.
                    Typ[] args = []
                    for i in range(len(t.args)):
                        args.append(self.meet(t.args[i], si.args[i]))
                    return Instance(t.typ, args)
                else:
                    return NoneTyp()
            else:
                if is_subtype(t, self.s):
                    return t
                elif is_subtype(self.s, t):
                    # See also above comment.
                    return self.s
                else:
Example #16
0
 def assert_not_subtype(self, s, t):
     assert_true(not is_subtype(s, t), '{} subtype of {}'.format(s, t))
Example #17
0
 def assert_subtype(self, s, t):
     assert_true(is_subtype(s, t), '{} not subtype of {}'.format(s, t))
Example #18
0
                    tuplet = (TupleType)arg_types[actual]
                    while tuple_counter[0] < len(tuplet.items):
                        actual_type = get_actual_type(arg_type,
                                                      arg_kinds[actual],
                                                      tuple_counter)
                        self.check_arg(actual_type, arg_type,
                                       callee.arg_types[i],
                                       actual + 1, callee, context)
    
    
    void check_arg(self, Typ caller_type, Typ original_caller_type,
                   Typ callee_type, int n, Callable callee, Context context):
        """Check the type of a single argument in a call."""
        if isinstance(caller_type, Void):
            self.msg.does_not_return_value(caller_type, context)
        elif not is_subtype(caller_type, callee_type):
            self.msg.incompatible_argument(n, callee, original_caller_type,
                                           context)
    
    Typ overload_call_target(self, Typ[] arg_types, bool is_var_arg,
                             Overloaded overload, Context context):
        """Infer the correct overload item to call with given argument types.

        The return value may be Callable or any (if an unique item
        could not be determined). If is_var_arg is True, the caller
        uses varargs.
        """
        # TODO for overlapping signatures we should try to get a more precise
        #      result than 'any'
        Typ match = None # Callable, Any or None
        for typ in overload.items():
Example #19
0
 def is_valid_keyword_var_arg(self, typ):    
     """Is a type valid as a **kwargs argument?"""
     return is_subtype(typ, self.chk.named_generic_type(
         'builtins.dict', [self.named_type('builtins.str'), Any()]))
Example #20
0
 def is_boolean(self, typ):
     """Is type compatible with bool?"""
     return is_subtype(typ, self.chk.bool_type())
Example #21
0
File: join.py Project: khukri/mypy
     else:
         return self.default(self.s)
 
 Typ visit_erased_type(self, ErasedType t):
     return self.s
 
 Typ visit_type_var(self, TypeVar t):
     if isinstance(self.s, TypeVar) and ((TypeVar)self.s).id == t.id:
         return self.s
     else:
         return self.default(self.s)
 
 Typ visit_instance(self, Instance t):
     if isinstance(self.s, Instance):
         return join_instances(t, (Instance)self.s, True, self.basic)
     elif t.typ == self.basic.std_type.typ and is_subtype(self.s, t):
         return t
     else:
         return self.default(self.s)
 
 Typ visit_callable(self, Callable t):
     if isinstance(self.s, Callable) and is_similar_callables(
                                                 t, (Callable)self.s):
         return combine_similar_callables(t, (Callable)self.s, self.basic)
     elif t.is_type_obj() and is_subtype(self.s, self.basic.std_type):
         return self.basic.std_type
     elif (isinstance(self.s, Instance) and
               ((Instance)self.s).typ == self.basic.std_type.typ and
               t.is_type_obj()):
         return self.basic.std_type
     else:
Example #22
0
                if top is None:
                    top = c.target
                else:
                    top = meet_types(top, c.target, basic)
        
        if top is None:
            if isinstance(bottom, Void):
                top = Void()
            else:
                top = basic.object
        
        if bottom is None:
            if isinstance(top, Void):
                bottom = Void()
            else:
                bottom = NoneTyp()
        
        if isinstance(top, Any) or isinstance(bottom, Any):
            top = Any()
            bottom = Any()
        
        # Pick the most specific type if it satisfies the constraints.
        if (not top or not bottom or is_subtype(bottom, top)) and (
                not isinstance(top, ErrorType) and
                not isinstance(bottom, ErrorType)):
            res.append(bottom)
        else:
            res.append(None)
    
    return res