diff --git a/conan/tools/scm/git.py b/conan/tools/scm/git.py
index c1aeb577a74..f3578e2c9ff 100644
--- a/conan/tools/scm/git.py
+++ b/conan/tools/scm/git.py
@@ -231,6 +231,7 @@ def fetch_commit(self, url, commit, hide_url=True):
         """
         if os.path.exists(url):
             url = url.replace("\\", "/")  # Windows local directory
+        mkdir(self.folder)
         self._conanfile.output.info("Shallow fetch of git repo")
         self.run('init')
         self.run(f'remote add origin "{url}"', hidden_output=url if hide_url else None)

diff --git a/test/functional/tools/scm/test_git.py b/test/functional/tools/scm/test_git.py
index 47214e461bc..ceef1e68610 100644
--- a/test/functional/tools/scm/test_git.py
+++ b/test/functional/tools/scm/test_git.py
@@ -504,6 +504,46 @@ def source(self):
         c.run("source .")
         assert f'conanfile.py (pkg/0.1): RUN: git remote add origin "{url}"' in c.out

+    @pytest.mark.skipif(platform.system() == "Linux", reason="Git version in Linux not support it")
+    def test_clone_to_subfolder(self):
+        conanfile = textwrap.dedent("""
+            import os
+            from conan import ConanFile
+            from conan.tools.scm import Git
+            from conan.tools.files import load
+
+            class Pkg(ConanFile):
+                name = "pkg"
+                version = "0.1"
+
+                def layout(self):
+                    self.folders.source = "source"
+
+                def source(self):
+                    git = Git(self, folder="folder")
+                    git.fetch_commit(url="{url}", commit="{commit}")
+                    self.output.info("MYCMAKE: {{}}".format(load(self, "folder/CMakeLists.txt")))
+                    self.output.info("MYFILE: {{}}".format(load(self, "folder/src/myfile.h")))
+            """)
+        folder = os.path.join(temp_folder(), "myrepo")
+        url, commit = create_local_git_repo(files={"src/myfile.h": "myheader!",
+                                                   "CMakeLists.txt": "mycmake"}, folder=folder)
+        # This second commit will NOT be used, as I will use the above commit in the conanfile
+        save_files(path=folder, files={"src/myfile.h": "my2header2!"})
+        git_add_changes_commit(folder=folder)
+
+        c = TestClient()
+        c.save({"conanfile.py": conanfile.format(url=url, commit=commit)})
+        c.run("create . -v")
+        assert "pkg/0.1: MYCMAKE: mycmake" in c.out
+        assert "pkg/0.1: MYFILE: myheader!" in c.out
+
+        # It also works in local flow
+        c.run("source .")
+        assert "conanfile.py (pkg/0.1): MYCMAKE: mycmake" in c.out
+        assert "conanfile.py (pkg/0.1): MYFILE: myheader!" in c.out
+        assert c.load("source/folder/CMakeLists.txt") == "mycmake"
+        assert c.load("source/folder/src/myfile.h") == "myheader!"

 class TestGitCloneWithArgs:
     """ Git cloning passing additional arguments

[bug] git.fetch_commit() throws an error when downloading sources to subfolder
### Describe the bug

`conan.tools.scm.Git.fetch_commit()` method throws an error when `folder` argument is passed to Git class constructor:

```python
def source(self):
    git = Git(self, folder="myFolder")
    git.fetch_commit(url, commit=self.conan_data["sources"]["commit"])
```

Error message:
```bash
ERROR: mypackage/1.2.3: Error in source() method, line 65
        git.fetch_commit(url, commit=self.conan_data["sources"]["commit"])
        FileNotFoundError: [Errno 2] No such file or directory: 'myFolder'
```

It seems that `mkdir(self.folder)` is missing in the body of `fetch_commit()` method - similarly as it is done in `clone()` method.

### How to reproduce it

_No response_

Hi @bkarasm

Thanks for your report.
It seems it could be a small UX improvement (what we call a ``fix``, not a ``bugfix``), and I think it should be very straightforward, would you like to do it yourself and contribute a PR?
Sure, I can give it a try.


diff --git a/mypy/plugins/default.py b/mypy/plugins/default.py
index 73c5742614ee..03cb379a8173 100644
--- a/mypy/plugins/default.py
+++ b/mypy/plugins/default.py
@@ -304,11 +304,12 @@ def typed_dict_pop_callback(ctx: MethodContext) -> Type:
         and len(ctx.arg_types) >= 1
         and len(ctx.arg_types[0]) == 1
     ):
-        keys = try_getting_str_literals(ctx.args[0][0], ctx.arg_types[0][0])
+        key_expr = ctx.args[0][0]
+        keys = try_getting_str_literals(key_expr, ctx.arg_types[0][0])
         if keys is None:
             ctx.api.fail(
                 message_registry.TYPEDDICT_KEY_MUST_BE_STRING_LITERAL,
-                ctx.context,
+                key_expr,
                 code=codes.LITERAL_REQ,
             )
             return AnyType(TypeOfAny.from_error)
@@ -316,13 +317,13 @@ def typed_dict_pop_callback(ctx: MethodContext) -> Type:
         value_types = []
         for key in keys:
             if key in ctx.type.required_keys:
-                ctx.api.msg.typeddict_key_cannot_be_deleted(ctx.type, key, ctx.context)
+                ctx.api.msg.typeddict_key_cannot_be_deleted(ctx.type, key, key_expr)

             value_type = ctx.type.items.get(key)
             if value_type:
                 value_types.append(value_type)
             else:
-                ctx.api.msg.typeddict_key_not_found(ctx.type, key, ctx.context)
+                ctx.api.msg.typeddict_key_not_found(ctx.type, key, key_expr)
                 return AnyType(TypeOfAny.from_error)

         if len(ctx.args[1]) == 0:
@@ -363,27 +364,29 @@ def typed_dict_setdefault_callback(ctx: MethodContext) -> Type:
         and len(ctx.arg_types[0]) == 1
         and len(ctx.arg_types[1]) == 1
     ):
-        keys = try_getting_str_literals(ctx.args[0][0], ctx.arg_types[0][0])
+        key_expr = ctx.args[0][0]
+        keys = try_getting_str_literals(key_expr, ctx.arg_types[0][0])
         if keys is None:
             ctx.api.fail(
                 message_registry.TYPEDDICT_KEY_MUST_BE_STRING_LITERAL,
-                ctx.context,
+                key_expr,
                 code=codes.LITERAL_REQ,
             )
             return AnyType(TypeOfAny.from_error)

         assigned_readonly_keys = ctx.type.readonly_keys & set(keys)
         if assigned_readonly_keys:
-            ctx.api.msg.readonly_keys_mutated(assigned_readonly_keys, context=ctx.context)
+            ctx.api.msg.readonly_keys_mutated(assigned_readonly_keys, context=key_expr)

         default_type = ctx.arg_types[1][0]
+        default_expr = ctx.args[1][0]

         value_types = []
         for key in keys:
             value_type = ctx.type.items.get(key)

             if value_type is None:
-                ctx.api.msg.typeddict_key_not_found(ctx.type, key, ctx.context)
+                ctx.api.msg.typeddict_key_not_found(ctx.type, key, key_expr)
                 return AnyType(TypeOfAny.from_error)

             # The signature_callback above can't always infer the right signature
@@ -392,7 +395,7 @@ def typed_dict_setdefault_callback(ctx: MethodContext) -> Type:
             # default can be assigned to all key-value pairs we're updating.
             if not is_subtype(default_type, value_type):
                 ctx.api.msg.typeddict_setdefault_arguments_inconsistent(
-                    default_type, value_type, ctx.context
+                    default_type, value_type, default_expr
                 )
                 return AnyType(TypeOfAny.from_error)

@@ -409,20 +412,21 @@ def typed_dict_delitem_callback(ctx: MethodContext) -> Type:
         and len(ctx.arg_types) == 1
         and len(ctx.arg_types[0]) == 1
     ):
-        keys = try_getting_str_literals(ctx.args[0][0], ctx.arg_types[0][0])
+        key_expr = ctx.args[0][0]
+        keys = try_getting_str_literals(key_expr, ctx.arg_types[0][0])
         if keys is None:
             ctx.api.fail(
                 message_registry.TYPEDDICT_KEY_MUST_BE_STRING_LITERAL,
-                ctx.context,
+                key_expr,
                 code=codes.LITERAL_REQ,
             )
             return AnyType(TypeOfAny.from_error)

         for key in keys:
             if key in ctx.type.required_keys or key in ctx.type.readonly_keys:
-                ctx.api.msg.typeddict_key_cannot_be_deleted(ctx.type, key, ctx.context)
+                ctx.api.msg.typeddict_key_cannot_be_deleted(ctx.type, key, key_expr)
             elif key not in ctx.type.items:
-                ctx.api.msg.typeddict_key_not_found(ctx.type, key, ctx.context)
+                ctx.api.msg.typeddict_key_not_found(ctx.type, key, key_expr)
     return ctx.default_return_type

diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test
index 44524b9df943..fd1778af59ab 100644
--- a/test-data/unit/check-columns.test
+++ b/test-data/unit/check-columns.test
@@ -227,9 +227,19 @@ class D(TypedDict):
     x: int
 t: D = {'x':
     'y'} # E:5: Incompatible types (expression has type "str", TypedDict item "x" has type "int")
+s: str

 if int():
-    del t['y'] # E:5: TypedDict "D" has no key "y"
+    del t[s]    # E:11: Expected TypedDict key to be string literal
+    del t["x"]  # E:11: Key "x" of TypedDict "D" cannot be deleted
+    del t["y"]  # E:11: TypedDict "D" has no key "y"
+
+t.pop(s)    # E:7: Expected TypedDict key to be string literal
+t.pop("y")  # E:7: TypedDict "D" has no key "y"
+
+t.setdefault(s, 123)    # E:14: Expected TypedDict key to be string literal
+t.setdefault("x", "a")  # E:19: Argument 2 to "setdefault" of "TypedDict" has incompatible type "str"; expected "int"
+t.setdefault("y", 123)  # E:14: TypedDict "D" has no key "y"
 [builtins fixtures/dict.pyi]
 [typing fixtures/typing-typeddict.pyi]

diff --git a/test-data/unit/check-literal.test b/test-data/unit/check-literal.test
index b2d3024d3b44..cff6e07670a7 100644
--- a/test-data/unit/check-literal.test
+++ b/test-data/unit/check-literal.test
@@ -1909,8 +1909,9 @@ reveal_type(d.get(a_key, u))  # N: Revealed type is "Union[builtins.int, __main_
 reveal_type(d.get(b_key, u))  # N: Revealed type is "Union[builtins.str, __main__.Unrelated]"
 reveal_type(d.get(c_key, u))  # N: Revealed type is "builtins.object"

-reveal_type(d.pop(a_key))     # E: Key "a" of TypedDict "Outer" cannot be deleted \
-                              # N: Revealed type is "builtins.int"
+reveal_type(d.pop(a_key))     # N: Revealed type is "builtins.int" \
+                              # E: Key "a" of TypedDict "Outer" cannot be deleted
+
 reveal_type(d.pop(b_key))     # N: Revealed type is "builtins.str"
 d.pop(c_key)                  # E: TypedDict "Outer" has no key "c"

diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test
index 6a86dd63a3cd..5234ced8ea86 100644
--- a/test-data/unit/check-typeddict.test
+++ b/test-data/unit/check-typeddict.test
@@ -1747,8 +1747,9 @@ td: Union[TDA, TDB]

 reveal_type(td.pop('a'))  # N: Revealed type is "builtins.int"
 reveal_type(td.pop('b'))  # N: Revealed type is "Union[builtins.str, builtins.int]"
-reveal_type(td.pop('c'))  # E: TypedDict "TDA" has no key "c" \
-                          # N: Revealed type is "Union[Any, builtins.int]"
+reveal_type(td.pop('c'))  # N: Revealed type is "Union[Any, builtins.int]" \
+                          # E: TypedDict "TDA" has no key "c"
+
 [builtins fixtures/dict.pyi]
 [typing fixtures/typing-typeddict.pyi]

