Skip to content

Commit

Permalink
Add a test / TODO for a bug in __init__
Browse files Browse the repository at this point in the history
Summary:
I noticed this in the middle of a refactor, and it's not convenient
to fix until I finish the refactor, but recording a test case.

The correct semantics here aren't 100% clear, but you can see the
runtime behavior [here]( https://codapi.org/embed/?sandbox=python&code=data%3A%3Bbase64%2CSyvKz1UoqSzIzEtXyMwtyC8qUQipLEhNcclMLtFR8MsvCUotLM0sSk3h4krOSSwuVnDRgMtrWnEpgECFlUJmXgmEXQlmK9gqmEL4VVbIhkRn5pXEcnFxFRRl5pVouGhoagIA), the constructor
call allows anything, which means that
 - we almost certainly should allow `z` to be missing
 - we probably should also complain about `y` missing, the generated
   `__init__` does *not* use the default value. I think this bug
	 is caused by incorrect sharing of code between dataclass and typed dict
	 logic, where we shared the code because the operations look the same in
	 the Rust type system, but the actual Python semantics are divergent.

I found this working on a refactor to hide internals of `ClassField`, which
has the side effect of encouraging TypedDict and dataclass to actually own
thier own behavior instead of farming out logic to an overly abstract helper
method, which will naturally make it easy to fix this on top of my refactor.

Reviewed By: ndmitchell

Differential Revision: D70057864

fbshipit-source-id: 52b2aef295b5ee2b3f7b903e04ee32fe51bc2d50
  • Loading branch information
stroxler authored and facebook-github-bot committed Feb 23, 2025
1 parent 940de93 commit 5c9ddfe
Showing 1 changed file with 14 additions and 0 deletions.
14 changes: 14 additions & 0 deletions pyre2/pyre2/lib/test/typed_dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

use crate::testcase;
use crate::testcase_with_bug;

testcase!(
test_typed_dict,
Expand Down Expand Up @@ -344,3 +345,16 @@ def foo(x: Coord, **kwargs: Unpack[Coord]):
assert_type(kwargs, Coord)
"#,
);

testcase_with_bug!(
"TODO(stroxler) We should correctly account for requireness of a field in requiredness of `__init__` args",
test_requireness_in_init,
r#"
from typing import TypedDict, NotRequired
class D(TypedDict):
x: int
y: int = 5 # E: TypedDict item `y` may not be initialized.
z: NotRequired[int]
D(x=5) # E: Missing argument `z`
"#,
);

0 comments on commit 5c9ddfe

Please sign in to comment.