Skip to content

Enable new type inference by default #16345

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

Merged
merged 6 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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