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
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
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
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)