@@ -2614,8 +2615,9 @@ def func(foo: Union[Foo1, Foo2]):

     del foo["missing"]  # E: TypedDict "Foo1" has no key "missing" \
                         # E: TypedDict "Foo2" has no key "missing"
-    del foo[1]  # E: Expected TypedDict key to be string literal \
-                # E: Argument 1 to "__delitem__" has incompatible type "int"; expected "str"
+    del foo[1]  # E: Argument 1 to "__delitem__" has incompatible type "int"; expected "str" \
+                # E: Expected TypedDict key to be string literal
+
 [builtins fixtures/dict.pyi]
 [typing fixtures/typing-typeddict.pyi]

@@ -3726,8 +3728,9 @@ class TP(TypedDict):
     mutable: bool

 x: TP
-reveal_type(x.pop("key"))  # E: Key "key" of TypedDict "TP" cannot be deleted \
-                           # N: Revealed type is "builtins.str"
+reveal_type(x.pop("key"))  # N: Revealed type is "builtins.str" \
+                           # E: Key "key" of TypedDict "TP" cannot be deleted
+

 x.update({"key": "abc", "other": 1, "mutable": True})  # E: ReadOnly TypedDict keys ("key", "other") TypedDict are mutated
 x.setdefault("key", "abc")  # E: ReadOnly TypedDict key "key" TypedDict is mutated

(🐞) Wrong column number for `TypedDict.setdefault`
```py
from typing import TypedDict

class A(TypedDict):
    x: int
a: A
a.setdefault('x', '')  # test.py:6:1: error: Argument 2 to "setdefault" of "TypedDict" has incompatible type "str"; expected "int"
```
column 1?

Internally an error with the correct column number is generated, but is filtered out as a duplicate.


