Ejemplo n.º 1
0
def find_fixed_callable_return(expr: Expression) -> Optional[CallableType]:
    if isinstance(expr, RefExpr):
        if isinstance(expr.node, FuncDef):
            typ = expr.node.type
            if typ:
                if isinstance(typ, CallableType) and has_no_typevars(typ.ret_type):
                    if isinstance(typ.ret_type, CallableType):
                        return typ.ret_type
    elif isinstance(expr, CallExpr):
        t = find_fixed_callable_return(expr.callee)
        if t:
            if isinstance(t.ret_type, CallableType):
                return t.ret_type
    return None
Ejemplo n.º 2
0
def find_fixed_callable_return(expr: Expression) -> Optional[CallableType]:
    if isinstance(expr, RefExpr):
        if isinstance(expr.node, FuncDef):
            typ = expr.node.type
            if typ:
                if isinstance(typ, CallableType) and has_no_typevars(typ.ret_type):
                    if isinstance(typ.ret_type, CallableType):
                        return typ.ret_type
    elif isinstance(expr, CallExpr):
        t = find_fixed_callable_return(expr.callee)
        if t:
            if isinstance(t.ret_type, CallableType):
                return t.ret_type
    return None
Ejemplo n.º 3
0
def find_fixed_callable_return(expr: Expression) -> Optional[CallableType]:
    """Return the return type, if expression refers to a callable that returns a callable.

    But only do this if the return type has no type variables. Return None otherwise.
    This approximates things a lot as this is supposed to be called before type checking
    when full type information is not available yet.
    """
    if isinstance(expr, RefExpr):
        if isinstance(expr.node, FuncDef):
            typ = expr.node.type
            if typ:
                if isinstance(typ, CallableType) and has_no_typevars(typ.ret_type):
                    if isinstance(typ.ret_type, CallableType):
                        return typ.ret_type
    elif isinstance(expr, CallExpr):
        t = find_fixed_callable_return(expr.callee)
        if t:
            if isinstance(t.ret_type, CallableType):
                return t.ret_type
    return None
Ejemplo n.º 4
0
def find_fixed_callable_return(expr: Expression) -> Optional[CallableType]:
    """Return the return type, if expression refers to a callable that returns a callable.

    But only do this if the return type has no type variables. Return None otherwise.
    This approximates things a lot as this is supposed to be called before type checking
    when full type information is not available yet.
    """
    if isinstance(expr, RefExpr):
        if isinstance(expr.node, FuncDef):
            typ = expr.node.type
            if typ:
                if isinstance(typ, CallableType) and has_no_typevars(
                        typ.ret_type):
                    if isinstance(typ.ret_type, CallableType):
                        return typ.ret_type
    elif isinstance(expr, CallExpr):
        t = find_fixed_callable_return(expr.callee)
        if t:
            if isinstance(t.ret_type, CallableType):
                return t.ret_type
    return None
Ejemplo n.º 5
0
    def visit_instance(self, t: Instance) -> Type:
        if 'pfun.Intersection' == t.type.fullname:
            args = [get_proper_type(arg) for arg in t.args]
            if any(isinstance(arg, AnyType) for arg in args):
                return AnyType(TypeOfAny.special_form)
            if all(
                    hasattr(arg, 'type')
                    and arg.type.fullname == 'builtins.object'
                    for arg in args):
                return args[0]
            is_typevar = lambda arg: isinstance(arg, TypeVarType)
            has_type_attr = lambda arg: hasattr(arg, 'type')
            is_protocol = lambda arg: arg.type.is_protocol
            is_object = lambda arg: arg.type.fullname == 'builtins.object'
            if not all(
                    is_typevar(arg) or has_type_attr(arg) and
                (is_protocol(arg) or is_object(arg)) for arg in args):
                s = str(t)
                if self.inferred:
                    msg = (f'All arguments to "Intersection" '
                           f'must be protocols but inferred "{s}"')
                else:
                    msg = (f'All arguments to "Intersection" '
                           f'must be protocols, but got "{s}"')
                self.api.msg.fail(msg, self.context)
                return AnyType(TypeOfAny.special_form)
            if not has_no_typevars(t):
                return t
            bases = []
            for arg in args:
                if arg in bases:
                    continue
                bases.extend(self.get_bases(arg, []))
            if len(bases) == 1:
                return bases[0]
            bases_repr = ', '.join([repr(base) for base in bases])
            name = f'Intersection[{bases_repr}]'
            defn = ClassDef(name, Block([]), [], [
                NameExpr(arg.name) if isinstance(arg, TypeVarType) else
                NameExpr(arg.type.fullname) for arg in args
            ], None, [])
            defn.fullname = f'pfun.{name}'
            info = TypeInfo({}, defn, '')
            info.is_protocol = True
            info.is_abstract = True
            info.bases = bases
            attrs = []
            for base in bases:
                if isinstance(base, TypeVarType):
                    continue
                attrs.extend(base.type.abstract_attributes)
            info.abstract_attributes = attrs
            try:
                calculate_mro(info)
            except MroError:
                self.api.msg.fail(
                    'Cannot determine consistent method resolution '
                    'order (MRO) for "%s"' % defn.fullname, self.context)
                return AnyType(TypeOfAny.special_form)
            return Instance(info, [])

        return super().visit_instance(t)