-
Notifications
You must be signed in to change notification settings - Fork 258
Type erasure and related issues #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
We (me, Mark Shannon and Andrey Vlasovskikh) discussed this yesterday and the consensus was that |
Given the expense of creating a new class, it might be worth caching these things in the |
I like that idea. Maybe I won't get to implementing it before beta 1 though. |
I have another issue with supporting Example:
My argument against storing the type argument in instances is primarily based on two issues:
These are more minor issues:
|
OK, unless there are further objections, let's disallow instantiating parametrized types. |
How about we make We could even go back and make |
That could be nice -- that's how mypy used to work, and it was somewhat helpful. These are the tradeoffs as I see them:
|
I wonder if the real utility of |
This needs text in the PEP describing what we decided to do. I think it's this (which is already implemented in typing.py):
|
FWIW I also need to fix this in typing.py -- currently |
This addresses issue #79, but does not fix it (typing.py needs to be updated to implement type erasure).
I found the section in the PEP (added in c29a9b9) unclear to read as someone not very familiar with type systems (coming from C and Python). Two things are confusing to me:
After reading it a few times, here is what I think it means:
Is this correct? Maybe the text could be clarified a bit, though I'm not sure how exactly. |
That's good feedback. I'll clarify it. |
Done in rev b5e4e3d. |
I'm reopening this. The PEP (https://www.python.org/dev/peps/pep-0484/#instantiating-generic-classes-and-type-erasure) explicitly allows
The discussion in this issue was somewhat hurried and went back and forth a few times. What should we do? Fix mypy or change the PEP? |
I do not see why class Box(Generic[T]):
def __init__(self, value: T) -> None:
self.value = value If I want to be able to find type errors at instantiation, then I have two options: x = Box[int]('a string') # OOPS! or alternatively x = Box('a string') # type: Box[int] The second option looks a bit ugly to me. It would be even more ugly if I want to type annotate something like if Box('a string') in box_list: # type: Box[int]
... Although there might be no serious reason to recommend the first option, I do not see any reason to prohibit it. |
The main reason to prohibit Why is it so slow? Because each time you call However you can still create a type alias for
|
Type alias is a nice compromise here. I would even say that using type aliases could improve readability in this case. Finally, the facts that this already works in mypy and it is fast mean that this is a good option that we could recommend. |
Maybe you could update mypy's error message to hint at that?
|
Explicitly making a type alias such as |
The alias solution already works -- mypy understands it and the runtime
implementation does erase the type variable.
The question is purely about whether the PEP should disallow `Box[int]()`
or whether mypy should start allowing it (at runtime it also works, but is
really slow).
I think that the best solution really is to disallow `Box[int]()` in the
PEP (but continue to support it via type aliases) since the `Box[int]` part
of the expression is just always going to be expensive (even if we could
speed it up a bunch with caching).
If you agree, I'll update the PEP and maybe you can update mypy to also
suggest an alias in the error message.
|
Sorry, I was quite busy today, @gvanrossum I agree with everything what you said, I propose to change the error message to the following one "Generic type is prohibited as a runtime expression (use a type alias or '# type:' comment)". I have made a PR at mypy python/mypy#1326 |
This entire section in the PEP is questionable (showing how little I understood when I wrote it):
I would like to rewrite all of this it to clarify:
|
(Also added to the peps repo, as rev 1ad9e828ca36.) |
We said it shouldn't be possible to instantiate
List
orList[t]
(i.e.,List()
orList[t]()
), but the implementation allows this (wheret
can be a type variable or a concrete class). This should be disallowed (and made sure it's documented in the PEP).However, for user-defined generic classes it should definitely be possible to write node
Node()
and probably alsoNode[t]()
. We must decide whether the latter is allowed, and if so whether the object it returns hasNode
orNode[t]
as its__class__
.Also note that if the
Node
class is declared generic in a stub file, all uses ofNode[t]
must appear in string quotes (i.e. as forward references) since in this case the runtimeNode
class is not parametrized. (See #60.)Mark Shannon has proposed an intermediate option, using a class decorator like
@implements(Generic[T])
, which would make the fact thatNode
is parametrized knowable at runtime but without definingisinstance()
,issubclass()
orNode[t]
. This would be a third way to do it, not replacing stubs or inheriting fromGeneric[T]
. It could possibly also save space (since in CPython class objects such as created byNode[t]
use a lot of memory).The text was updated successfully, but these errors were encountered: