conformance: allow consistent treatment of kwargs: Unpack[TD]#2272
conformance: allow consistent treatment of kwargs: Unpack[TD]#2272carljm wants to merge 1 commit intopython:mainfrom
Conversation
I'm looking at what (I think) is the corresponding section of the conformance suite, and the function has an extra parameter corresponding to the extra key in TD2: If you delete the With that said, I'd be fine with modifying the conformance test to also allow a consistent |
davidhalter
left a comment
There was a problem hiding this comment.
We can have a discussion about which of these interpretations should be preferred, but given the lack of clarity about this in the spec, I think for now a conformant implementation should be allowed to choose either interpretation and implement it consistently.
I agree, though I personally prefer the version where this errors even if - from a theoretical perspective - this should pass. The reason for this is that most people are probably using Unpack[TypedDict] to reuse some kwargs and for that it will catch annoying errors, because people are going to forget that they should have used extra_items=Never or closed=True.
I would just want to avoid making type checkers non-conformant for being more "strict" here.
|
@rchen152 Sorry I wasn't clearer -- I wasn't saying that the conformance suite contains that example, just that pyright and pyrefly do allow it. What the conformance suite does contain is the requirement (added in #1918) that a callable that doesn't accept Relatedly, I think that the spec now has a lot of complex cases and language around assignability of callables using @davidhalter Yes, I think that's defensible. I think that a type-checker which consistently implemented that approach should not allow the Thanks both for the reviews! |
rchen152
left a comment
There was a problem hiding this comment.
Ah, got it. Thanks for the clarification!
JelleZijlstra
left a comment
There was a problem hiding this comment.
I think this is a step in the right direction. In the long term I feel we should consistently treat open TypedDicts as if they can have arbitrary extra keys (because they can), which means the call at issue here should be allowed by type checkers.
But I think it's OK to wait with that until PEP 728 is more widely used and supported.
Closed TypedDicts are arguably more intuitive and better behaved in many ways; perhaps they should have been the default. It's too late for that though.
The conformance suite currently asserts this (simplified for clarity):
This implies that the signature of
fde-sugars tof(*, v1: int). But the current conformance suite simultaneously also requires that callable assignability behave as if it de-sugars tof(*, v1: int, **kwargs: object). That addition to the conformance suite was justified by this call, which is allowed by pyright and pyrefly:It seems reasonable to allow this call, because TD2 is a subtype of TD1 and assignable to it, so
**td2should therefore be acceptable for**kwargs: Unpack[TD1]. But if this call (which definitely provides a keyword argumentv2) is allowed, then we should also allow the above call that explicitly providesv2.I think we could defensibly pick either of the interpretations of the signature of
f(with or without**kwargs: object), but type checkers should be allowed to pick a consistent interpretation, not be required to implement an inconsistent hybrid behavior.The interpretation with
**kwargs: objectis IMO more consistent and better supported by the spec. The spec says that ifTDhasextra_items, then arbitrary additional keyword arguments of that type should be accepted. And it also says that aTypedDictwithout an explicitclosedorextra_itemsparameter usually behaves as if it hasextra_itemsof typeReadOnly[object].The interpretation without
**kwargs: objectwould effectively be saying that**kwargs: Unpack[TD]is one of these special cases (along withTypedDictconstructor calls) where an unmarked TypedDict is (inconsistent with its "open" semantics) not treated as havingextra_itemsof typeReadOnly[object].We can have a discussion about which of these interpretations should be preferred, but given the lack of clarity about this in the spec, I think for now a conformant implementation should be allowed to choose either interpretation and implement it consistently.