Repository: dask/dask
File: dask/delayed.py (Python)

Code before:
    if typ in (list, tuple, set):
        args, collections = utils.unzip(
            (unpack_collections(e, _return_collections=False) for e in expr), 2
        )

        collections = tuple(toolz.unique(toolz.concat(collections), key=id))
        # The List constructor also checks for futures
        args = List(*args)
        if not collections and not args.dependencies:
            return expr, ()
        if _return_collections:
            args, collections = _finalize_args_collections(args, collections)
        # Ensure output type matches input type
        if typ is not list:
            args = Task(None, typ, args)
        return args, collections

    if typ is dict:
        keyargs, kcollections = unpack_collections(
            [k for k in expr.keys()], _return_collections=False
        )
        valargs, valcollections = unpack_collections(
            [v for v in expr.values()], _return_collections=False
        )
        collections = kcollections + valcollections
        args = Dict({k: v for k, v in zip(keyargs, valargs)})
        if not collections and not args.dependencies:
            return expr, ()
        if _return_collections:
            args, collections = _finalize_args_collections(args, collections)
        return args, collections

    if typ is slice:
        args, collections = unpack_collections(
            [expr.start, expr.stop, expr.step], _return_collections=False
        )
        if not collections and not isinstance(args, GraphNode):
            return expr, ()

        if _return_collections:
            args, collections = _finalize_args_collections(args, collections)
        return Task(None, apply, slice, args), collections

    if is_dataclass(expr):
        args, collections = unpack_collections(
            [
                [f.name, getattr(expr, f.name)]
                for f in fields(expr)
                if hasattr(expr, f.name)  # if init=False, field might not exist
            ],
            _return_collections=False,

Review comment (bug):
This is the bit that's failing for unhashable `keyargs` (like `Alias`). Seems like defining `Alias.__hash__` as something like `hash(self.key)` might work, but I'm not sure what other consequences that might have and what other types might end up here.

Code after:
    if typ in (list, tuple, set):
        args, collections = utils.unzip(
            (unpack_collections(e, _return_collections=False) for e in expr), 2
        )

        collections = tuple(toolz.unique(toolz.concat(collections), key=id))
        # The List constructor also checks for futures
        args = List(*args)
        if not collections and not args.dependencies:
            return expr, ()
        if _return_collections:
            args, collections = _finalize_args_collections(args, collections)
        # Ensure output type matches input type
        if typ is not list:
            args = Task(None, typ, args)
        return args, collections

    if typ is dict:
        keyargs, kcollections = unpack_collections(
            [k for k in expr.keys()], _return_collections=False
        )
        valargs, valcollections = unpack_collections(
            [v for v in expr.values()], _return_collections=False
        )
        collections = kcollections + valcollections
        args = Dict([[k, v] for k, v in zip(keyargs, valargs)])
        if not collections and not args.dependencies:
            return expr, ()
        if _return_collections:
            args, collections = _finalize_args_collections(args, collections)
        return args, collections

    if typ is slice:
        args, collections = unpack_collections(
            [expr.start, expr.stop, expr.step], _return_collections=False
        )
        if not collections and not isinstance(args, GraphNode):
            return expr, ()

        if _return_collections:
            args, collections = _finalize_args_collections(args, collections)
        return Task(None, apply, slice, args), collections

    if is_dataclass(expr):
        args, collections = unpack_collections(
            [
                [f.name, getattr(expr, f.name)]
                for f in fields(expr)
                if hasattr(expr, f.name)  # if init=False, field might not exist
            ],
            _return_collections=False,