A side effect of computing aliases on a Return is that it updates the
        ``return_alias`` field of current function

        >>> from pythran import passmanager
        >>> pm = passmanager.PassManager('demo')
        >>> module = ast.parse('def foo(a, b): return a')
        >>> result = pm.gather(Aliases, module)
        >>> module.body[0].return_alias # doctest: +ELLIPSIS
        <function ...merge_return_aliases at...>

        This field is a function that takes as many nodes as the function
        argument count as input and returns an expression based on
        these arguments if the function happens to create aliasing
        between its input and output. In our case:

        >>> f = module.body[0].return_alias
        >>> Aliases.dump(f([ast.Name('A', ast.Load(), None), ast.Num(1)]))
        ['A']

        This also works if the relationship between input and output
        is more complex:

        >>> module = ast.parse('def foo(a, b): return a or b[0]')
        >>> result = pm.gather(Aliases, module)
        >>> f = module.body[0].return_alias
        >>> List = ast.List([ast.Name('L0', ast.Load(), None)], ast.Load())
        >>> Aliases.dump(f([ast.Name('B', ast.Load(), None), List]))
        ['B', '[L0][0]']

        Which actually means that when called with two arguments ``B`` and
        the single-element list ``[L[0]]``, ``foo`` may returns either the
        first argument, or the first element of the second argument.

def visit_Return(self, node):
        '''
        A side effect of computing aliases on a Return is that it updates the
        ``return_alias`` field of current function

        >>> from pythran import passmanager
        >>> pm = passmanager.PassManager('demo')
        >>> module = ast.parse('def foo(a, b): return a')
        >>> result = pm.gather(Aliases, module)
        >>> module.body[0].return_alias # doctest: +ELLIPSIS
        <function ...merge_return_aliases at...>

        This field is a function that takes as many nodes as the function
        argument count as input and returns an expression based on
        these arguments if the function happens to create aliasing
        between its input and output. In our case:

        >>> f = module.body[0].return_alias
        >>> Aliases.dump(f([ast.Name('A', ast.Load(), None), ast.Num(1)]))
        ['A']

        This also works if the relationship between input and output
        is more complex:

        >>> module = ast.parse('def foo(a, b): return a or b[0]')
        >>> result = pm.gather(Aliases, module)
        >>> f = module.body[0].return_alias
        >>> List = ast.List([ast.Name('L0', ast.Load(), None)], ast.Load())
        >>> Aliases.dump(f([ast.Name('B', ast.Load(), None), List]))
        ['B', '[L0][0]']

        Which actually means that when called with two arguments ``B`` and
        the single-element list ``[L[0]]``, ``foo`` may returns either the
        first argument, or the first element of the second argument.
        '''
        if not node.value:
            return
        ret_aliases = self.visit(node.value)
        if Aliases.RetId in self.aliases:
            ret_aliases = ret_aliases.union(self.aliases[Aliases.RetId])
        self.aliases[Aliases.RetId] = ret_aliases