Support typing.NoReturn and typing.Never#14559
Conversation
|
AlexWaygood
left a comment
There was a problem hiding this comment.
Thanks! Not a full review yet, but one important thing I noticed:
carljm
left a comment
There was a problem hiding this comment.
Also not a full review yet, just a couple things I noticed in passing.
| # revealed: NoReturn | ||
| reveal_type(stop()) |
There was a problem hiding this comment.
I think this should be a separate test that ends here. If you were to actually run this code, the program would never return from the stop() call.
Everything after this line can be considered unreachable code from the perspective of static analysis. Which also means we might not (should not) emit any diagnostics, including reveal_type-information. I guess it's even questionable as to whether or not the reveal_type in this line should emit a diagnostic. You would not see any result at runtime. Existing type checkers still reveal the type for the stop() call, but nothing beyond.
Similar reasoning applies to some of the tests below, I think.
There was a problem hiding this comment.
My intention was to test the revealed type only. You're right this test will break when the behavior for Never is added.
I will move this call and other reveal_types that can stop the type checking to a function.
I think this should be a separate test that ends here.
Are you suggesting to implement this behavior in this PR? Otherwise I can add a todo comment here and work on it in a follow up PR.
There was a problem hiding this comment.
Are you suggesting to implement this behavior in this PR?
Ah, no — sorry. I was merely suggesting that we split this large test into multiple smaller tests. And take care not to have any test assertions (# revealed: / # error: ) in lines following a call to a function that returns Never/NoReturn. To make sure this test will work in the future once we add unreachable-code analysis.
Writing smaller self-consistent tests would also be beneficial if we ever need to debug an assertion failure in this file.
This is correct to skip in this PR; there shouldn't be any special-casing of such a check, it will just fall out naturally from checking return type assignability in general, since nothing (except for |
57c7764 to
f8debee
Compare
59d08ba to
7102da0
Compare
carljm
left a comment
There was a problem hiding this comment.
Looks great, thank you! Just a few small tweaks which I'll push, and then merge.
| `NoReturn` to annotate functions that never return normally. `Never` represents the bottom type, a | ||
| type that represents the empty set of Python objects. These two annotations can be used | ||
| interchangeably. |
There was a problem hiding this comment.
| `NoReturn` to annotate functions that never return normally. `Never` represents the bottom type, a | |
| type that represents the empty set of Python objects. These two annotations can be used | |
| interchangeably. | |
| `NoReturn` is used to annotate functions that never return (they always raise an exception or exit the process). | |
| `Never` is the bottom type, and represents the empty set of Python objects. These two annotations can be used | |
| interchangeably. |
| }, | ||
| ) | ||
| } | ||
| (Type::Never, Type::Never) => false, |
There was a problem hiding this comment.
I think this case is a) wrong (because Never should be assignable to Never) and b) never reached, due to the is_equivalent_to check that takes precedence above.
There is a test verifying that Never is actually assignable to Never.
| (Type::Never, Type::Never) => false, |
| ) | ||
| } | ||
| (Type::Never, Type::Never) => false, | ||
| (_, Type::Never) => false, |
There was a problem hiding this comment.
And I think this case should also not be necessary, because we fallback to is_subtype_of, which already contains this same case for Never. Removing this line and the previous one, all tests still pass.
| (_, Type::Never) => false, |
Co-authored-by: Alex Waygood <[email protected]>
1de7286 to
a217be4
Compare
Fix #14558
Summary
typing.NoReturnandtyping.Neverto known instances and infer them asType::Neveris_assignable_tocases forType::NeverI skipped emitting diagnostic for when a function is annotated as
NoReturnbut it actually returns.Test Plan
Added tests from
https://github.com/python/typing/blob/main/conformance/tests/specialtypes_never.py
except from generics and checking if the return value of the function and the annotations match.