-
Notifications
You must be signed in to change notification settings - Fork 142
Description
This issue is here to collect ideas, how mutmut could use type hints to prevent mutants that a type checker would catch.
For instance:
def foo():
x: int = 1
# should not be mutated to
def foo():
x: int = None1. Using type hints while generating mutants
For simple cases like above, we could check the variable type hint, and if it's a basic type like str, int, ... then only allow these types. For more complex cases, I think we would need to use some type checker with an API and use it to understand which mutations are valid or not. I think this would get complex quickly and also the type checker we use would need to be compatible with the type checker of the user (as types are not 100% standardized).
2. Generating mutants, then filtering out with type checker
I wonder if for (2), we could simply run a type checker and ignore mutants where the mutated method has a type error:
- Generate mutants
- Run type checker
- Go through all lines with a type error
- If the line is a mutated method, disable this mutant
- For all remaining mutations, run pytest
The question I have here, is if we can ensure that mutations will only cause type errors in their own function. Could be possible, but not 100% sure.
At least our current implementation breaks it with pyright (see https://github.com/microsoft/pyright/blob/main/docs/type-inference.md#multi-assignment-type-inference):
class Foo:
def xǁFoo_foo__mutmut_orig(self):
self.x = 'foo'
def xǁFoo_foo__mutmut_1(self):
self.x = None # mutated codeOriginally, Foo().x is inferred to be of type str. With the mutated method in the same class, pyright will infer Foo().x to be the union str | None. This wlil break users of instance variables.
I think approach (2) is worth a try. If someone wants to work on it, let me know and I can give some pointers. Maybe I'll also start it when I have some free time :)