mypy icon indicating copy to clipboard operation
mypy copied to clipboard

When a type error results from type information being lost because an object (context manager) is used with `with` (with-as block), mypy should emit a hint alluding to this.

Open wyattscarpenter opened this issue 1 year ago • 2 comments

Feature

When a type error results from type information being lost because an object (context manager) is used with with (with-as block), mypy should emit a hint alluding to this.

Pitch

Consider the following issue, which is not by me but is a predicament I also ran into recently:

https://github.com/python/mypy/issues/9750

The user is, essentially, confused why the type of x.y is int but the type of c.y in with x as c: c.y is Any.

This happens because the __enter__ method of x is missing a return type signature, so mypy treats its output as having type Any. However, it is a common (as fair as I can tell) pattern for an object's __enter__ method to simply return self — possibly without a proper type signature, thus wiping its type information in the process. So, I think this would be a useful hint for mypy to emit, if it encounters any type problems where the problematic value has just resulted from a with statement.

Something like: hint: the type of c.y is Any, but the type of x is Foo. Did you mean the type of c to be Foo? If so, add the return type annotation -> Self to the __enter__ method of Foo.

Currently, there is no warning about this whatsoever, which means in the (admittedly, rare) circumstances where this problem crops up, it is unintuitive and the user has very little to go off of.

wyattscarpenter avatar Apr 02 '24 07:04 wyattscarpenter

+1 I've just run into this issue as well. Interestingly, Pylance (used by my VS Code) infers the expected type on its own, i.e. without any annotation needed on the __enter__ method. At minimum for the case of with Renderer() as renderer: ... (with Renderer.__enter__ implemented as return self). Wondering if mypy couldn't do the same...

pbodnar avatar Aug 19 '24 20:08 pbodnar

Presumably the difference between mypy and pyright here is a result of the general difference in unannotated inference strategies described in, eg, https://github.com/microsoft/pyright/blob/main/docs/mypy-comparison.md#inferred-return-types :

If a function or method lacks a return type annotation, pyright infers the return type from return and yield statements within the function’s body (including the implied return None at the end of the function body). This is important for supporting completion suggestions. It also improves type checking coverage and eliminates the need for developers to needlessly supply return type annotations for trivial return types.

By comparison, mypy never infers return types and assumes that functions without a return type annotation have a return type of Any. This was an intentional design decision by mypy developers and is explained in this thread.

Edit: that issue, #10149, would also obsolete this issue if fulfilled, presumably.

wyattscarpenter avatar Aug 20 '24 06:08 wyattscarpenter