literals_interactions.py: do not mandate optional narrowing behaviour from type checkers#2209
literals_interactions.py: do not mandate optional narrowing behaviour from type checkers#2209
literals_interactions.py: do not mandate optional narrowing behaviour from type checkers#2209Conversation
…ur from type checkers
JelleZijlstra
left a comment
There was a problem hiding this comment.
For usability reasons I think it is more practical to narrow in these cases, but you are technically correct it is unsound.
|
Just wondering: Are you not going to narrow this and other cases? Because it feels like if you don't narrow here you can essentially not narrow in almost any |
That's correct, yeah — we currently do equality narrowing in much more limited circumstances than other type checkers do. You can see exactly what we support here: https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/narrow/conditionals/eq.md To be clear, we still might change this for reasons of pragmatism! But even if we did change our behaviour here, I still don't think the conformance tests should be mandating behavior that the spec explicitly says is optional. And while we have had several issues from users surprised about our current behaviour, I wouldn't say there's actually been that much dissatisfaction from users so far about this. Folks have generally agreed with the rationale once it's been explained — the main issue IMO is that the result is not what users initially expect a lot of the time. |
|
I think the most important thing here is just that the spec says this is optional, and does not generally prescribe narrowing behavior, so the conformance suite shouldn't be requiring it. |
X-ref #2208 (comment).
An example in this file mandates that type checkers should narrow an object
xof typestrtoLiteral["foo"]after anif x == "foo"check. This example appears to be testing adherence to the passage in the spec at https://typing.python.org/en/latest/spec/literal.html#interactions-with-narrowing. But the passage in the spec here clearly indicates that narrowingstrorLiteralStringtypes toLiteralstrings is optional:The narrowing examples given by the spec are also unsound; it's easy to create a
strsubclass (andstrsubclasses are common, due toStrEnumin the standard library) that has custom equality semantics and breaks the assumptions of narrowing like this:This PR keeps a version of the existing test (since it comes directly from the spec), but allows type checkers to optionally emit errors on certain lines if they do not implement the optional narrowing behaviour described by the spec. It also adds additional tests using
LiteralString, for which narrowing to aLiteralstring type via equality or containment is unambiguously sound.The effect of this PR is that mypy and ty now fully pass
literals_interactions.py. All other type checkers have their conformance score unchanged.