Repository: pydantic/pydantic

Issue:
copy_on_model_validation config doesn't copy List field anymore in v1.9.0
### Checks

* [x] I added a descriptive title to this issue
* [x] I have searched (google, github) for similar issues and couldn't find anything
* [x] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and still think this is a bug

<!-- Sorry to sound so draconian, but every second saved replying to issues is time spend improving pydantic :-) -->

# Bug

The output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"` when I use v1.9.0a1,
```
             pydantic version: 1.9.0a1
            pydantic compiled: True
                 install path: <*my-project-dir*>/venv/lib/python3.9/site-packages/pydantic
               python version: 3.9.9 (main, Nov 16 2021, 03:05:18)  [GCC 7.5.0]
                     platform: Linux-5.4.0-91-generic-x86_64-with-glibc2.27
     optional deps. installed: ['typing-extensions']
```
The output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"` when I use v1.9.0,
```
             pydantic version: 1.9.0
            pydantic compiled: True
                 install path: <*my-project-dir*>/venv/lib/python3.9/site-packages/pydantic
               python version: 3.9.9 (main, Nov 16 2021, 03:05:18)  [GCC 7.5.0]
                     platform: Linux-5.4.0-91-generic-x86_64-with-glibc2.27
     optional deps. installed: ['typing-extensions']
```

<!-- or if you're using pydantic prior to v1.3, manually include: OS, python version and pydantic version -->

<!-- Please read the [docs](https://pydantic-docs.helpmanual.io/) and search through issues to
confirm your bug hasn't already been reported. -->

<!-- Where possible please include a self-contained code snippet describing your bug: -->

Looks like there is accidental behaviour change from v1.9.0a1 to v1.9.0 regarding the `copy_on_model_validation` config.

```py
from pydantic import BaseModel
from typing import List


class A(BaseModel):
    name: str
    
    class Config:
        copy_on_model_validation = True  # Default behaviour
        

class B(BaseModel):
    list_a: List[A]


a = A(name="a")
b = B(list_a=[a])

print(a)
print(b)
a.name = "b"  # make a change to variable a's field
print(a)
print(b)

```
The output using v1.9.0a1,
```
A(name='a')
B(list_a=[A(name='a')])
A(name='b')
B(list_a=[A(name='a')])
```

The output using v1.9.0 changed to,
```
A(name='a')
B(list_a=[A(name='a')])
A(name='b')
B(list_a=[A(name='b')])
```




Discussion:

Resolving patch:
diff --git a/pydantic/main.py b/pydantic/main.py
--- a/pydantic/main.py
+++ b/pydantic/main.py
@@ -666,7 +666,7 @@ def __get_validators__(cls) -> 'CallableGenerator':
     def validate(cls: Type['Model'], value: Any) -> 'Model':
         if isinstance(value, cls):
             if cls.__config__.copy_on_model_validation:
-                return value._copy_and_set_values(value.__dict__, value.__fields_set__, deep=False)
+                return value._copy_and_set_values(value.__dict__, value.__fields_set__, deep=True)
             else:
                 return value
 


Test patch:
diff --git a/tests/test_main.py b/tests/test_main.py
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -1561,12 +1561,28 @@ class Config:
 
     assert t.user is not my_user
     assert t.user.hobbies == ['scuba diving']
-    assert t.user.hobbies is my_user.hobbies  # `Config.copy_on_model_validation` only does a shallow copy
+    assert t.user.hobbies is not my_user.hobbies  # `Config.copy_on_model_validation` does a deep copy
     assert t.user._priv == 13
     assert t.user.password.get_secret_value() == 'hashedpassword'
     assert t.dict() == {'id': '1234567890', 'user': {'id': 42, 'hobbies': ['scuba diving']}}
 
 
+def test_validation_deep_copy():
+    """By default, Config.copy_on_model_validation should do a deep copy"""
+
+    class A(BaseModel):
+        name: str
+
+    class B(BaseModel):
+        list_a: List[A]
+
+    a = A(name='a')
+    b = B(list_a=[a])
+    assert b.list_a == [A(name='a')]
+    a.name = 'b'
+    assert b.list_a == [A(name='a')]
+
+
 @pytest.mark.parametrize(
     'kinds',
     [