Repository navigation
ParamSpec substitution: difference in behaviour between collections.abc.Callable and typing.Callable #102723
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errorstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory3.12only security fixesonly security fixes
on Mar 15, 2023 I am going to research, how hard it is to change.
If this is a rather simple patch, I am going to apply it.
If this is a complex one, I will close this issue as "won't fix".Because parameters and their substitution is a very hard thing to get right.
Reacted by Alex WaygoodWait, I am confused again. Why
c.Callable[P, T][[P, str], bool]is allowed?It seems like
Pcan only be substituted with:- Some other
ParamSpecvariable:P->P2 ...- Arguments list without any
ParamSpecvariables:[int, str] ConcatenatewithParamSpec:Concatenate[int, P]
Am I missing something?
- Some other
You're correct,
c.Callable[P, T][[P, str], bool]should also, strictly speaking, not be allowed.Honestly, I think we should probably leave this one. The runtime allows all sorts of crazy things that should be rejected by type checkers. My personal favourite (we should make this an alias for
Any):>>> list[r"¯\_(ツ)_/¯"] list['¯\\_(ツ)_/¯']We've never promised that the runtime would disallow all things that should be rejected by type checkers, and I don't want us to start making that promise now.
The fact that
c.Callable[P, T][[P, str], bool][int]raises aTypeErroris, strictly speaking, correct -- but I think it's almost certainly just an accident of the current implementation rather than something that was designed. So we shouldn't spend time trying to change the behaviour (since the behaviour is not incorrect), but we also probably shouldn't spend time trying to maketyping.Callablematch it.#88965 seems like a much more important issue to me, since that involves the runtime incorrectly raising a
TypeErrorfor valid substitutions.Yes, I agree. We should close this as won't fix. Because the correct behaviour is very complex to achieve. And will probably break other things.
I am going to research, how hard it is to change.
There's no point to address a minor issue like this one by the cost of increasing code complexity.
Reacted by Alex WaygoodWould you be interested in taking a look at #88965? Serhiy assigned it to himself several months ago, but there's been no activity on the issue since, and it would be great to have it fixed.
I will tomorrow!
Reacted by Alex Waygood
There is currently a difference in behaviour between
collections.abc.Callableandtyping.Callablefor the following edge case involvingParamSpecsubstitution:According to PEP-612, this is an invalid substitution, for two reasons:
ParamSpecin a parameters list usingtyping(_extensions).Concatenate.ParamSpecin a parameters list is disallowed.As such, the behaviour of
collections.abc.Callableis more correct here, so ideally we'd change the behaviour oftyping.Callableto matchcollections.abc.Callable.However, this error should hopefully be caught by static type checkers anyway, and this is a false negative rather than a false positive. The runtime makes no promises that it will raise
TypeErroron all invalid substitutions, so fixing this should be low priority, in my opinion. We should first concentrate on fixing substitutions where the runtime raises exceptions, even though it shouldn't. For example:This discrepancy in behaviour was first uncovered as part of a broader discussion in:
Cc. @sobolevn