Repository: pydantic/pydantic

Issue:
TypeAdapter fails to validate against generic dataclass when using different type parameters
### Initial Checks

- [X] I confirm that I'm using Pydantic V2

### Description

I've just started using pydantic, and I'm using `TypeAdapters` to turn JSON strings into `dataclass` instances. This works really well until I try to validate the same generic class with a different type parameter. It seems to me that in my example, once you create a `TypeAdapter` for `Outer[int]`, you can only ever validate that exact type, and not types that use a different type parameter like `Outer[str]`.

### Example Code

```Python
from pydantic import TypeAdapter
from pydantic.dataclasses import dataclass
from typing import Generic, TypeVar

T = TypeVar("T")

@dataclass
class Outer(Generic[T]):
    data: T

json1 = '{"data": 42}'
json2 = '{"data": "something else"}'

adapter1 = TypeAdapter(Outer[int])
adapter2 = TypeAdapter(Outer[str])

assert Outer(42) == adapter1.validate_json(json1, strict=True)  # works
assert Outer("something else") == adapter2.validate_json(json2, strict=True)  # crashes

# pydantic_core._pydantic_core.ValidationError: 1 validation error for Outer
# data
#   Input should be a valid integer [type=int_type, input_value='something else', input_type=str]
#     For further information visit https://errors.pydantic.dev/2.3/v/int_type
```


### Python, Pydantic & OS Version

```Text
pydantic version: 2.3.0
        pydantic-core version: 2.6.3
          pydantic-core build: profile=release pgo=false
                 install path: /Users/timwie/.pyenv/versions/3.9.17/envs/aio-taginfo39/lib/python3.9/site-packages/pydantic
               python version: 3.9.17 (main, Jun 26 2023, 11:24:22)  [Clang 14.0.3 (clang-1403.0.22.14.1)]
                     platform: macOS-13.5.2-arm64-arm-64bit
     optional deps. installed: ['typing-extensions']
```



Discussion:

Resolving patch:
diff --git a/pydantic/_internal/_core_utils.py b/pydantic/_internal/_core_utils.py
--- a/pydantic/_internal/_core_utils.py
+++ b/pydantic/_internal/_core_utils.py
@@ -1,7 +1,16 @@
 from __future__ import annotations
 
 from collections import defaultdict
-from typing import Any, Callable, Hashable, Iterable, TypeVar, Union, cast
+from typing import (
+    Any,
+    Callable,
+    Hashable,
+    Iterable,
+    TypeVar,
+    Union,
+    _GenericAlias,  # type: ignore
+    cast,
+)
 
 from pydantic_core import CoreSchema, core_schema
 from typing_extensions import TypeAliasType, TypeGuard, get_args
@@ -65,7 +74,7 @@ def get_type_ref(type_: type[Any], args_override: tuple[type[Any], ...] | None =
     when creating generic models without needing to create a concrete class.
     """
     origin = type_
-    args = args_override or ()
+    args = get_args(type_) if isinstance(type_, _GenericAlias) else (args_override or ())
     generic_metadata = getattr(type_, '__pydantic_generic_metadata__', None)
     if generic_metadata:
         origin = generic_metadata['origin'] or origin
diff --git a/pydantic/_internal/_generate_schema.py b/pydantic/_internal/_generate_schema.py
--- a/pydantic/_internal/_generate_schema.py
+++ b/pydantic/_internal/_generate_schema.py
@@ -9,7 +9,7 @@
 import typing
 import warnings
 from contextlib import contextmanager
-from copy import copy
+from copy import copy, deepcopy
 from enum import Enum
 from functools import partial
 from inspect import Parameter, _ParameterKind, signature
@@ -1275,7 +1275,7 @@ def _dataclass_schema(
                 from ..dataclasses import is_pydantic_dataclass
 
                 if is_pydantic_dataclass(dataclass):
-                    fields = dataclass.__pydantic_fields__
+                    fields = deepcopy(dataclass.__pydantic_fields__)
                     if typevars_map:
                         for field in fields.values():
                             field.apply_typevars_map(typevars_map, self._types_namespace)


Test patch:
diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py
--- a/tests/test_dataclasses.py
+++ b/tests/test_dataclasses.py
@@ -2058,6 +2058,41 @@ class GenericDataclass(Generic[T]):
         assert exc_info.value.errors(include_url=False) == output_value
 
 
+def test_multiple_parametrized_generic_dataclasses():
+    T = TypeVar('T')
+
+    @pydantic.dataclasses.dataclass
+    class GenericDataclass(Generic[T]):
+        x: T
+
+    validator1 = pydantic.TypeAdapter(GenericDataclass[int])
+    validator2 = pydantic.TypeAdapter(GenericDataclass[str])
+
+    # verify that generic parameters are showing up in the type ref for generic dataclasses
+    # this can probably be removed if the schema changes in some way that makes this part of the test fail
+    assert '[int:' in validator1.core_schema['schema']['schema_ref']
+    assert '[str:' in validator2.core_schema['schema']['schema_ref']
+
+    assert validator1.validate_python({'x': 1}).x == 1
+    assert validator2.validate_python({'x': 'hello world'}).x == 'hello world'
+
+    with pytest.raises(ValidationError) as exc_info:
+        validator2.validate_python({'x': 1})
+    assert exc_info.value.errors(include_url=False) == [
+        {'input': 1, 'loc': ('x',), 'msg': 'Input should be a valid string', 'type': 'string_type'}
+    ]
+    with pytest.raises(ValidationError) as exc_info:
+        validator1.validate_python({'x': 'hello world'})
+    assert exc_info.value.errors(include_url=False) == [
+        {
+            'input': 'hello world',
+            'loc': ('x',),
+            'msg': 'Input should be a valid integer, unable to parse string as an integer',
+            'type': 'int_parsing',
+        }
+    ]
+
+
 @pytest.mark.parametrize('dataclass_decorator', **dataclass_decorators(include_identity=True))
 def test_pydantic_dataclass_preserves_metadata(dataclass_decorator: Callable[[Any], Any]) -> None:
     @dataclass_decorator