diff --git a/mypy/semanal_typeargs.py b/mypy/semanal_typeargs.py
index 646bb28a3b6e..435abb78ca43 100644
--- a/mypy/semanal_typeargs.py
+++ b/mypy/semanal_typeargs.py
@@ -148,17 +148,18 @@ def validate_args(
         is_error = False
         is_invalid = False
         for (i, arg), tvar in zip(enumerate(args), type_vars):
+            context = ctx if arg.line < 0 else arg
             if isinstance(tvar, TypeVarType):
                 if isinstance(arg, ParamSpecType):
                     is_invalid = True
                     self.fail(
                         INVALID_PARAM_SPEC_LOCATION.format(format_type(arg, self.options)),
-                        ctx,
+                        context,
                         code=codes.VALID_TYPE,
                     )
                     self.note(
                         INVALID_PARAM_SPEC_LOCATION_NOTE.format(arg.name),
-                        ctx,
+                        context,
                         code=codes.VALID_TYPE,
                     )
                     continue
@@ -167,7 +168,7 @@ def validate_args(
                     self.fail(
                         f"Cannot use {format_type(arg, self.options)} for regular type variable,"
                         " only for ParamSpec",
-                        ctx,
+                        context,
                         code=codes.VALID_TYPE,
                     )
                     continue
@@ -182,13 +183,15 @@ def validate_args(
                             is_error = True
                             self.fail(
                                 message_registry.INVALID_TYPEVAR_AS_TYPEARG.format(arg.name, name),
-                                ctx,
+                                context,
                                 code=codes.TYPE_VAR,
                             )
                             continue
                     else:
                         arg_values = [arg]
-                    if self.check_type_var_values(name, arg_values, tvar.name, tvar.values, ctx):
+                    if self.check_type_var_values(
+                        name, arg_values, tvar.name, tvar.values, context
+                    ):
                         is_error = True
                 # Check against upper bound. Since it's object the vast majority of the time,
                 # add fast path to avoid a potentially slow subtype check.
@@ -209,7 +212,7 @@ def validate_args(
                             name,
                             format_type(upper_bound, self.options),
                         ),
-                        ctx,
+                        context,
                         code=codes.TYPE_VAR,
                     )
             elif isinstance(tvar, ParamSpecType):
@@ -220,7 +223,7 @@ def validate_args(
                     self.fail(
                         "Can only replace ParamSpec with a parameter types list or"
                         f" another ParamSpec, got {format_type(arg, self.options)}",
-                        ctx,
+                        context,
                         code=codes.VALID_TYPE,
                     )
         if is_invalid:

diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test
index 5ce80faaee18..a3d35da15107 100644
--- a/test-data/unit/check-classes.test
+++ b/test-data/unit/check-classes.test
@@ -6112,8 +6112,8 @@ A = G
 x: A[B[int]] # E
 B = G
 [out]
-main:8:4: error: Type argument "G[int]" of "G" must be a subtype of "str"
-main:8:6: error: Type argument "int" of "G" must be a subtype of "str"
+main:8:6: error: Type argument "G[int]" of "G" must be a subtype of "str"
+main:8:8: error: Type argument "int" of "G" must be a subtype of "str"

 [case testExtremeForwardReferencing]
 from typing import TypeVar, Generic
diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test
index 44524b9df943..79a2f31b574b 100644
--- a/test-data/unit/check-columns.test
+++ b/test-data/unit/check-columns.test
@@ -310,9 +310,18 @@ T = TypeVar('T', int, str)
 class C(Generic[T]):
     pass

-def f(c: C[object]) -> None: pass # E:10: Value of type variable "T" of "C" cannot be "object"
+def f(c: C[object]) -> None: pass # E:12: Value of type variable "T" of "C" cannot be "object"
 (C[object]()) # E:2: Value of type variable "T" of "C" cannot be "object"

+[case testColumnInvalidLocationForParamSpec]
+from typing import List
+from typing_extensions import ParamSpec
+
+P = ParamSpec('P')
+def foo(x: List[P]): pass  # E:17: Invalid location for ParamSpec "P" \
+                           # N:17: You can use ParamSpec as the first argument to Callable, e.g., "Callable[P, int]"
+[builtins fixtures/list.pyi]
+
 [case testColumnSyntaxErrorInTypeAnnotation]
 if int():
     def f(x # type: int,
diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test
index b8cc0422b749..5791b9c471d5 100644
--- a/test-data/unit/check-generics.test
+++ b/test-data/unit/check-generics.test
@@ -671,7 +671,7 @@ reveal_type(a) # N: Revealed type is "other.array[Any, other.dtype[builtins.floa
 [out]
 main:3: error: Type argument "float" of "Array" must be a subtype of "generic"  [type-var]
     a: other.Array[float]
-       ^
+                   ^
 [file other.py]
 from typing import Any, Generic, TypeVar

diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test
index 784b9db9f66e..81b0066dbf81 100644
--- a/test-data/unit/check-newsemanal.test
+++ b/test-data/unit/check-newsemanal.test
@@ -1666,8 +1666,8 @@ T = TypeVar('T', bound=int)
 class C(Generic[T]): pass
 class C2(Generic[T]): pass

-A = C[str] # E: Type argument "str" of "C" must be a subtype of "int" \
-           # E: Value of type variable "T" of "C" cannot be "str"
+A = C[str] # E: Value of type variable "T" of "C" cannot be "str" \
+           # E: Type argument "str" of "C" must be a subtype of "int"
 B = Union[C[str], int] # E: Type argument "str" of "C" must be a subtype of "int"
 S = TypeVar('S', bound=C[str]) # E: Type argument "str" of "C" must be a subtype of "int"
 U = TypeVar('U', C[str], str) # E: Type argument "str" of "C" must be a subtype of "int"

(🐞) Wrong column number for "Invalid location for ParamSpec"
```py
from typing import List, ParamSpec

P = ParamSpec('P')

def foo(x: List[P]) -> None: ...
```
```
test.py:5:13: error: Invalid location for ParamSpec "P"  [misc]
test.py:5:18: note: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]'
Found 2 errors in 1 file (checked 1 source file)
```

Column 13 is the `L` in `List`. The error and the note don't match up.

Notice that the error and the note specify different column numbers.

An internal error with the correct column number is generated, but is removed as a duplicate.

This has changed in master I think:
```
test.py:5:12: error: Invalid location for ParamSpec "P"  [misc]
test.py:5:12: note: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]'
Found 1 error in 1 file (checked 1 source file)
```

They have the same column now (still not on the `ParamSpec` though)


diff --git a/mypy/typeanal.py b/mypy/typeanal.py
index daf7ab1951ea..b7e7da17e209 100644
--- a/mypy/typeanal.py
+++ b/mypy/typeanal.py
@@ -2277,7 +2277,8 @@ def set_any_tvars(
         env[tv.id] = arg
     t = TypeAliasType(node, args, newline, newcolumn)
     if not has_type_var_tuple_type:
-        fixed = expand_type(t, env)
+        with state.strict_optional_set(options.strict_optional):
+            fixed = expand_type(t, env)
         assert isinstance(fixed, TypeAliasType)
         t.args = fixed.args

diff --git a/test-data/unit/check-typevar-defaults.test b/test-data/unit/check-typevar-defaults.test
index 3cd94f4a46d2..93d20eb26f6e 100644
--- a/test-data/unit/check-typevar-defaults.test
+++ b/test-data/unit/check-typevar-defaults.test
@@ -728,3 +728,24 @@ class C(Generic[_I]): pass

 t: type[C] | int = C
 [builtins fixtures/tuple.pyi]
+
+
+
+[case testGenericTypeAliasWithDefaultTypeVarPreservesNoneInDefault]
+from typing_extensions import TypeVar
+from typing import Generic, Union
+
+T1 = TypeVar("T1", default=Union[int, None])
+T2 = TypeVar("T2", default=Union[int, None])
+
+
+class A(Generic[T1, T2]):
+    def __init__(self, a: T1, b: T2) -> None:
+        self.a = a
+        self.b = b
+
+
+MyA = A[T1, int]
+a: MyA = A(None, 10)
+reveal_type(a.a)  # N: Revealed type is "Union[builtins.int, None]"
+[builtins fixtures/tuple.pyi]

Generic type aliases with TypeVar defaults infer to an incorrect type
<!--
If you're not sure whether what you're experiencing is a mypy bug, please see the "Question and Help" form instead.
Please consider:

- checking our common issues page: https://mypy.readthedocs.io/en/stable/common_issues.html
- searching our issue tracker: https://github.com/python/mypy/issues to see if it's already been reported
- asking on gitter chat: https://gitter.im/python/typing
-->

**Bug Report**

When using type alias of a generic type which uses type variables with defaults unbound type variables may infer to an incorrect default type.

<!--
If you're reporting a problem with a specific library function, the typeshed tracker is better suited for this report: https://github.com/python/typeshed/issues

If the project you encountered the issue in is open source, please provide a link to the project.
-->

**To Reproduce**

```python
from typing import Generic, TypeVar, TypeAlias

T1 = TypeVar('T1', default=int | None)
T2 = TypeVar('T2', default=int | None)

class A(Generic[T1, T2]):
    def __init__(self, a: T1, b: T2) -> None:
        self.a = a
        self.b = b

MyA: TypeAlias = A[T1, int]
a: MyA = A(None, 10)
```
https://mypy-play.net/?mypy=latest&python=3.12&gist=abece06adfb80e28c6d23bd99997964e

**Expected Behavior**

`MyA` should preserve `T1` default type, which is `int | None`

**Actual Behavior**

`T1` is inferred to `int` default in `MyA`, so assignment to `a` fails with:

`Argument 1 to "A" has incompatible type "None"; expected "int"  [arg-type]`

<!-- What went wrong? Paste mypy's output. -->

**Your Environment**

<!-- Include as many relevant details about the environment you experienced the bug in -->

- Mypy version used: 1.13
- Python version used: 3.12

<!-- You can freely edit this text, please remove all the lines you believe are unnecessary. -->


diff --git a/mypy/subtypes.py b/mypy/subtypes.py
index 11f3421331a5..a26aaf798b58 100644
--- a/mypy/subtypes.py
+++ b/mypy/subtypes.py
@@ -910,14 +910,12 @@ def visit_typeddict_type(self, left: TypedDictType) -> bool:
                     return False
                 # Non-required key is not compatible with a required key since
                 # indexing may fail unexpectedly if a required key is missing.
-                # Required key is not compatible with a non-required key since
-                # the prior doesn't support 'del' but the latter should support
-                # it.
-                #
-                # NOTE: 'del' support is currently not implemented (#3550). We
-                #       don't want to have to change subtyping after 'del' support
-                #       lands so here we are anticipating that change.
-                if (name in left.required_keys) != (name in right.required_keys):
+                # Required key is not compatible with a non-read-only non-required
+                # key since the prior doesn't support 'del' but the latter should
+                # support it.
+                # Required key is compatible with a read-only non-required key.
+                required_differ = (name in left.required_keys) != (name in right.required_keys)
+                if not right_readonly and required_differ:
                     return False
                 # Readonly fields check:
                 #

diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test
index affa472bb640..521a5b80573d 100644
--- a/test-data/unit/check-typeddict.test
+++ b/test-data/unit/check-typeddict.test
@@ -3894,6 +3894,20 @@ accepts_B(b)
 [builtins fixtures/dict.pyi]
 [typing fixtures/typing-typeddict.pyi]

+[case testTypedDictRequiredConsistentWithNotRequiredReadOnly]
+from typing import NotRequired, ReadOnly, Required, TypedDict
+
+class A(TypedDict):
+    x: NotRequired[ReadOnly[str]]
+
+class B(TypedDict):
+    x: Required[str]
+
+def f(b: B):
+    a: A = b  # ok
+[builtins fixtures/dict.pyi]
+[typing fixtures/typing-typeddict.pyi]
+
 [case testTypedDictReadOnlyCall]
 from typing import ReadOnly, TypedDict

`arg-type` error duck typing a `TypedDict` with `NotRequired` field
**Bug Report**

[mypy play url](https://mypy-play.net/?mypy=latest&python=3.12&gist=e6a8b78acddafd1ad10e81364e8e9ab5)

it seems that mypy doesn't "match" a `NotRequired` field with a normal one when duck typing 2 different typed dict:

Let's say that I have a function `foo` that expect a `Small` TypedDict as parameter

```python
class Small(TypedDict):
    a: NotRequired[str]

def foo(small: Small) -> None: ...
```

In this `Small` TypedDict the field `a` is marked as `NotRequired`.

Elsewere I have another `Big` TypedDict with 2 fields `a`, and `b`, both required.

```python
class Big(TypedDict):
    a: str
    b: str
```

but if I try to pass a `Big` dict instance to my `foo` function, mypy mark it as an error:
`main.py:21: error: Argument 1 to "foo" has incompatible type "Big"; expected "Small"  [arg-type]`

If I change the type of `Big.a` to a `NotRequired[str]`, mypy is happy, however mypy should allow the original definition, as a "normal" field should be treated as a stricter, "smaller" version of a not required one

One wrinkle is that `Small` allows deleting keys whereas `Big` does not, which makes passing a `Big` where a `Small` is expected potentially unsound.

Consider:
```python
from typing import NotRequired, TypedDict

class Big(TypedDict):
    a: str
    b: str

class Small(TypedDict):
    a: NotRequired[str]

def foo(small: Small) -> None:
    del small["a"]  # ok, deleting NotRequired keys is permitted

x = Big(a="a", b="b")
foo(x)  # danger! If this was legal, x would no longer be a valid Big
```

However, if you prevent key deletion using [`ReadOnly`](https://peps.python.org/pep-0705/), I think this would be safe. Pyright seems to support this, provided that the `NotRequired` fields are `ReadOnly`: [[pyright playground]](https://pyright-play.net/?pythonVersion=3.12&code=GYJw9gtgBALgngBwJYDsDmUkQWEMoByYMASgKYCOArkiGQCYA0UAKogwCJIDGMAsAChQkWIlRoA%2BmQAeMMigDOSMIszZc%2BcgEN6AeRQAbOIMHcDWhQqgAhJGgAUbBJx4wAlAC5BUH1C0eoBRgQb18AIwCgkIFfKFNzSygAZQgtAwNHdnouXk9Qn38obT1DOABtIlJKGjp6MqiAXQb8uIF6MmAoYDAwewVU9ICUtIM3KABaAD5CFTIvGN8ECwUWgGIodoNAgYMygCItPeaFn0FpKABeGzt7LQuDveYw%2B7C9t0Fu3uk3IA)


diff --git a/mypy/checker.py b/mypy/checker.py
index 1bee348bc252..ef3f7502d7ce 100644
--- a/mypy/checker.py
+++ b/mypy/checker.py
@@ -6274,10 +6274,6 @@ def has_no_custom_eq_checks(t: Type) -> bool:
                 coerce_only_in_literal_context,
             )

-        # Strictly speaking, we should also skip this check if the objects in the expr
-        # chain have custom __eq__ or __ne__ methods. But we (maybe optimistically)
-        # assume nobody would actually create a custom objects that considers itself
-        # equal to None.
         if if_map == {} and else_map == {}:
             if_map, else_map = self.refine_away_none_in_comparison(
                 operands, operand_types, expr_indices, narrowable_operand_index_to_hash.keys()
@@ -6602,25 +6598,36 @@ def refine_away_none_in_comparison(
         For more details about what the different arguments mean, see the
         docstring of 'refine_identity_comparison_expression' up above.
         """
+
         non_optional_types = []
         for i in chain_indices:
             typ = operand_types[i]
             if not is_overlapping_none(typ):
                 non_optional_types.append(typ)

-        # Make sure we have a mixture of optional and non-optional types.
-        if len(non_optional_types) == 0 or len(non_optional_types) == len(chain_indices):
-            return {}, {}
+        if_map, else_map = {}, {}

-        if_map = {}
-        for i in narrowable_operand_indices:
-            expr_type = operand_types[i]
-            if not is_overlapping_none(expr_type):
-                continue
-            if any(is_overlapping_erased_types(expr_type, t) for t in non_optional_types):
-                if_map[operands[i]] = remove_optional(expr_type)
+        if not non_optional_types or (len(non_optional_types) != len(chain_indices)):

-        return if_map, {}
+            # Narrow e.g. `Optional[A] == "x"` or `Optional[A] is "x"` to `A` (which may be
+            # convenient but is strictly not type-safe):
+            for i in narrowable_operand_indices:
+                expr_type = operand_types[i]
+                if not is_overlapping_none(expr_type):
+                    continue
+                if any(is_overlapping_erased_types(expr_type, t) for t in non_optional_types):
+                    if_map[operands[i]] = remove_optional(expr_type)
+
+            # Narrow e.g. `Optional[A] != None` to `A` (which is stricter than the above step and
+            # so type-safe but less convenient, because e.g. `Optional[A] == None` still results
+            # in `Optional[A]`):
+            if any(isinstance(get_proper_type(ot), NoneType) for ot in operand_types):
+                for i in narrowable_operand_indices:
+                    expr_type = operand_types[i]
+                    if is_overlapping_none(expr_type):
+                        else_map[operands[i]] = remove_optional(expr_type)
+
+        return if_map, else_map

     def is_len_of_tuple(self, expr: Expression) -> bool:
         """Is this expression a `len(x)` call where x is a tuple or union of tuples?"""

diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test
index d740708991d0..bc763095477e 100644
--- a/test-data/unit/check-narrowing.test
+++ b/test-data/unit/check-narrowing.test
@@ -1385,9 +1385,9 @@ val: Optional[A]
 if val == None:
     reveal_type(val)  # N: Revealed type is "Union[__main__.A, None]"
 else:
-    reveal_type(val)  # N: Revealed type is "Union[__main__.A, None]"
+    reveal_type(val)  # N: Revealed type is "__main__.A"
 if val != None:
-    reveal_type(val)  # N: Revealed type is "Union[__main__.A, None]"
+    reveal_type(val)  # N: Revealed type is "__main__.A"
 else:
     reveal_type(val)  # N: Revealed type is "Union[__main__.A, None]"

`==`-based narrowing of `Optional`
1. Mypy's current behaviour:

```python
x: int | None
if x == None:
    x  # "Union[builtins.int, None]"
else:
    x  # "Union[builtins.int, None]"
```

2. Pyright's current behaviour:

```python
x: int | None
if x == None:
    x  # x is None
else:
    x  # x is int
```

3. I think the ideal solution would be:

```python
x: int | None
if x == None:
    x  # "Union[builtins.int, None]"
else:
    x  # "builtins.int"
```

This [Mypy code comment](https://github.com/python/mypy/blob/3b00002acdf098e7241df8f2e1843f8b8260b168/mypy/checker.py#L6278-L6280) seems to favour solution 2.

I am asking because if Mypy would follow solution 2 or 3, `in`-based narrowing of optional types could be implemented more consistently.

Related pull requests: #15760 #17154 #17044.

I think both 2 and 3 are fine. If we go with 3, we should look at presence of `__eq__` (`int` has `__eq__` defined, not sure why, dates back to 2015)
Did you mean we should check for `__eq__` when going for solution **2**?

If so, this could be an additional safety net for most cases.  Then, the modified solution 2 would only result in wrong narrowing for subtypes that override `__eq__` strangely:

```python
class A: ...

class B(A):
    def __eq__(self, o: object) -> bool:
        return True

def f(x: A | None) -> None:
    if x == None:
        assert x is None

f(B())  # AssertionError
```

I think, for complete safety, we would have to combine looking for `__eq__` with checking for `final`:

```python
from typing import final

@final
class A: ...

def f(x: A | None) -> None:
    if x == None:
        reveal_type(x)  # must be None
```


diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py
index 577576a4e5f8..11a9cffe18c3 100644
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -5612,11 +5612,15 @@ def visit_slice_expr(self, e: SliceExpr) -> Type:
         except KeyError:
             supports_index = self.chk.named_type("builtins.int")  # thanks, fixture life
         expected = make_optional_type(supports_index)
+        type_args = []
         for index in [e.begin_index, e.end_index, e.stride]:
             if index:
                 t = self.accept(index)
                 self.chk.check_subtype(t, expected, index, message_registry.INVALID_SLICE_INDEX)
-        return self.named_type("builtins.slice")
+                type_args.append(t)
+            else:
+                type_args.append(NoneType())
+        return self.chk.named_generic_type("builtins.slice", type_args)

     def visit_list_comprehension(self, e: ListComprehension) -> Type:
         return self.check_generator_or_comprehension(

diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test
index d5ddc910bcd6..cd26c9bb408a 100644
--- a/test-data/unit/check-expressions.test
+++ b/test-data/unit/check-expressions.test
@@ -1178,8 +1178,8 @@ class B: pass
 [case testSlicingWithInvalidBase]

 a: A
-a[1:2] # E: Invalid index type "slice" for "A"; expected type "int"
-a[:]   # E: Invalid index type "slice" for "A"; expected type "int"
+a[1:2] # E: Invalid index type "slice[int, int, None]" for "A"; expected type "int"
+a[:]   # E: Invalid index type "slice[None, None, None]" for "A"; expected type "int"
 class A:
   def __getitem__(self, n: int) -> 'A': pass
 [builtins fixtures/slice.pyi]

Change in inference of overloads involving `Hashable` and `slice` now that `slice` is generic
**Bug Report**

Consider the following Python snippet, saved as `foo.pyi`:

```py
from typing import assert_type, overload, Hashable

class Foo: ...

class DataFrame:
    @overload
    def __getitem__(self, key: slice) -> DataFrame: ...
    @overload
    def __getitem__(self, key: Hashable) -> Foo: ...

df = DataFrame()
assert_type(df[1:], DataFrame)
assert_type(df[:2], DataFrame)
```

Prior to [the recent change to make `slice` generic in typeshed](https://github.com/python/typeshed/pull/11637), mypy used to emit no errors on this snippet. However, mypy on the `master` branch emits the following errors:

```
foo.pyi:7: error: Overloaded function signatures 1 and 2 overlap with incompatible return types  [overload-overlap]
foo.pyi:13: error: Expression is of type "Any", not "DataFrame"  [assert-type]
foo.pyi:14: error: Expression is of type "Any", not "DataFrame"  [assert-type]
```

The first error here seems reasonable to me, but it's unclear to me why mypy now infers `Any` as the result of the `df` subscriptions. This snippet is minimized from the sole new mypy_primer error reported in https://github.com/python/typeshed/pull/11637#issuecomment-2435268577.

**To Reproduce**

https://mypy-play.net/?mypy=master&python=3.12&gist=339ba7f72c9048770ce15d6dc75207a1

**Your Environment**

- Mypy version used: mypy 1.14.0+dev.2ebc690279c7e20ed8bec006787030c5ba57c40e (compiled: no)

I think this is because since python 3.12, slice is hashable, hence it satisfies both overloads and mypy performs a join of the return types. When you run with 3.11 the error disappears:

https://mypy-play.net/?mypy=master&python=3.11&gist=339ba7f72c9048770ce15d6dc75207a1
@AlexWaygood Uhh, I just discovered that it actually seems to be related to the bug #2410 we just encountered in typeshed as well, because when you use non-literal slices it also disappears!

```python
from typing import assert_type, overload, Hashable

class Foo: ...

class DataFrame:
    @overload
    def __getitem__(self, key: slice, /) -> "DataFrame": ...
    @overload
    def __getitem__(self, key: Hashable, /) -> Foo: ...

df = DataFrame()
assert_type(df[1:], DataFrame)  # ❌
assert_type(df[:2], DataFrame)  # ❌
assert_type(df[slice(1, None)], DataFrame)  # ✅
assert_type(df[slice(None, 2)], DataFrame)  # ✅
```

https://mypy-play.net/?mypy=master&python=3.12&gist=935d2927539dbe01d6727037ace98469

----

I was wondering about this because according to https://mypy.readthedocs.io/en/stable/more_types.html#type-checking-calls-to-overloads, no join operation should happen. I guess there is some legacy code responsible for dealing with literal slices in `__getitem__` that's going haywire?

> I guess there is some legacy code responsible for dealing with literal slices in `__getitem__` that's going haywire?

~Indeed, this is actually hardcoded into the expression checker:~ Nevermind, I had my wires crossed about what this issue was about, sorry for the noise!

[https://github.com/python/mypy/blob/2ebc690279c7e20ed8bec006787030c5ba57c40e/mypy/checkexpr.py#L5609-L5619.](https://github.com/python/mypy/blob/2ebc690279c7e20ed8bec006787030c5ba57c40e/mypy/checkexpr.py#L5609-L5619)
Actually, my previous comment wasn't as far from the mark as I thought :laughing:

The difference between slice expressions and non-literal slices does come down to the hardcoded analysis in the expression checker, specifically the return:

https://github.com/python/mypy/blob/2ebc690279c7e20ed8bec006787030c5ba57c40e/mypy/checkexpr.py#L5619

This erases any type information and makes all slice expressions be treated as `slice[Any, Any, Any]`. Manually passing a slice of type `slice[Any, Any, Any]` indeed has the same behavior:
```python
df = DataFrame()
x: slice[Any, Any, Any]
assert_type(df[x], DataFrame)  # E: Expression is of type "Any", not "DataFrame"
```
I'm not fully sure why passing `slice[Any, Any, Any]` causes the overload return type to resolve to `Any`, but I think it may have to do with the way [`infer_overload_return_type`](https://github.com/python/mypy/blob/2ebc690279c7e20ed8bec006787030c5ba57c40e/mypy/checkexpr.py#L2838) resolves ambiguous overloads, specifically now that this check will resolve to True:
https://github.com/python/mypy/blob/2ebc690279c7e20ed8bec006787030c5ba57c40e/mypy/checkexpr.py#L2862
so this branch can no longer be taken:
https://github.com/python/mypy/blob/2ebc690279c7e20ed8bec006787030c5ba57c40e/mypy/checkexpr.py#L2882-L2884

I think the fix would be to just properly infer the generic type arguments for slice expressions. Naively that could look something like the following, though we'd probably want to make it match the behavior of `slice.__new__` in typeshed.
```diff
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -5612,11 +5612,15 @@ class ExpressionChecker(ExpressionVisitor[Type]):
         except KeyError:
             supports_index = self.chk.named_type("builtins.int")  # thanks, fixture life
         expected = make_optional_type(supports_index)
+        type_args = []
         for index in [e.begin_index, e.end_index, e.stride]:
             if index:
                 t = self.accept(index)
                 self.chk.check_subtype(t, expected, index, message_registry.INVALID_SLICE_INDEX)
-        return self.named_type("builtins.slice")
+                type_args.append(t)
+            else:
+                type_args.append(NoneType())
+        return self.chk.named_generic_type("builtins.slice", type_args)
```


diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py
index 6b4fa35f9c49..a7121712a6db 100644
--- a/mypy/checkpattern.py
+++ b/mypy/checkpattern.py
@@ -693,7 +693,9 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType:

     def should_self_match(self, typ: Type) -> bool:
         typ = get_proper_type(typ)
-        if isinstance(typ, Instance) and typ.type.is_named_tuple:
+        if isinstance(typ, Instance) and typ.type.get("__match_args__") is not None:
+            # Named tuples and other subtypes of builtins that define __match_args__
+            # should not self match.
             return False
         for other in self.self_match_types:
             if is_subtype(typ, other):

diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test
index 58b70d7b74d8..8187f27353a9 100644
--- a/test-data/unit/check-python310.test
+++ b/test-data/unit/check-python310.test
@@ -648,6 +648,25 @@ match m:
         reveal_type(m)  # N: Revealed type is "builtins.tuple[Any, ...]"
 [builtins fixtures/primitives.pyi]

+[case testMatchClassPatternCaptureSelfSubtype]
+class A(str):
+    pass
+
+class B(str):
+    __match_args__ = ("b",)
+    b: int
+
+def f1(x: A):
+    match x:
+        case A(a):
+            reveal_type(a)  # N: Revealed type is "__main__.A"
+
+def f2(x: B):
+    match x:
+        case B(b):
+            reveal_type(b)  # N: Revealed type is "builtins.int"
+[builtins fixtures/tuple.pyi]
+
 [case testMatchInvalidClassPattern]
 m: object

Positional subpattern of a built-in type subclass with __match_args__ causes type confusion
Given

```python
class PrintableKey(bytes):
    __match_args__ = ('ch', )

    @property
    def ch(self) -> str:
        return self.decode('UTF-8')
```

now

```python
match event:
    case PrintableKey(ch):
        reveal_type(ch)  # mypy thinks it's PrintableKey
```

versus

```python
match event:
    case PrintableKey(ch=ch):
        reveal_type(ch)  # mypy correctly deduces it's str
```

_Originally posted by @mgedmin in https://github.com/python/mypy/issues/13804#issuecomment-2466177933_


diff --git a/mypy/semanal.py b/mypy/semanal.py
index 59e4594353f0..1f5f31d59e32 100644
--- a/mypy/semanal.py
+++ b/mypy/semanal.py
@@ -484,6 +484,12 @@ def __init__(
         # Used to pass information about current overload index to visit_func_def().
         self.current_overload_item: int | None = None

+        # Used to track whether currently inside an except* block. This helps
+        # to invoke errors when continue/break/return is used inside except* block.
+        self.inside_except_star_block: bool = False
+        # Used to track edge case when return is still inside except* if it enters a loop
+        self.return_stmt_inside_except_star_block: bool = False
+
     # mypyc doesn't properly handle implementing an abstractproperty
     # with a regular attribute so we make them properties
     @property
@@ -511,6 +517,25 @@ def allow_unbound_tvars_set(self) -> Iterator[None]:
         finally:
             self.allow_unbound_tvars = old

+    @contextmanager
+    def inside_except_star_block_set(
+        self, value: bool, entering_loop: bool = False
+    ) -> Iterator[None]:
+        old = self.inside_except_star_block
+        self.inside_except_star_block = value
+
+        # Return statement would still be in except* scope if entering loops
+        if not entering_loop:
+            old_return_stmt_flag = self.return_stmt_inside_except_star_block
+            self.return_stmt_inside_except_star_block = value
+
+        try:
+            yield
+        finally:
+            self.inside_except_star_block = old
+            if not entering_loop:
+                self.return_stmt_inside_except_star_block = old_return_stmt_flag
+
     #
     # Preparing module (performed before semantic analysis)
     #
@@ -877,7 +902,8 @@ def visit_func_def(self, defn: FuncDef) -> None:
             return

         with self.scope.function_scope(defn):
-            self.analyze_func_def(defn)
+            with self.inside_except_star_block_set(value=False):
+                self.analyze_func_def(defn)

     def function_fullname(self, fullname: str) -> str:
         if self.current_overload_item is None:
@@ -5263,6 +5289,8 @@ def visit_return_stmt(self, s: ReturnStmt) -> None:
         self.statement = s
         if not self.is_func_scope():
             self.fail('"return" outside function', s)
+        if self.return_stmt_inside_except_star_block:
+            self.fail('"return" not allowed in except* block', s, serious=True)
         if s.expr:
             s.expr.accept(self)

@@ -5296,7 +5324,8 @@ def visit_while_stmt(self, s: WhileStmt) -> None:
         self.statement = s
         s.expr.accept(self)
         self.loop_depth[-1] += 1
-        s.body.accept(self)
+        with self.inside_except_star_block_set(value=False, entering_loop=True):
+            s.body.accept(self)
         self.loop_depth[-1] -= 1
         self.visit_block_maybe(s.else_body)

@@ -5320,20 +5349,24 @@ def visit_for_stmt(self, s: ForStmt) -> None:
                 s.index_type = analyzed

         self.loop_depth[-1] += 1
-        self.visit_block(s.body)
+        with self.inside_except_star_block_set(value=False, entering_loop=True):
+            self.visit_block(s.body)
         self.loop_depth[-1] -= 1
-
         self.visit_block_maybe(s.else_body)

     def visit_break_stmt(self, s: BreakStmt) -> None:
         self.statement = s
         if self.loop_depth[-1] == 0:
             self.fail('"break" outside loop', s, serious=True, blocker=True)
+        if self.inside_except_star_block:
+            self.fail('"break" not allowed in except* block', s, serious=True)

     def visit_continue_stmt(self, s: ContinueStmt) -> None:
         self.statement = s
         if self.loop_depth[-1] == 0:
             self.fail('"continue" outside loop', s, serious=True, blocker=True)
+        if self.inside_except_star_block:
+            self.fail('"continue" not allowed in except* block', s, serious=True)

     def visit_if_stmt(self, s: IfStmt) -> None:
         self.statement = s
@@ -5354,7 +5387,8 @@ def analyze_try_stmt(self, s: TryStmt, visitor: NodeVisitor[None]) -> None:
                 type.accept(visitor)
             if var:
                 self.analyze_lvalue(var)
-            handler.accept(visitor)
+            with self.inside_except_star_block_set(self.inside_except_star_block or s.is_star):
+                handler.accept(visitor)
         if s.else_body:
             s.else_body.accept(visitor)
         if s.finally_body:

diff --git a/test-data/unit/check-python311.test b/test-data/unit/check-python311.test
index 28951824999f..6f4c540572b0 100644
--- a/test-data/unit/check-python311.test
+++ b/test-data/unit/check-python311.test
@@ -173,3 +173,89 @@ Alias4 = Callable[[*IntList], int]  # E: "List[int]" cannot be unpacked (must be
 x4: Alias4[int]  # E: Bad number of arguments for type alias, expected 0, given 1
 reveal_type(x4)  # N: Revealed type is "def (*Any) -> builtins.int"
 [builtins fixtures/tuple.pyi]
+
+[case testReturnInExceptStarBlock1]
+# flags: --python-version 3.11
+def foo() -> None:
+    try:
+        pass
+    except* Exception:
+        return   # E: "return" not allowed in except* block
+    finally:
+        return
+[builtins fixtures/exception.pyi]
+
+[case testReturnInExceptStarBlock2]
+# flags: --python-version 3.11
+def foo():
+    while True:
+        try:
+            pass
+        except* Exception:
+            while True:
+                return  # E: "return" not allowed in except* block
+[builtins fixtures/exception.pyi]
+
+[case testContinueInExceptBlockNestedInExceptStarBlock]
+# flags: --python-version 3.11
+while True:
+    try:
+        ...
+    except* Exception:
+        try:
+            ...
+        except Exception:
+            continue  # E: "continue" not allowed in except* block
+        continue  # E: "continue" not allowed in except* block
+[builtins fixtures/exception.pyi]
+
+[case testReturnInExceptBlockNestedInExceptStarBlock]
+# flags: --python-version 3.11
+def foo():
+    try:
+        ...
+    except* Exception:
+        try:
+            ...
+        except Exception:
+            return  # E: "return" not allowed in except* block
+        return  # E: "return" not allowed in except* block
+[builtins fixtures/exception.pyi]
+
+[case testBreakContinueReturnInExceptStarBlock1]
+# flags: --python-version 3.11
+from typing import Iterable
+def foo(x: Iterable[int]) -> None:
+    for _ in x:
+        try:
+            pass
+        except* Exception:
+            continue   # E: "continue" not allowed in except* block
+        except* Exception:
+            for _ in x:
+                continue
+            break  # E: "break" not allowed in except* block
+        except* Exception:
+            return  # E: "return" not allowed in except* block
+[builtins fixtures/exception.pyi]
+
+[case testBreakContinueReturnInExceptStarBlock2]
+# flags: --python-version 3.11
+def foo():
+    while True:
+        try:
+            pass
+        except* Exception:
+            def inner():
+                while True:
+                    if 1 < 1:
+                        continue
+                    else:
+                        break
+                return
+            if 1 < 2:
+                break  # E: "break" not allowed in except* block
+            if 1 < 2:
+                continue  # E: "continue" not allowed in except* block
+            return  # E: "return" not allowed in except* block
+[builtins fixtures/exception.pyi]

mypy doesn't flag continue/break/return in except*
**Feature**
continue/break/return in except* is a syntax error, see https://peps.python.org/pep-0654/#forbidden-combinations.

```python
def foo():
    for _ in range(5):
        try:
            ...
        except* Exception:
            continue
        except* ValueError:
            break
        except* TypeError:
            return
```
```sh
$ mypy --python-version=3.11 foo.py
Success: no issues found in 1 source file
$ mypy --version
mypy 1.13.0 (compiled: yes)
```

**Pitch**
mypy does give an error if you try to combine `except` and `except*`, and as far as I know it flags all other syntax errors as well, so should probably handle this too. It might also cause users to adjust code to avoid `unreachable code` needlessly, when in fact they have bigger problems to fix first.

I'd like to work on this!
@coldwolverine great! You can check out [CONTRIBUTING.md](https://github.com/python/mypy/blob/master/CONTRIBUTING.md) and the [Developer Guides](https://github.com/python/mypy/wiki/Developer-Guides) for contributing guidelines and tips on where to start.

I'm guessing this feature will involve adding some new state to the semantic analyzer to keep track of whether its currently inside an `except*` block. While working on this feature, be mindful of edge cases like nested try statements and function definitions or loops inside the  `except*` block.


diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py
index 6b4fa35f9c49..4323daa68025 100644
--- a/mypy/checkpattern.py
+++ b/mypy/checkpattern.py
@@ -158,7 +158,8 @@ def visit_or_pattern(self, o: OrPattern) -> PatternType:
         for pattern in o.patterns:
             pattern_type = self.accept(pattern, current_type)
             pattern_types.append(pattern_type)
-            current_type = pattern_type.rest_type
+            if not is_uninhabited(pattern_type.type):
+                current_type = pattern_type.rest_type

         #
         # Collect the final type

diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test
index 58b70d7b74d8..3ef964d3c0b9 100644
--- a/test-data/unit/check-python310.test
+++ b/test-data/unit/check-python310.test
@@ -1702,6 +1702,22 @@ def f(x: int | str) -> int:
         case str() as s:
             return 1

+[case testMatchOrPatternExhaustiveness]
+from typing import NoReturn, Literal
+def assert_never(x: NoReturn) -> None: ...
+
+Color = Literal["blue", "green", "red"]
+c: Color
+
+match c:
+    case "blue":
+        reveal_type(c) # N: Revealed type is "Literal['blue']"
+    case "green" | "notColor":
+        reveal_type(c) # N: Revealed type is "Literal['green']"
+    case _:
+        assert_never(c) # E: Argument 1 to "assert_never" has incompatible type "Literal['red']"; expected "Never"
+[typing fixtures/typing-typeddict.pyi]
+
 [case testMatchAsPatternIntersection-skip]
 class A: pass
 class B: pass

Structural Pattern Matching Exhaustiveness check when using OR
<!--
If you're not sure whether what you're experiencing is a mypy bug, please see the "Question and Help" form instead.
Please consider:

- checking our common issues page: https://mypy.readthedocs.io/en/stable/common_issues.html
- searching our issue tracker: https://github.com/python/mypy/issues to see if it's already been reported
- asking on gitter chat: https://gitter.im/python/typing
-->

**Bug Report**

Mypy fails to identify missing value comparisons in my `match` when I use `|`

**To Reproduce**

[Gist URL](https://gist.github.com/mypy-play/cba9c66b56fcbfbd383ca559518ebac5)
[Playground URL](https://mypy-play.net/?mypy=latest&python=3.12&flags=strict&gist=cba9c66b56fcbfbd383ca559518ebac5)

```python
from typing import Literal, assert_never

Color = Literal["blue", "green", "red"]

def print_color(color: Color) -> None:
  match color:
      case "blue":
          print("blue")
      case "green" | "kangaroo":
          print("green")
      case _:
          assert_never(color)
```

**Expected Behavior**

I expected mypy to error because I missed checking against `red`
```console
colors.py:13: error: Argument 1 to "assert_never" has incompatible type "Literal['red']"; expected "Never"  [arg-type]
Found 1 error in 1 file (checked 1 source file)
```

**Actual Behavior**

Mypy doesn't raise any errors

```console
Success: no issues found in 1 source file
```

** Extra Context **

This only happens when I use `|`.
I don't use pyright but ran it to see if I was the one missing something but I believe they do flag it correctly
```console
colors.py:13:24 - error: Argument of type "Literal['red']" cannot be assigned to parameter "arg" of type "Never" in function "assert_never"
    Type "Literal['red']" is not assignable to type "Never" (reportArgumentType)
```

**Your Environment**

- Mypy version used: `mypy 1.13.0 (compiled: yes)`
- Mypy command-line flags: `--strict`
- Python version used: `Python 3.11.6`


diff --git a/mypy/subtypes.py b/mypy/subtypes.py
index a63db93fd9cb..11f3421331a5 100644
--- a/mypy/subtypes.py
+++ b/mypy/subtypes.py
@@ -625,8 +625,8 @@ def visit_instance(self, left: Instance) -> bool:
                         return is_named_instance(item, "builtins.object")
         if isinstance(right, LiteralType) and left.last_known_value is not None:
             return self._is_subtype(left.last_known_value, right)
-        if isinstance(right, CallableType):
-            # Special case: Instance can be a subtype of Callable.
+        if isinstance(right, FunctionLike):
+            # Special case: Instance can be a subtype of Callable / Overloaded.
             call = find_member("__call__", left, left, is_operator=True)
             if call:
                 return self._is_subtype(call, right)

diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test
index 5ed2351e33e6..0367be3dde65 100644
--- a/test-data/unit/check-protocols.test
+++ b/test-data/unit/check-protocols.test
@@ -4215,3 +4215,24 @@ def g4(a: Input[bytes], b: Output[str]) -> None:
     f(a, b)  # E: Cannot infer type argument 1 of "f"

 [builtins fixtures/tuple.pyi]
+
+[case testOverloadProtocolSubtyping]
+from typing import Protocol, Self, overload
+
+class NumpyFloat:
+    __add__: "FloatOP"
+
+class FloatOP(Protocol):
+    @overload
+    def __call__(self, other: float) -> NumpyFloat: ...
+    @overload
+    def __call__(self, other: NumpyFloat) -> NumpyFloat: ...
+
+class SupportsAdd(Protocol):
+    @overload
+    def __add__(self, other: float) -> Self: ...
+    @overload
+    def __add__(self, other: NumpyFloat) -> Self: ...
+
+x: SupportsAdd = NumpyFloat()
+[builtins fixtures/tuple.pyi]

Problems with "expected overloaded function" when method hinted via Callback Protocol (⇝`numpy`)
**Bug Report**

`mypy` complains about expecting an overloaded function, when a method is hinted by a Callback-Protocol. This technique is used in the `numpy` stubs, and causes `mypy` to complain when trying to describe numpy scalars with simple protocols.

**To Reproduce**

Below is a MWE [[mypy-playground]](https://mypy-play.net/?mypy=latest&python=3.12&gist=8041e0145f43507bed8c86104a5fb5b2), based on how the [numpy stubs declare the methods on scalars](https://github.com/numpy/numpy/blob/bd1f6067a13f8bbdf99871277426dfaad9f7602d/numpy/__init__.pyi#L3582). Note that [[pyright-playground]](https://pyright-play.net/?code=GYJw9gtgBALgngBwJYDsDmUkQWEMoAK4MYAxmADYA0UAygKYXA1gBu9IFYAhgCYBQ-UhW4BnUVAByAV2xwAYl24wAXPygaoAfS19eOlVABEinjADyBI4OFiJp5ZYAURMCXIUAlGs1QAAmwcSgK%2BvPTA2lqk3BQUOk6ijMxQbgAWHIbASjCeUAC0AHxSsggK2YYAdFXqmgHsnDwhmmEROtGx8YlMLDDpIIYycg45%2BUWDpcOV1UIi4nTSCDh4ogCCvLwuxGSU3jUadUGNe1AtkXqdST19mdm5hXRJUxXHBw18x6c651oJlym9GWKQ1uoweTCeggAHoZaAsljBVusoABeIETbJOTz8IA) does not report any issues.

```python
from typing import Protocol, Self, overload

class NumpyFloat:
    __add__: "FloatOP"

class FloatOP(Protocol):
    @overload
    def __call__(self, other: float) -> NumpyFloat: ...
    @overload
    def __call__(self, other: NumpyFloat) -> NumpyFloat: ...

class SupportsAdd(Protocol):
    @overload
    def __add__(self, other: float) -> Self: ...
    @overload
    def __add__(self, other: NumpyFloat) -> Self: ...

x: SupportsAdd = NumpyFloat()  # expected overloaded function, got "FloatOP"
```

Concrete example with `numpy==2.1.3` (again, `pyright` reports no errors):

```python
from typing import Protocol, Self, overload
import numpy as np

class TimeDelta(Protocol):
    def __sub__(self, other: Self, /) -> Self: ...

class TimeStamp[TD: TimeDelta](Protocol):
    @overload
    def __sub__(self, other: Self, /) -> TD: ...
    @overload
    def __sub__(self, other: TD, /) -> Self: ...

x: TimeStamp[np.timedelta64] = np.datetime64("2021-01-01")  # ✅
y: TimeStamp[np.float64] = np.float64(10.0)  # expected overloaded function, got "_FloatOp[_64Bit]"
```


diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py
index 6b4fa35f9c49..f54b3c53f907 100644
--- a/mypy/checkpattern.py
+++ b/mypy/checkpattern.py
@@ -46,6 +46,7 @@
     TypedDictType,
     TypeOfAny,
     TypeVarTupleType,
+    TypeVarType,
     UninhabitedType,
     UnionType,
     UnpackType,
@@ -342,13 +343,11 @@ def visit_sequence_pattern(self, o: SequencePattern) -> PatternType:
             new_inner_type = UninhabitedType()
             for typ in new_inner_types:
                 new_inner_type = join_types(new_inner_type, typ)
-            new_type = self.construct_sequence_child(current_type, new_inner_type)
-            if is_subtype(new_type, current_type):
-                new_type, _ = self.chk.conditional_types_with_intersection(
-                    current_type, [get_type_range(new_type)], o, default=current_type
-                )
+            if isinstance(current_type, TypeVarType):
+                new_bound = self.narrow_sequence_child(current_type.upper_bound, new_inner_type, o)
+                new_type = current_type.copy_modified(upper_bound=new_bound)
             else:
-                new_type = current_type
+                new_type = self.narrow_sequence_child(current_type, new_inner_type, o)
         return PatternType(new_type, rest_type, captures)

     def get_sequence_type(self, t: Type, context: Context) -> Type | None:
@@ -447,6 +446,16 @@ def expand_starred_pattern_types(

         return new_types

+    def narrow_sequence_child(self, outer_type: Type, inner_type: Type, ctx: Context) -> Type:
+        new_type = self.construct_sequence_child(outer_type, inner_type)
+        if is_subtype(new_type, outer_type):
+            new_type, _ = self.chk.conditional_types_with_intersection(
+                outer_type, [get_type_range(new_type)], ctx, default=outer_type
+            )
+        else:
+            new_type = outer_type
+        return new_type
+
     def visit_starred_pattern(self, o: StarredPattern) -> PatternType:
         captures: dict[Expression, Type] = {}
         if o.capture is not None:

diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test
index 58b70d7b74d8..f6f4c9cf167f 100644
--- a/test-data/unit/check-python310.test
+++ b/test-data/unit/check-python310.test
@@ -2343,3 +2343,30 @@ def test(xs: Tuple[Unpack[Ts]]) -> None:
             reveal_type(b3)  # N: Revealed type is "builtins.list[builtins.object]"
             reveal_type(c3)  # N: Revealed type is "builtins.int"
 [builtins fixtures/tuple.pyi]
+
+[case testMatchSequencePatternTypeVarBoundNoCrash]
+# This was crashing: https://github.com/python/mypy/issues/18089
+from typing import TypeVar, Sequence, Any
+
+T = TypeVar("T", bound=Sequence[Any])
+
+def f(x: T) -> None:
+    match x:
+        case [_]:
+            pass
+[builtins fixtures/tuple.pyi]
+
+[case testMatchSequencePatternTypeVarBoundNarrows]
+from typing import TypeVar, Sequence
+
+T = TypeVar("T", bound=Sequence[int | str])
+
+def accept_seq_int(x: Sequence[int]): ...
+
+def f(x: T) -> None:
+    match x:
+        case [1, 2]:
+            accept_seq_int(x)
+        case _:
+            accept_seq_int(x)  # E: Argument 1 to "accept_seq_int" has incompatible type "T"; expected "Sequence[int]"
+[builtins fixtures/tuple.pyi]

Crash on sequence match statement in generic class with restricted type variable bound to sequence
<!--
  Use this form only if mypy reports an "INTERNAL ERROR" and/or gives a traceback.
  Please include the traceback and all other messages below (use `mypy --show-traceback`).
-->

**Crash Report**

mypy crashes when the following conditions are met:
1. A generic class is present.
2. The generic class refers to a typevar `T` that is bound to a sequence.
3. The generic class has a method that attempts to pattern match a method parameter of type `T`
4. One of the pattern matching cases is a sequence pattern such as `_, _`.

This crash is similar to but distinct from this issue: https://github.com/python/mypy/issues/12448

**Traceback**

```
$ mypy mypy_mre.py --show-traceback
mypy_mre.py:7: error: INTERNAL ERROR -- Please try using mypy master on GitHub:
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 1.14.0+dev.05a9e79068a5830e57264390c9f6bca859e92053
Traceback (most recent call last):
  File "~/venv-3.11.6/bin/mypy", line 8, in <module>
    sys.exit(console_entry())
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/__main__.py", line 15, in console_entry
    main()
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/main.py", line 109, in main
    res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/main.py", line 193, in run_build
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/build.py", line 194, in build
    result = _build(
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/build.py", line 269, in _build
    graph = dispatch(sources, manager, stdout)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/build.py", line 2937, in dispatch
    process_graph(graph, manager)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/build.py", line 3335, in process_graph
    process_stale_scc(graph, scc, manager)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/build.py", line 3436, in process_stale_scc
    graph[id].type_check_first_pass()
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/build.py", line 2306, in type_check_first_pass
    self.type_checker().check_first_pass()
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 483, in check_first_pass
    self.accept(d)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/nodes.py", line 1196, in accept
    return visitor.visit_class_def(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 2461, in visit_class_def
    self.accept(defn.defs)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/nodes.py", line 1277, in accept
    return visitor.visit_block(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 2951, in visit_block
    self.accept(s)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/nodes.py", line 827, in accept
    return visitor.visit_func_def(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 1046, in visit_func_def
    self._visit_func_def(defn)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 1050, in _visit_func_def
    self.check_func_item(defn, name=defn.name)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 1084, in check_func_item
    self.check_func_def(defn, typ, name, allow_empty)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 1360, in check_func_def
    self.accept(item.body)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/nodes.py", line 1277, in accept
    return visitor.visit_block(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 2951, in visit_block
    self.accept(s)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/nodes.py", line 1661, in accept
    return visitor.visit_match_stmt(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 5298, in visit_match_stmt
    pattern_types = [self.pattern_checker.accept(p, subject_type) for p in s.patterns]
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checker.py", line 5298, in <listcomp>
    pattern_types = [self.pattern_checker.accept(p, subject_type) for p in s.patterns]
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checkpattern.py", line 129, in accept
    result = o.accept(self)
             ^^^^^^^^^^^^^^
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/patterns.py", line 93, in accept
    return visitor.visit_sequence_pattern(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checkpattern.py", line 345, in visit_sequence_pattern
    new_type = self.construct_sequence_child(current_type, new_inner_type)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/venv-3.11.6/lib/python3.11/site-packages/mypy/checkpattern.py", line 766, in construct_sequence_child
    assert isinstance(proper_type, Instance)
AssertionError:
mypy_mre.py:7: : note: use --pdb to drop into pdb
```

**To Reproduce**

Here is an MRE:

```python
from typing import Generic, TypeVar, Sequence, Any

T = TypeVar("T", bound=Sequence[Any])

class C(Generic[T]):
    def f(self, x: T) -> None:
        match x:
            case _, _:
                pass
            case _:
                pass
```

**Your Environment**

<!-- Include as many relevant details about the environment you experienced the bug in -->

- Mypy version used: 1.14.0+dev.05a9e79068a5830e57264390c9f6bca859e92053 (current master)
- Mypy command-line flags: None
- Mypy configuration options from `mypy.ini` (and other config files):
```toml
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
extra_checks = true
no_implicit_reexport = true
python_version = "3.11"
strict_equality = true
warn_redundant_casts = true
warn_return_any = true
warn_unused_configs = true
warn_unused_ignores = true
  ```
- Python version used: 3.11.6
- Operating system and version: AlmaLinux 9.4 under WSL 2 on Windows 10

<!--
You can freely edit this text, please remove all the lines
you believe are unnecessary.
-->


diff --git a/mypy/checker.py b/mypy/checker.py
index 4b3d6c3298b4..f52bebdaa052 100644
--- a/mypy/checker.py
+++ b/mypy/checker.py
@@ -1072,46 +1072,7 @@ def _visit_func_def(self, defn: FuncDef) -> None:
         if defn.original_def:
             # Override previous definition.
             new_type = self.function_type(defn)
-            if isinstance(defn.original_def, FuncDef):
-                # Function definition overrides function definition.
-                old_type = self.function_type(defn.original_def)
-                if not is_same_type(new_type, old_type):
-                    self.msg.incompatible_conditional_function_def(defn, old_type, new_type)
-            else:
-                # Function definition overrides a variable initialized via assignment or a
-                # decorated function.
-                orig_type = defn.original_def.type
-                if orig_type is None:
-                    # If other branch is unreachable, we don't type check it and so we might
-                    # not have a type for the original definition
-                    return
-                if isinstance(orig_type, PartialType):
-                    if orig_type.type is None:
-                        # Ah this is a partial type. Give it the type of the function.
-                        orig_def = defn.original_def
-                        if isinstance(orig_def, Decorator):
-                            var = orig_def.var
-                        else:
-                            var = orig_def
-                        partial_types = self.find_partial_types(var)
-                        if partial_types is not None:
-                            var.type = new_type
-                            del partial_types[var]
-                    else:
-                        # Trying to redefine something like partial empty list as function.
-                        self.fail(message_registry.INCOMPATIBLE_REDEFINITION, defn)
-                else:
-                    name_expr = NameExpr(defn.name)
-                    name_expr.node = defn.original_def
-                    self.binder.assign_type(name_expr, new_type, orig_type)
-                    self.check_subtype(
-                        new_type,
-                        orig_type,
-                        defn,
-                        message_registry.INCOMPATIBLE_REDEFINITION,
-                        "redefinition with type",
-                        "original type",
-                    )
+            self.check_func_def_override(defn, new_type)

     def check_func_item(
         self,
@@ -1147,6 +1108,49 @@ def check_func_item(
             if dataclasses_plugin.is_processed_dataclass(defn.info):
                 dataclasses_plugin.check_post_init(self, defn, defn.info)

+    def check_func_def_override(self, defn: FuncDef, new_type: FunctionLike) -> None:
+        assert defn.original_def is not None
+        if isinstance(defn.original_def, FuncDef):
+            # Function definition overrides function definition.
+            old_type = self.function_type(defn.original_def)
+            if not is_same_type(new_type, old_type):
+                self.msg.incompatible_conditional_function_def(defn, old_type, new_type)
+        else:
+            # Function definition overrides a variable initialized via assignment or a
+            # decorated function.
+            orig_type = defn.original_def.type
+            if orig_type is None:
+                # If other branch is unreachable, we don't type check it and so we might
+                # not have a type for the original definition
+                return
+            if isinstance(orig_type, PartialType):
+                if orig_type.type is None:
+                    # Ah this is a partial type. Give it the type of the function.
+                    orig_def = defn.original_def
+                    if isinstance(orig_def, Decorator):
+                        var = orig_def.var
+                    else:
+                        var = orig_def
+                    partial_types = self.find_partial_types(var)
+                    if partial_types is not None:
+                        var.type = new_type
+                        del partial_types[var]
+                else:
+                    # Trying to redefine something like partial empty list as function.
+                    self.fail(message_registry.INCOMPATIBLE_REDEFINITION, defn)
+            else:
+                name_expr = NameExpr(defn.name)
+                name_expr.node = defn.original_def
+                self.binder.assign_type(name_expr, new_type, orig_type)
+                self.check_subtype(
+                    new_type,
+                    orig_type,
+                    defn,
+                    message_registry.INCOMPATIBLE_REDEFINITION,
+                    "redefinition with type",
+                    "original type",
+                )
+
     @contextmanager
     def enter_attribute_inference_context(self) -> Iterator[None]:
         old_types = self.inferred_attribute_types
@@ -5120,6 +5124,10 @@ def visit_decorator_inner(self, e: Decorator, allow_empty: bool = False) -> None
             if e.type and not isinstance(get_proper_type(e.type), (FunctionLike, AnyType)):
                 self.fail(message_registry.BAD_CONSTRUCTOR_TYPE, e)

+        if e.func.original_def and isinstance(sig, FunctionLike):
+            # Function definition overrides function definition.
+            self.check_func_def_override(e.func, sig)
+
     def check_for_untyped_decorator(
         self, func: FuncDef, dec_type: Type, dec_expr: Expression
     ) -> None:

diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test
index 96f9815019e6..b8a02a1ec7d4 100644
--- a/test-data/unit/check-functions.test
+++ b/test-data/unit/check-functions.test
@@ -1474,7 +1474,7 @@ def dec(f) -> Callable[[int], None]: pass

 x = int()
 if x:
-    def f(x: int) -> None: pass
+    def f(x: int, /) -> None: pass
 else:
     @dec
     def f(): pass
@@ -1489,9 +1489,12 @@ x = int()
 if x:
     def f(x: str) -> None: pass
 else:
-    # TODO: Complain about incompatible redefinition
     @dec
-    def f(): pass
+    def f(): pass   # E: All conditional function variants must have identical signatures \
+                    # N: Original: \
+                    # N:     def f(x: str) -> None \
+                    # N: Redefinition: \
+                    # N:     def f(int, /) -> None

 [case testConditionalFunctionDefinitionUnreachable]
 def bar() -> None:
@@ -1599,7 +1602,7 @@ else:
     def f():
         yield
 [file m.py]
-def f(): pass
+def f() -> None: pass

 [case testDefineConditionallyAsImportedAndDecoratedWithInference]
 if int():
diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test
index 511c7b003015..fe02ac3ccd5e 100644
--- a/test-data/unit/check-newsemanal.test
+++ b/test-data/unit/check-newsemanal.test
@@ -1908,9 +1908,9 @@ else:
     @dec
     def f(x: int) -> None:
         1()  # E: "int" not callable
-reveal_type(f) # N: Revealed type is "def (x: builtins.str)"
+reveal_type(f) # N: Revealed type is "def (builtins.str)"
 [file m.py]
-def f(x: str) -> None: pass
+def f(x: str, /) -> None: pass

 [case testNewAnalyzerConditionallyDefineFuncOverVar]
 from typing import Callable
diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test
index e414c1c9b0b6..9d01ce6bd480 100644
--- a/test-data/unit/check-overloading.test
+++ b/test-data/unit/check-overloading.test
@@ -6463,7 +6463,7 @@ class D: ...
 def f1(g: A) -> A: ...
 if True:
     @overload  # E: Single overload definition, multiple required
-    def f1(g: B) -> B: ...
+    def f1(g: B) -> B: ...  # E: Incompatible redefinition (redefinition with type "Callable[[B], B]", original type "Callable[[A], A]")
     if maybe_true:  # E: Condition can't be inferred, unable to merge overloads \
                     # E: Name "maybe_true" is not defined
         @overload
@@ -6480,14 +6480,14 @@ if True:
         def f2(g: B) -> B: ...
     elif maybe_true:  # E: Name "maybe_true" is not defined
         @overload  # E: Single overload definition, multiple required
-        def f2(g: C) -> C: ...
+        def f2(g: C) -> C: ...  # E: Incompatible redefinition (redefinition with type "Callable[[C], C]", original type "Callable[[A], A]")
 def f2(g): ...  # E: Name "f2" already defined on line 21

 @overload  # E: Single overload definition, multiple required
 def f3(g: A) -> A: ...
 if True:
     @overload  # E: Single overload definition, multiple required
-    def f3(g: B) -> B: ...
+    def f3(g: B) -> B: ...  # E: Incompatible redefinition (redefinition with type "Callable[[B], B]", original type "Callable[[A], A]")
     if True:
         pass  # Some other node
         @overload  # E: Name "f3" already defined on line 32 \

Conditional decorated functions are not type checked
**Bug Report**

Going through Mypy's tests, I realized that some tests are passing that shouldn't. This involves for example:

- `testConditionalFunctionDefinitionUsingDecorator3` (there's an error in the test that the test author probably didn't notice: Positional only args of a callable are never assignable to a normal function with positional-or-keyword params; typically an error in Mypy would look like this: `Incompatible redefinition (redefinition with type "Callable[[int], None]", original type "Callable[[Arg(int, 'x')], None]")`)
- `testConditionalFunctionDefinitionUsingDecorator4` (there's even a TODO in there that complains about this not being done)
- `testNewAnalyzerConditionalDecoratedFunc`

**To Reproduce**

```python
from typing import Callable
def dec(f) -> Callable[[int], None]: raise NotImplementedError

if int():
    def f(x: str): pass
else:
    @dec
    def f() -> None: pass
```

https://mypy-play.net/?mypy=latest&python=3.12&gist=18b131da809d740eced20dd7652ea213

**Expected Behavior**

It would be nice if Mypy complained here (like in AFAIK all other conditional definitions).

I'm happy to assist if somebody wants to fix this.


diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py
index b06aaa8f89f5..08d7345452fb 100644
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -399,8 +399,8 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type:
                 # TODO: always do this in type_object_type by passing the original context
                 result.ret_type.line = e.line
                 result.ret_type.column = e.column
-            if isinstance(get_proper_type(self.type_context[-1]), TypeType):
-                # This is the type in a Type[] expression, so substitute type
+            if is_type_type_context(self.type_context[-1]):
+                # This is the type in a type[] expression, so substitute type
                 # variables with Any.
                 result = erasetype.erase_typevars(result)
         elif isinstance(node, MypyFile):
@@ -6617,3 +6617,12 @@ def get_partial_instance_type(t: Type | None) -> PartialType | None:
     if t is None or not isinstance(t, PartialType) or t.type is None:
         return None
     return t
+
+
+def is_type_type_context(context: Type | None) -> bool:
+    context = get_proper_type(context)
+    if isinstance(context, TypeType):
+        return True
+    if isinstance(context, UnionType):
+        return any(is_type_type_context(item) for item in context.items)
+    return False

diff --git a/test-data/unit/check-typevar-defaults.test b/test-data/unit/check-typevar-defaults.test
index 9ca67376da26..22e2594eb38b 100644
--- a/test-data/unit/check-typevar-defaults.test
+++ b/test-data/unit/check-typevar-defaults.test
@@ -717,3 +717,15 @@ def func_d3(
     reveal_type(c)  # N: Revealed type is "__main__.B[__main__.A[builtins.dict[builtins.int, builtins.float]]]"
     reveal_type(d)  # N: Revealed type is "__main__.B[builtins.int]"
 [builtins fixtures/dict.pyi]
+
+[case testTypeVarDefaultsAndTypeObjectTypeInUnion]
+from __future__ import annotations
+from typing import Generic
+from typing_extensions import TypeVar
+
+_I = TypeVar("_I", default=int)
+
+class C(Generic[_I]): pass
+
+t: type[C] | int = C
+[builtins fixtures/tuple.pyi]

[1.12 regression] New error on type[memoryView] | type[str]
**Bug Report**

new to 1.12.0
incorrect error message on union of two type one being memoryview

Complete file checked:

"""
a_type: type[memoryview] | type[str] = memoryview
"""

mypy 1.11.2 no error

mypy 1.12.0
Incompatible default for argument "a_type" (default has type "type[memoryview[Any]]", argument has type "type[memoryview[int]] | type[str]")

**Your Environment**
github action ubuntu various , python various

- Mypy command-line flags:
-no flags
- Mypy configuration options from `mypy.ini` (and other config files):
- None
- Python version used: via github actions
3.8, 3.9, 3.10, 3.11, 3.12 and 3.13

while
"""
a_type: type[memoryview] = memoryview
""""
Works ok!


diff --git a/mypy/plugins/functools.py b/mypy/plugins/functools.py
index 6650af637519..f09ea88f7162 100644
--- a/mypy/plugins/functools.py
+++ b/mypy/plugins/functools.py
@@ -18,6 +18,7 @@
     Type,
     TypeOfAny,
     UnboundType,
+    UnionType,
     get_proper_type,
 )

@@ -130,7 +131,19 @@ def partial_new_callback(ctx: mypy.plugin.FunctionContext) -> Type:
     if isinstance(get_proper_type(ctx.arg_types[0][0]), Overloaded):
         # TODO: handle overloads, just fall back to whatever the non-plugin code does
         return ctx.default_return_type
-    fn_type = ctx.api.extract_callable_type(ctx.arg_types[0][0], ctx=ctx.default_return_type)
+    return handle_partial_with_callee(ctx, callee=ctx.arg_types[0][0])
+
+
+def handle_partial_with_callee(ctx: mypy.plugin.FunctionContext, callee: Type) -> Type:
+    if not isinstance(ctx.api, mypy.checker.TypeChecker):  # use internals
+        return ctx.default_return_type
+
+    if isinstance(callee_proper := get_proper_type(callee), UnionType):
+        return UnionType.make_union(
+            [handle_partial_with_callee(ctx, item) for item in callee_proper.items]
+        )
+
+    fn_type = ctx.api.extract_callable_type(callee, ctx=ctx.default_return_type)
     if fn_type is None:
         return ctx.default_return_type

diff --git a/test-data/unit/check-functools.test b/test-data/unit/check-functools.test
index 50de3789ebd2..bee30931a92b 100644
--- a/test-data/unit/check-functools.test
+++ b/test-data/unit/check-functools.test
@@ -346,15 +346,32 @@ fn1: Union[Callable[[int], int], Callable[[int], int]]
 reveal_type(functools.partial(fn1, 2)())  # N: Revealed type is "builtins.int"

 fn2: Union[Callable[[int], int], Callable[[int], str]]
-reveal_type(functools.partial(fn2, 2)())  # N: Revealed type is "builtins.object"
+reveal_type(functools.partial(fn2, 2)())  # N: Revealed type is "Union[builtins.int, builtins.str]"

 fn3: Union[Callable[[int], int], str]
 reveal_type(functools.partial(fn3, 2)())  # E: "str" not callable \
-                                          # E: "Union[Callable[[int], int], str]" not callable \
                                           # N: Revealed type is "builtins.int" \
                                           # E: Argument 1 to "partial" has incompatible type "Union[Callable[[int], int], str]"; expected "Callable[..., int]"
 [builtins fixtures/tuple.pyi]

+[case testFunctoolsPartialUnionOfTypeAndCallable]
+import functools
+from typing import Callable, Union, Type
+from typing_extensions import TypeAlias
+
+class FooBar:
+    def __init__(self, arg1: str) -> None:
+        pass
+
+def f1(t: Union[Type[FooBar], Callable[..., 'FooBar']]) -> None:
+    val = functools.partial(t)
+
+FooBarFunc: TypeAlias = Callable[..., 'FooBar']
+
+def f2(t: Union[Type[FooBar], FooBarFunc]) -> None:
+    val = functools.partial(t)
+[builtins fixtures/tuple.pyi]
+
 [case testFunctoolsPartialExplicitType]
 from functools import partial
 from typing import Type, TypeVar, Callable

Union between a callable and a type not respected by functools.partial
Seems similar to #17646 but not fixed in https://mypy-play.net/?mypy=master&python=3.12
The linked #17659 is not applicable because I am not using Self.

Sample code:
```python
import functools
import typing as T
from typing_extensions import TypeAlias

FooBarFunc: TypeAlias = T.Callable[..., 'FooBar']

class FooBar:
    def __init__(self, arg1: str) -> None:
        pass

def transform(t: T.Union[T.Type[FooBar], FooBarFunc]) -> None:
    val = functools.partial(t)
```

Error:
```
main.py:12: error: "type[FooBar] | Callable[..., FooBar]" not callable  [misc]
```

The codebase where this was discovered: https://github.com/mesonbuild/meson/blob/83f8de5357f31d6448ae033e1e8ed2b22c8c306a/mesonbuild/dependencies/factory.py#L75-L95

```
mesonbuild/dependencies/factory.py:95:38: error: "type[CMakeDependency] | Callable[..., CMakeDependency]" not callable  [misc]
```

Both sides of the union if cast and used independently, work.

This is sort of underlying behaviour in mypy that is exposed now that mypy checks functools.partial

E.g. on mypy 1.11 both of these will complain
```
def join(t1: T.Type[FooBar], t2: FooBarFunc):
    val1 = [t1, t2]
    val1[0]("asdf")

    val2 = t1 if random.random() < 0.5 else t2
    val2("asdf")
```

This could be fixed by improving the join logic (improving callable joins would fix many existing mypy issues) or potentially by changing the functools.partial logic to avoid using joins on unions (this could get messy)


diff --git a/mypy/errors.py b/mypy/errors.py
index 13452b14a237..1b3f485d19c0 100644
--- a/mypy/errors.py
+++ b/mypy/errors.py
@@ -922,9 +922,25 @@ def file_messages(self, path: str, formatter: ErrorFormatter | None = None) -> l
         self.flushed_files.add(path)
         source_lines = None
         if self.options.pretty and self.read_source:
-            source_lines = self.read_source(path)
+            # Find shadow file mapping and read source lines if a shadow file exists for the given path.
+            # If shadow file mapping is not found, read source lines
+            mapped_path = self.find_shadow_file_mapping(path)
+            if mapped_path:
+                source_lines = self.read_source(mapped_path)
+            else:
+                source_lines = self.read_source(path)
         return self.format_messages(error_tuples, source_lines)

+    def find_shadow_file_mapping(self, path: str) -> str | None:
+        """Return the shadow file path for a given source file path or None."""
+        if self.options.shadow_file is None:
+            return None
+
+        for i in self.options.shadow_file:
+            if i[0] == path:
+                return i[1]
+        return None
+
     def new_messages(self) -> list[str]:
         """Return a string list of new error messages.

diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test
index 2262b7e7280c..38ea83cdbcf4 100644
--- a/test-data/unit/cmdline.test
+++ b/test-data/unit/cmdline.test
@@ -914,6 +914,23 @@ s4.py:2: error: Incompatible return value type (got "int", expected "str")
 s3.py:2: error: Incompatible return value type (got "List[int]", expected "int")
 s1.py:2: error: Incompatible return value type (got "int", expected "str")

+[case testShadowFileWithPretty]
+# cmd: mypy a.py --pretty --shadow-file a.py b.py
+[file a.py]
+b: bytes
+[file b.py]
+a: int = ""
+b: bytes = 1
+[out]
+a.py:1: error: Incompatible types in assignment (expression has type "str",
+variable has type "int")
+    a: int = ""
+             ^~
+a.py:2: error: Incompatible types in assignment (expression has type "int",
+variable has type "bytes")
+    b: bytes = 1
+               ^
+
 [case testConfigWarnUnusedSection1]
 # cmd: mypy foo.py quux.py spam/eggs.py
 [file mypy.ini]

Crash in `--pretty` mode with `--shadow-file` which shadows a shorter file
**Crash Report**

`--pretty` inserts source file fragments from the file that's being reported. If `--shadow-file` uses a `SHADOW_FILE` which is longer than `SOURCE_FILE`, mypy crashes as it tries to access a line which doesn't exist.

**To Reproduce & Traceback**

`a.py`
```python
b: bytes  # Ensure there is at most 1 newline character in this file
```
`b.py`
```python
a: int = ""
b: bytes = 1
```
```shell
$ mypy a.py --pretty --shadow-file a.py b.py
Traceback (most recent call last):
  ...
  File "<virtual environment>\lib\site-packages\mypy\__main__.py", line 15, in console_entry
    main()
  File "mypy\main.py", line 103, in main
  File "mypy\main.py", line 187, in run_build
  File "mypy\build.py", line 193, in build
  File "mypy\build.py", line 268, in _build
  File "mypy\build.py", line 2950, in dispatch
  File "mypy\build.py", line 3348, in process_graph
  File "mypy\build.py", line 3471, in process_stale_scc
  File "mypy\errors.py", line 923, in file_messages
  File "mypy\errors.py", line 883, in format_messages
IndexError: list index out of range
```

https://github.com/python/mypy/blob/1a2c8e2a4df21532e4952191cad74ae50083f4ad/mypy/errors.py#L883

I think the solution is to insert source file fragments from `SHADOW_FILE` rather than `SOURCE_FILE`. Even if this doesn't crash, the resultant messages don't make sense. For example, inserting extra newlines into `a.py` prevents the crash but you get
```shell
a.py:1:10:1:11: error: Incompatible types in assignment (expression has type "str", variable has type "int")  [assignment]
    b: bytes
            ^
a.py:2:12:2:12: error: Incompatible types in assignment (expression has type "int", variable has type "bytes")  [assignment]

       ^
```

**Your Environment**

- Mypy version used: 1.11.2
- Mypy command-line flags: `--pretty --shadow-file`
- Mypy configuration options from `mypy.ini` (and other config files): None
- Python version used: 3.9
- Operating system and version: Windows 11 Home


diff --git a/mypy/typeops.py b/mypy/typeops.py
index 7f530d13d4e2..0699cda53cfa 100644
--- a/mypy/typeops.py
+++ b/mypy/typeops.py
@@ -14,6 +14,7 @@
 from mypy.expandtype import expand_type, expand_type_by_instance
 from mypy.maptype import map_instance_to_supertype
 from mypy.nodes import (
+    ARG_OPT,
     ARG_POS,
     ARG_STAR,
     ARG_STAR2,
@@ -305,9 +306,27 @@ class B(A): pass

     """
     if isinstance(method, Overloaded):
-        items = [
-            bind_self(c, original_type, is_classmethod, ignore_instances) for c in method.items
-        ]
+        items = []
+        original_type = get_proper_type(original_type)
+        for c in method.items:
+            if isinstance(original_type, Instance):
+                # Filter based on whether declared self type can match actual object type.
+                # For example, if self has type C[int] and method is accessed on a C[str] value,
+                # omit this item. This is best effort since bind_self can be called in many
+                # contexts, and doing complete validation might trigger infinite recursion.
+                #
+                # Note that overload item filtering normally happens elsewhere. This is needed
+                # at least during constraint inference.
+                keep = is_valid_self_type_best_effort(c, original_type)
+            else:
+                keep = True
+            if keep:
+                items.append(bind_self(c, original_type, is_classmethod, ignore_instances))
+        if len(items) == 0:
+            # If no item matches, returning all items helps avoid some spurious errors
+            items = [
+                bind_self(c, original_type, is_classmethod, ignore_instances) for c in method.items
+            ]
         return cast(F, Overloaded(items))
     assert isinstance(method, CallableType)
     func = method
@@ -379,6 +398,43 @@ class B(A): pass
     return cast(F, res)

+def is_valid_self_type_best_effort(c: CallableType, self_type: Instance) -> bool:
+    """Quickly check if self_type might match the self in a callable.
+
+    Avoid performing any complex type operations. This is performance-critical.
+
+    Default to returning True if we don't know (or it would be too expensive).
+    """
+    if (
+        self_type.args
+        and c.arg_types
+        and isinstance((arg_type := get_proper_type(c.arg_types[0])), Instance)
+        and c.arg_kinds[0] in (ARG_POS, ARG_OPT)
+        and arg_type.args
+        and self_type.type.fullname != "functools._SingleDispatchCallable"
+    ):
+        if self_type.type is not arg_type.type:
+            # We can't map to supertype, since it could trigger expensive checks for
+            # protocol types, so we consevatively assume this is fine.
+            return True
+
+        # Fast path: no explicit annotation on self
+        if all(
+            (
+                type(arg) is TypeVarType
+                and type(arg.upper_bound) is Instance
+                and arg.upper_bound.type.fullname == "builtins.object"
+            )
+            for arg in arg_type.args
+        ):
+            return True
+
+        from mypy.meet import is_overlapping_types
+
+        return is_overlapping_types(self_type, c.arg_types[0])
+    return True
+
+
 def erase_to_bound(t: Type) -> Type:
     # TODO: use value restrictions to produce a union?
     t = get_proper_type(t)

diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test
index 48d5996b226f..e414c1c9b0b6 100644
--- a/test-data/unit/check-overloading.test
+++ b/test-data/unit/check-overloading.test
@@ -6750,3 +6750,21 @@ def foo(x: object) -> str: ...
 def bar(x: int) -> int: ...
 @overload
 def bar(x: Any) -> str: ...
+
+[case testOverloadOnInvalidTypeArgument]
+from typing import TypeVar, Self, Generic, overload
+
+class C: pass
+
+T = TypeVar("T", bound=C)
+
+class D(Generic[T]):
+    @overload
+    def f(self, x: int) -> int: ...
+    @overload
+    def f(self, x: str) -> str: ...
+    def f(Self, x): ...
+
+a: D[str]  # E: Type argument "str" of "D" must be a subtype of "C"
+reveal_type(a.f(1))  # N: Revealed type is "builtins.int"
+reveal_type(a.f("x"))  # N: Revealed type is "builtins.str"
diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test
index ee7556461fd3..5ed2351e33e6 100644
--- a/test-data/unit/check-protocols.test
+++ b/test-data/unit/check-protocols.test
@@ -4127,3 +4127,91 @@ class P(Protocol):

 class C(P): ...
 C(0)  # OK
+
+[case testTypeVarValueConstraintAgainstGenericProtocol]
+from typing import TypeVar, Generic, Protocol, overload
+
+T_contra = TypeVar("T_contra", contravariant=True)
+AnyStr = TypeVar("AnyStr", str, bytes)
+
+class SupportsWrite(Protocol[T_contra]):
+    def write(self, s: T_contra, /) -> None: ...
+
+class Buffer: ...
+
+class IO(Generic[AnyStr]):
+    @overload
+    def write(self: IO[bytes], s: Buffer, /) -> None: ...
+    @overload
+    def write(self, s: AnyStr, /) -> None: ...
+    def write(self, s): ...
+
+def foo(fdst: SupportsWrite[AnyStr]) -> None: ...
+
+x: IO[str]
+foo(x)
+
+[case testTypeVarValueConstraintAgainstGenericProtocol2]
+from typing import Generic, Protocol, TypeVar, overload
+
+AnyStr = TypeVar("AnyStr", str, bytes)
+T_co = TypeVar("T_co", covariant=True)
+T_contra = TypeVar("T_contra", contravariant=True)
+
+class SupportsRead(Generic[T_co]):
+    def read(self) -> T_co: ...
+
+class SupportsWrite(Protocol[T_contra]):
+    def write(self, s: T_contra) -> object: ...
+
+def copyfileobj(fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr]) -> None: ...
+
+class WriteToMe(Generic[AnyStr]):
+    @overload
+    def write(self: WriteToMe[str], s: str) -> int: ...
+    @overload
+    def write(self: WriteToMe[bytes], s: bytes) -> int: ...
+    def write(self, s): ...
+
+class WriteToMeOrReadFromMe(WriteToMe[AnyStr], SupportsRead[AnyStr]): ...
+
+copyfileobj(WriteToMeOrReadFromMe[bytes](), WriteToMe[bytes]())
+
+[case testOverloadedMethodWithExplictSelfTypes]
+from typing import Generic, overload, Protocol, TypeVar, Union
+
+AnyStr = TypeVar("AnyStr", str, bytes)
+T_co = TypeVar("T_co", covariant=True)
+T_contra = TypeVar("T_contra", contravariant=True)
+
+class SupportsRead(Protocol[T_co]):
+    def read(self) -> T_co: ...
+
+class SupportsWrite(Protocol[T_contra]):
+    def write(self, s: T_contra) -> int: ...
+
+class Input(Generic[AnyStr]):
+    def read(self) -> AnyStr: ...
+
+class Output(Generic[AnyStr]):
+    @overload
+    def write(self: Output[str], s: str) -> int: ...
+    @overload
+    def write(self: Output[bytes], s: bytes) -> int: ...
+    def write(self, s: Union[str, bytes]) -> int: ...
+
+def f(src: SupportsRead[AnyStr], dst: SupportsWrite[AnyStr]) -> None: ...
+
+def g1(a: Input[bytes], b: Output[bytes]) -> None:
+    f(a, b)
+
+def g2(a: Input[bytes], b: Output[bytes]) -> None:
+    f(a, b)
+
+def g3(a: Input[str], b: Output[bytes]) -> None:
+    f(a, b)  # E: Cannot infer type argument 1 of "f"
+
+def g4(a: Input[bytes], b: Output[str]) -> None:
+    f(a, b)  # E: Cannot infer type argument 1 of "f"
+
+[builtins fixtures/tuple.pyi]

Regression: IO[str] not compatible with SupportsWrite[AnyStr]
This code generates a false positive, but type checked cleanly on mypy 1.11:
```py
from typing import IO
from shutil import copyfileobj

f: IO[str]
copyfileobj(f, f)  # Cannot infer type argument 1 of "copyfileobj"
```
I believe the reason is that the definition of `IO.write` changed in typeshed, and this triggered a mypy bug. Here's how `IO.write` is currently defined:
```py
class IO(Iterator[AnyStr]):
    ...
    @abstractmethod
    @overload
    def write(self: IO[bytes], s: ReadableBuffer, /) -> int: ...
    @abstractmethod
    @overload
    def write(self, s: AnyStr, /) -> int: ...
```