Skip to content

Commit

Permalink
Enable new type inference by default (#16345)
Browse files Browse the repository at this point in the history
Fixes #15906

I am adding `--old-type-inference` so people can disable the flag if
they have issues (for few releases). IIRC there will be some fallback in
`mypy_primer`, but last time I checked it was all correct. Also I don't
remember if we need to update some tests, but we will see.
  • Loading branch information
ilevkivskyi authored Oct 28, 2023
1 parent 9011ca8 commit 93d4cb0
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 14 deletions.
6 changes: 3 additions & 3 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -4043,11 +4043,11 @@ def is_valid_defaultdict_partial_value_type(self, t: ProperType) -> bool:
return True
if len(t.args) == 1:
arg = get_proper_type(t.args[0])
if self.options.new_type_inference:
allowed = isinstance(arg, (UninhabitedType, NoneType))
else:
if self.options.old_type_inference:
# Allow leaked TypeVars for legacy inference logic.
allowed = isinstance(arg, (UninhabitedType, NoneType, TypeVarType))
else:
allowed = isinstance(arg, (UninhabitedType, NoneType))
if allowed:
return True
return False
Expand Down
12 changes: 8 additions & 4 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ def __init__(
# on whether current expression is a callee, to give better error messages
# related to type context.
self.is_callee = False
type_state.infer_polymorphic = self.chk.options.new_type_inference
type_state.infer_polymorphic = not self.chk.options.old_type_inference

def reset(self) -> None:
self.resolved_type = {}
Expand Down Expand Up @@ -2082,7 +2082,7 @@ def infer_function_type_arguments(
elif not first_arg or not is_subtype(self.named_type("builtins.str"), first_arg):
self.chk.fail(message_registry.KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE, context)

if self.chk.options.new_type_inference and any(
if not self.chk.options.old_type_inference and any(
a is None
or isinstance(get_proper_type(a), UninhabitedType)
or set(get_type_vars(a)) & set(callee_type.variables)
Expand Down Expand Up @@ -2181,7 +2181,11 @@ def infer_function_type_arguments_pass2(
lambda a: self.accept(args[a]),
)

arg_types = self.infer_arg_types_in_context(callee_type, args, arg_kinds, formal_to_actual)
# Same as during first pass, disable type errors (we still have partial context).
with self.msg.filter_errors():
arg_types = self.infer_arg_types_in_context(
callee_type, args, arg_kinds, formal_to_actual
)

inferred_args, _ = infer_function_type_arguments(
callee_type,
Expand Down Expand Up @@ -5230,7 +5234,7 @@ def infer_lambda_type_using_context(
# they must be considered as indeterminate. We use ErasedType since it
# does not affect type inference results (it is for purposes like this
# only).
if self.chk.options.new_type_inference:
if not self.chk.options.old_type_inference:
# With new type inference we can preserve argument types even if they
# are generic, since new inference algorithm can handle constraints
# like S <: T (we still erase return type since it's ultimately unknown).
Expand Down
14 changes: 12 additions & 2 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,9 +995,13 @@ def add_invertible_flag(
help="Use a custom typing module",
)
internals_group.add_argument(
"--new-type-inference",
"--old-type-inference",
action="store_true",
help="Enable new experimental type inference algorithm",
help="Disable new experimental type inference algorithm",
)
# Deprecated reverse variant of the above.
internals_group.add_argument(
"--new-type-inference", action="store_true", help=argparse.SUPPRESS
)
parser.add_argument(
"--enable-incomplete-feature",
Expand Down Expand Up @@ -1383,6 +1387,12 @@ def set_strict_flags() -> None:
if options.logical_deps:
options.cache_fine_grained = True

if options.new_type_inference:
print(
"Warning: --new-type-inference flag is deprecated;"
" new type inference algorithm is already enabled by default"
)

if options.strict_concatenate and not strict_option_set:
print("Warning: --strict-concatenate is deprecated; use --extra-checks instead")

Expand Down
6 changes: 4 additions & 2 deletions mypy/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class BuildType:
| {
"platform",
"bazel",
"new_type_inference",
"old_type_inference",
"plugins",
"disable_bytearray_promotion",
"disable_memoryview_promotion",
Expand Down Expand Up @@ -360,7 +360,9 @@ def __init__(self) -> None:
# skip most errors after this many messages have been reported.
# -1 means unlimited.
self.many_errors_threshold = defaults.MANY_ERRORS_THRESHOLD
# Enable new experimental type inference algorithm.
# Disable new experimental type inference algorithm.
self.old_type_inference = False
# Deprecated reverse version of the above, do not use.
self.new_type_inference = False
# Export line-level, limited, fine-grained dependency information in cache data
# (undocumented feature).
Expand Down
1 change: 0 additions & 1 deletion mypy_self_check.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ always_false = MYPYC
plugins = mypy.plugins.proper_plugin
python_version = 3.8
exclude = mypy/typeshed/|mypyc/test-data/|mypyc/lib-rt/
new_type_inference = True
enable_error_code = ignore-without-code,redundant-expr
enable_incomplete_feature = PreciseTupleTypes
show_error_code_links = True
Expand Down
9 changes: 7 additions & 2 deletions test-data/unit/check-generics.test
Original file line number Diff line number Diff line change
Expand Up @@ -2724,7 +2724,7 @@ def f(x: Callable[[G[T]], int]) -> T: ...
class G(Generic[T]):
def g(self, x: S) -> Union[S, T]: ...

f(lambda x: x.g(0)) # E: Incompatible return value type (got "Union[int, T]", expected "int")
reveal_type(f(lambda x: x.g(0))) # N: Revealed type is "builtins.int"

[case testDictStarInference]
class B: ...
Expand Down Expand Up @@ -3059,14 +3059,19 @@ def dec5(f: Callable[[int], T]) -> Callable[[int], List[T]]:
return [f(x)] * x
return g

I = TypeVar("I", bound=int)
def dec4_bound(f: Callable[[I], List[T]]) -> Callable[[I], T]:
...

reveal_type(dec1(lambda x: x)) # N: Revealed type is "def [T] (T`3) -> builtins.list[T`3]"
reveal_type(dec2(lambda x: x)) # N: Revealed type is "def [S] (S`4) -> builtins.list[S`4]"
reveal_type(dec3(lambda x: x[0])) # N: Revealed type is "def [S] (S`6) -> S`6"
reveal_type(dec4(lambda x: [x])) # N: Revealed type is "def [S] (S`9) -> S`9"
reveal_type(dec1(lambda x: 1)) # N: Revealed type is "def (builtins.int) -> builtins.list[builtins.int]"
reveal_type(dec5(lambda x: x)) # N: Revealed type is "def (builtins.int) -> builtins.list[builtins.int]"
reveal_type(dec3(lambda x: x)) # N: Revealed type is "def [S] (S`16) -> builtins.list[S`16]"
dec4(lambda x: x) # E: Incompatible return value type (got "S", expected "List[object]")
reveal_type(dec4(lambda x: x)) # N: Revealed type is "def [T] (builtins.list[T`19]) -> T`19"
dec4_bound(lambda x: x) # E: Value of type variable "I" of "dec4_bound" cannot be "List[T]"
[builtins fixtures/list.pyi]

[case testInferenceAgainstGenericParamSpecBasicInList]
Expand Down
19 changes: 19 additions & 0 deletions test-data/unit/check-inference-context.test
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,25 @@ def g(l: List[C], x: str) -> Optional[C]:
return f(l, lambda c: reveal_type(c).x) # N: Revealed type is "__main__.C"
[builtins fixtures/list.pyi]

[case testPartialTypeContextWithTwoLambdas]
from typing import Any, Generic, TypeVar, Callable

def int_to_any(x: int) -> Any: ...
def any_to_int(x: Any) -> int: ...
def any_to_str(x: Any) -> str: ...

T = TypeVar("T")
class W(Generic[T]):
def __init__(
self, serialize: Callable[[T], Any], deserialize: Callable[[Any], T]
) -> None:
...
reveal_type(W(lambda x: int_to_any(x), lambda x: any_to_int(x))) # N: Revealed type is "__main__.W[builtins.int]"
W(
lambda x: int_to_any(x), # E: Argument 1 to "int_to_any" has incompatible type "str"; expected "int"
lambda x: any_to_str(x)
)

[case testWideOuterContextEmpty]
from typing import List, TypeVar

Expand Down
8 changes: 8 additions & 0 deletions test-data/unit/cmdline.test
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,14 @@ note: A user-defined top-level module with name "typing" is not supported
Failed to find builtin module mypy_extensions, perhaps typeshed is broken?
== Return code: 2

[case testNewTypeInferenceFlagDeprecated]
# cmd: mypy --new-type-inference a.py
[file a.py]
pass
[out]
Warning: --new-type-inference flag is deprecated; new type inference algorithm is already enabled by default
== Return code: 0

[case testNotesOnlyResultInExitSuccess]
# cmd: mypy a.py
[file a.py]
Expand Down

0 comments on commit 93d4cb0

Please sign in to comment.