@_infer_type.register(irast.FunctionCall)
def __infer_func_call(ir, schema):
    rtype = ir.func.returntype
    if is_polymorphic_type(rtype):
        if isinstance(rtype, s_types.Tuple):
            for (i, arg) in enumerate(ir.args):
                if is_polymorphic_type(ir.func.paramtypes[i]):
                    arg_type = infer_type(arg, schema)
                    stypes = collections.OrderedDict(rtype.element_types)
                    for (sn, st) in stypes.items():
                        if is_polymorphic_type(st):
                            stypes[sn] = arg_type
                            break
                    return rtype.from_subtypes(stypes, rtype.get_typemods())
        elif isinstance(rtype, s_types.Collection):
            for (i, arg) in enumerate(ir.args):
                if is_polymorphic_type(ir.func.paramtypes[i]):
                    arg_type = infer_type(arg, schema)
                    stypes = list(rtype.get_subtypes())
                    for (si, st) in enumerate(stypes):
                        if is_polymorphic_type(st):
                            stypes[si] = arg_type
                            break
                    return rtype.from_subtypes(stypes, rtype.get_typemods())
        else:
            for (i, arg) in enumerate(ir.args):
                if is_polymorphic_type(ir.func.paramtypes[i]):
                    arg_type = infer_type(arg, schema)
                    if isinstance(arg_type, s_types.Collection):
                        stypes = list(arg_type.get_subtypes())
                        return stypes[(- 1)]
    else:
        return rtype
@_infer_type.register(irast.FunctionCall)
def __infer_func_call(ir, schema):
    rtype = ir.func.returntype
    if is_polymorphic_type(rtype):
        if isinstance(rtype, s_types.Tuple):
            for (i, arg) in enumerate(ir.args):
                if is_polymorphic_type(ir.func.paramtypes[i]):
                    arg_type = infer_type(arg, schema)
                    stypes = collections.OrderedDict(rtype.element_types)
                    for (sn, st) in stypes.items():
                        if is_polymorphic_type(st):
                            stypes[sn] = arg_type
                            break
                    return rtype.from_subtypes(stypes, rtype.get_typemods())
        elif isinstance(rtype, s_types.Collection):
            for (i, arg) in enumerate(ir.args):
                if is_polymorphic_type(ir.func.paramtypes[i]):
                    arg_type = infer_type(arg, schema)
                    stypes = list(rtype.get_subtypes())
                    for (si, st) in enumerate(stypes):
                        if is_polymorphic_type(st):
                            stypes[si] = arg_type
                            break
                    return rtype.from_subtypes(stypes, rtype.get_typemods())
        else:
            for (i, arg) in enumerate(ir.args):
                if is_polymorphic_type(ir.func.paramtypes[i]):
                    arg_type = infer_type(arg, schema)
                    if isinstance(arg_type, s_types.Collection):
                        stypes = list(arg_type.get_subtypes())
                        return stypes[(- 1)]
    else:
        return rtype