ty icon indicating copy to clipboard operation
ty copied to clipboard

Stricter handling of instance variables

Open hauntsaninja opened this issue 2 months ago • 3 comments

Question

class X:
    def __init__(self, foo: int) -> None:
        self.foo = foo

    def whatever(self) -> None:
        self.foo + 1

def main(mfoo: int | None) -> None:
    x = X(5)
    x.foo = mfoo
    w.whatever()

https://play.ty.dev/32c2417c-5f39-4170-9f72-81efca658ce3

I would like a way to run ty such that it complains about the above program.

All of mypy, pyright, pyrefly complain about this.

(In general, I think many users would consider this to be a fully typed program. If ty is going to have novel interpretations of gradual typing (yay! innovation!), it becomes really important to have documented configurations that users can set which ensures that they don't get bitten, and I don't see one for this)

This has to be a duplicate, but I couldn't find one — sorry about that!

Version

No response

hauntsaninja avatar Dec 24 '25 23:12 hauntsaninja

The type inlays in the LSP don't even show the Unknown, making this extra pernicious

hauntsaninja avatar Dec 24 '25 23:12 hauntsaninja

I guess this is maybe a duplicate of this comment? https://github.com/astral-sh/ty/issues/1240#issuecomment-3322174806

hauntsaninja avatar Dec 24 '25 23:12 hauntsaninja

I assume this is about the widening of foo. There has been some discussion about a strict-mode setting in https://github.com/astral-sh/ty/issues/527, which this relates to .

I'm sure Carl or Alex will give you a more detailed answer once they're back from their PTO.

MichaReiser avatar Dec 25 '25 17:12 MichaReiser

Thanks -- I agree that we should emit a diagnostic on this program. There's two ways that might happen: one is discussed in #1515, which is that we'd have a special case to consider an implicit instance attribute "annotated" if it is directly assigned from an annotated __init__ argument. That's sufficient for this example, but it's fairly narrow, and would be easy to construct slightly more complex examples where it would no longer apply -- and then that unexpected "cliff" would also become a foot-gun. The other is #1240, where we plan to add an option to turn off the gradual-guarantee unioning with Unknown entirely; and I think that should probably be the default, at least for CLI use.

I don't think the gradual guarantee is novel (it's the standard definition of gradual typing in the academic literature), but it is novel for Python type checkers. I think it was an interesting and worthwhile experiment, but my interpretation of the results of that experiment at this point is that it doesn't work well for users who want to write typed Python -- it requires too many verbose/redundant annotations in order to get a fully typed program.

carljm avatar Dec 26 '25 17:12 carljm