Repository: sympy/sympy
File: sympy/solvers/solveset.py (Python)

Code before:
                unsolved_syms = _unsolved_syms(eq2, sort=True)
                if not unsolved_syms:
                    if res:
                        newresult, delete_res = _append_new_soln(
                            res, None, None, imgset_yes, soln_imageset,
                            original_imageset, newresult, eq2)
                        if delete_res:
                            # `delete_res` is true, means substituting `res` in
                            # eq2 doesn't return `zero` or deleting the `res`
                            # (a soln) since it satisfies expr of `exclude`
                            # list.
                            result.remove(res)
                    continue  # skip as it's independent of desired symbols
                depen1, depen2 = eq2.as_independent(*unsolved_syms)
                if (depen1.has(Abs) or depen2.has(Abs)) and solver == solveset_complex:
                    # Absolute values cannot be inverted in the
                    # complex domain
                    raise NotImplementedError(
                        "nonlinsolve cannot solve equations with Abs in the complex domain"
                    )
                soln_imageset = {}
                for sym in unsolved_syms:
                    not_solvable = False
                    try:
                        soln = solver(eq2, sym)
                        if isinstance(soln, Interval):
                            raise NotImplementedError(
                                f"Cannot solve system: solving for {sym} returned an Interval "
                                f"which cannot be substituted into remaining equations"
                            )
                        total_solvest_call += 1
                        soln_new = S.EmptySet
                        if isinstance(soln, Complement):
                            # separate solution and complement
                            complements[sym] = soln.args[1]
                            soln = soln.args[0]
                            # complement will be added at the end
                        if isinstance(soln, Intersection):
                            # Interval will be at 0th index always
                            if soln.args[0] != Interval(-oo, oo):
                                # sometimes solveset returns soln
                                # with intersection S.Reals, to confirm that
                                # soln is in domain=S.Reals
                                intersections[sym] = soln.args[0]
                            soln_new += soln.args[1]
                        soln = soln_new if soln_new else soln
                        if index > 0 and solver == solveset_real:
                            # one symbol's real soln, another symbol may have
                            # corresponding complex soln.
                            if not isinstance(soln, (ImageSet, ConditionSet)):
                                soln += solveset_complex(eq2, sym)  # might give ValueError with Abs

Review comment (bug):
Rather than rejecting `Interval` explicitly here I think somewhere later there needs to be a confirmation that we did or did not get a usable type which means that after handling things like Complement etc we should eventually get a `FiniteSet` (or `EmptySet`).

Currently `nonlinsolve` returns solutions like this sometimes:
```
In [1]: nonlinsolve([sin(x), y], [x, y])
Out[1]: {({2⋅n⋅π │ n ∊ ℤ}, 0), ({2⋅n⋅π + π │ n ∊ ℤ}, 0)}
```
I think that kind of solution is just broken and this case should be handled as an error.

It is not a proper set to have a tuple that contains sets like this.

Probably what is really needed is to accept that solveset and nonlinsolve are both failures and we again need a new version of solve that is different from them.

Code after:
                unsolved_syms = _unsolved_syms(eq2, sort=True)
                if not unsolved_syms:
                    if res:
                        newresult, delete_res = _append_new_soln(
                            res, None, None, imgset_yes, soln_imageset,
                            original_imageset, newresult, eq2)
                        if delete_res:
                            # `delete_res` is true, means substituting `res` in
                            # eq2 doesn't return `zero` or deleting the `res`
                            # (a soln) since it satisfies expr of `exclude`
                            # list.
                            result.remove(res)
                    continue  # skip as it's independent of desired symbols
                depen1, depen2 = eq2.as_independent(*unsolved_syms)
                if (depen1.has(Abs) or depen2.has(Abs)) and solver == solveset_complex:
                    # Absolute values cannot be inverted in the
                    # complex domain
                    raise NotImplementedError(
                        "nonlinsolve cannot solve equations with Abs in the complex domain"
                    )
                soln_imageset = {}
                for sym in unsolved_syms:
                    not_solvable = False
                    try:
                        soln = solver(eq2, sym)
                        total_solvest_call += 1
                        soln_new = S.EmptySet
                        if isinstance(soln, Complement):
                            # separate solution and complement
                            complements[sym] = soln.args[1]
                            soln = soln.args[0]
                            # complement will be added at the end
                        if isinstance(soln, Intersection):
                            # Interval will be at 0th index always
                            if soln.args[0] != Interval(-oo, oo):
                                # sometimes solveset returns soln
                                # with intersection S.Reals, to confirm that
                                # soln is in domain=S.Reals
                                intersections[sym] = soln.args[0]
                            soln_new += soln.args[1]
                        soln = soln_new if soln_new else soln
                        if index > 0 and solver == solveset_real:
                            # one symbol's real soln, another symbol may have
                            # corresponding complex soln.
                            if not isinstance(soln, (ImageSet, ConditionSet)):
                                soln += solveset_complex(eq2, sym)  # might give ValueError with Abs

                        if not isinstance(soln, (FiniteSet, ImageSet, ConditionSet, Union)) and soln is not S.EmptySet:
                            raise NotImplementedError(
                                f"nonlinsolve cannot handle solution of type {type(soln).__name__} "
                                f"for symbol {sym}. Got {soln} from equation {eq2}."