Repository: pydantic/pydantic

Issue:
Validating a dict value agains a Literal type gives the wrong ValidationError
### Initial Checks

- [X] I have searched GitHub for a duplicate issue and I'm sure this is something new
- [X] I have searched Google & StackOverflow for a solution and couldn't find anything
- [X] I have read and followed [the docs](https://docs.pydantic.dev) and still think this is a bug
- [X] I am confident that the issue is with pydantic (not my code, or another library in the ecosystem like [FastAPI](https://fastapi.tiangolo.com) or [mypy](https://mypy.readthedocs.io/en/stable))


### Description

Validating a dict value agains a Literal type gives the wrong ValidationError. Instead of `unexpected value; permitted: '*'` the validation error just says `unhashable type: 'dict' (type=type_error)`.  Which does not describe the problem and is confusing, e.g. if handing this to API users in fastAPI. I would also expect an `unexpected value; permitted: '*'` for all non string values.

The respective validator in `pydantic/validators.py` (line 480ff) only catches a KeyError:

```py
def make_literal_validator(type_: Any) -> Callable[[Any], Any]:
    permitted_choices = all_literal_values(type_)

    # To have a O(1) complexity and still return one of the values set inside the `Literal`,
    # we create a dict with the set values (a set causes some problems with the way intersection works).
    # In some cases the set value and checked value can indeed be different (see `test_literal_validator_str_enum`)
    allowed_choices = {v: v for v in permitted_choices}

    def literal_validator(v: Any) -> Any:
        try:
            return allowed_choices[v]
        except KeyError:
            raise errors.WrongConstantError(given=v, permitted=permitted_choices)

    return literal_validator
```

IMHO, it should also catch a  `TypeError` (i.e. the "unhashable type") and produce a corresponding error. Or, it could check for `isinstance(v, str)` first and raise respective error if it is not a string.

### Example Code

```Python
import pydantic
from typing import Literal

pydantic.parse_obj_as(Literal['*'], {})
```


### Python, Pydantic & OS Version

```Text
pydantic version: 1.10.9
            pydantic compiled: True
                 install path: ********.pyenv/lib/python3.9/site-packages/pydantic
               python version: 3.9.16 (main, Dec  7 2022, 10:16:11)  [Clang 14.0.0 (clang-1400.0.29.202)]
                     platform: macOS-13.2-x86_64-i386-64bit
     optional deps. installed: ['devtools', 'dotenv', 'email-validator', 'typing-extensions']
```


### Affected Components

- [ ] [Compatibility between releases](https://docs.pydantic.dev/changelog/)
- [X] [Data validation/parsing](https://docs.pydantic.dev/usage/models/#basic-model-usage)
- [ ] [Data serialization](https://docs.pydantic.dev/usage/exporting_models/) - `.dict()` and `.json()`
- [ ] [JSON Schema](https://docs.pydantic.dev/usage/schema/)
- [ ] [Dataclasses](https://docs.pydantic.dev/usage/dataclasses/)
- [ ] [Model Config](https://docs.pydantic.dev/usage/model_config/)
- [ ] [Field Types](https://docs.pydantic.dev/usage/types/) - adding or changing a particular data type
- [ ] [Function validation decorator](https://docs.pydantic.dev/usage/validation_decorator/)
- [ ] [Generic Models](https://docs.pydantic.dev/usage/models/#generic-models)
- [ ] [Other Model behaviour](https://docs.pydantic.dev/usage/models/) - `construct()`, pickling, private attributes, ORM mode
- [ ] [Plugins](https://docs.pydantic.dev/) and integration with other tools - mypy, FastAPI, python-devtools, Hypothesis, VS Code, PyCharm, etc.


Discussion:
Thanks @markus1978 for reporting.

Would you like to open a PR for fixing?
@hramezani 
> Would you like to open a PR for fixing?

Sure. I guess, I should base of and target `1.10.X-fixes`?
> @hramezani
> 
> > Would you like to open a PR for fixing?
> 
> Sure. I guess, I should base of and target `1.10.X-fixes`?

Yes

Resolving patch:
diff --git a/pydantic/validators.py b/pydantic/validators.py
--- a/pydantic/validators.py
+++ b/pydantic/validators.py
@@ -488,7 +488,7 @@ def make_literal_validator(type_: Any) -> Callable[[Any], Any]:
     def literal_validator(v: Any) -> Any:
         try:
             return allowed_choices[v]
-        except KeyError:
+        except (KeyError, TypeError):
             raise errors.WrongConstantError(given=v, permitted=permitted_choices)
 
     return literal_validator


Test patch:
diff --git a/tests/test_validators.py b/tests/test_validators.py
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -1189,6 +1189,24 @@ class Model(BaseModel):
     ]
 
 
+def test_literal_validator_non_str_value():
+    class Model(BaseModel):
+        a: Literal['foo']
+
+    Model(a='foo')
+
+    with pytest.raises(ValidationError) as exc_info:
+        Model(a={'bar': 'foo'})
+    assert exc_info.value.errors() == [
+        {
+            'loc': ('a',),
+            'msg': "unexpected value; permitted: 'foo'",
+            'type': 'value_error.const',
+            'ctx': {'given': {'bar': 'foo'}, 'permitted': ('foo',)},
+        }
+    ]
+
+
 def test_literal_validator_str_enum():
     class Bar(str, Enum):
         FIZ = 'fiz'