-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fix handling of type variables to prevent confusion across different functions/classes #1261
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
Renamed Refactoring -> Fix in the title as this is will change behavior. |
Should we move this to an earlier milestone? (I'll add more details soon.) |
Yeah, I think this one is important and should be given priority. Maybe we should just move it into 0.3.2 and move anything that's a cleanup or refactoring out of there and into 0.3.3? |
Sounds good to me. |
Using distinct ids for unrelated type variables would certainly lead to less confusion (both for the human and mypy). Though there are still subtleties: if One thing to watch out for is nondeterminism of generated ids. Even if ids are just allocated as sequential integers, it's easy in practice for the results to be affected by minor details, such as the order of type checking modules, This might be exposed to the user in two ways:
|
Reid: if you get to this, great. If not, we can push it to a later milestone. |
I took a stab at this but encountered a number of minor bugs that are masked by the way that mypy currently reuses type variable ids, so I'm going to move this to the next milestone. For my records, here are the issues I encountered (maybe some deserve their own issues in the tracker):
|
One of the unit tests (testOverrideGenericMethodInNonGenericClass, excerpted below) raised an interesting point:
When my branch didn't report an error on the last line, I thought at first it was a bug, but on reflection I decided that it was right and the test is wrong. After all, any time A correct test would be
Generating good error messages in this kind of situation is tricky, because each individual argument is compatible with the argument type of the supertype's method; they just aren't compatible taken together. |
This is needed for subtyping of generic function with type variables with values to work correctly, which will be needed for python#1261.
This is needed for subtyping of generic function with type variables with values to work correctly, which will be needed for #1261.
On the three preliminary issues from two comments above: The first is fixed by #1469. The third is more complicated than I originally thought, and I filed #1515 for it. I plan to just add |
Do we have some kind of process in place to find out when those `# type:
ignore` comments in stdlib-samples are no longer needed?
|
I've occasionally went through stdlib-samples but not consistently. Having a warning for an unneeded |
There's #1345 for that |
This is a prerequisite for fixing python#1261 because overrides with generic function type variables currently work by accident: the type variables have the same ids in the original method and the overriding method, so is_subtype on the argument type returns True. This also allows an overriding method to generalize a specific type in the original method to a type variable, as demonstrated in one of the tests (testOverrideGenericMethodInNonGenericClassGeneralize). is_subtype already determines correctly whether the override is valid, so all the hard work here is in providing a more specific error message when possible.
This is a prerequisite for fixing #1261 because overrides with generic function type variables currently work by accident: the type variables have the same ids in the original method and the overriding method, so is_subtype on the argument type returns True. This also allows an overriding method to generalize a specific type in the original method to a type variable, as demonstrated in one of the tests (testOverrideGenericMethodInNonGenericClassGeneralize). is_subtype already determines correctly whether the override is valid, so all the hard work here is in providing a more specific error message when possible.
This will be needed for python#1261, which will make type variable ids unpredictable.
This is a prerequisite for fixing #1261 because overrides with generic function type variables currently work by accident: the type variables have the same ids in the original method and the overriding method, so is_subtype on the argument type returns True. This also allows an overriding method to generalize a specific type in the original method to a type variable, as demonstrated in one of the tests (testOverrideGenericMethodInNonGenericClassGeneralize). is_subtype already determines correctly whether the override is valid, so all the hard work here is in providing a more specific error message when possible.
This will be needed for python#1261, which will make type variable ids unpredictable.
This commit series gives type variable ids their own type and replaces the class/function type variable distinction with a plain/metavariable distinction. The main goal is to fix #603, but it's also progress towards #1261 and other bugs involving type variable inference. Metavariables (or unification variables) are variables introduced during type inference to represent the types that will be substituted for generic class or function type parameters. They only exist during type inference and should never escape into the inferred type of identifiers. Fixes #603.
I partially did this in #1580: that commit generates fresh IDs for unification variables during type inference, which live in their own type variable ID "namespace". Type variables of generic classes and functions are still allocated using the same old scheme (positive for classes, negative for functions). This fixed the known issues that are a direct result of type variable ID confusion. I still think allocating unique IDs for all type variables is probably a good idea that may be helpful for some type inference engine improvements in the future. However, there's actually a fair amount of work involved in doing this correctly and so far there hasn't been a concrete reason to do it, so I've put this off. The major points that would need to be addressed when implementing this are:
|
(Adding the Incremental label to flag this as of potential interest -- however I don't think there's an incremental action item unless we decide to proceed with the full fix here.) |
Removing the Incremental label, I don't think it's relevant. |
Greg's original post just says that this causes "a number of bugs", but there are no specifics and I don't recall any from the five years since this issue was last touched. Closing as obsolete. |
Currently type variables are identified by two namespaces "function" and "class" and a small numeric index, with the numbering starting from 1 in each new function and class. Which function or which class a given type variable refers to is implicit in where the type variable comes from in a given section of code in the type-checker. This leads to a number of bugs (TODO: link some of them here.)
@JukkaL suggests instead identifying each type variable by a fresh ID number distinct from all others, which is common practice in other type-inference engines.
The text was updated successfully, but these errors were encountered: