diff --git a/mypy/checker.py b/mypy/checker.py index e68dc4178962..fd633b209438 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -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 diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index ddcaa6ee30c9..9ece4680f59e 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -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 = {} @@ -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) @@ -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, @@ -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). diff --git a/mypy/main.py b/mypy/main.py index 718eb5a7c0c1..43ab761072ca 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -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", @@ -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") diff --git a/mypy/options.py b/mypy/options.py index 3447b5dfb1f6..31d5d584f897 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -62,7 +62,7 @@ class BuildType: | { "platform", "bazel", - "new_type_inference", + "old_type_inference", "plugins", "disable_bytearray_promotion", "disable_memoryview_promotion", @@ -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). diff --git a/mypy_self_check.ini b/mypy_self_check.ini index 093926d4c415..7f1f9689a757 100644 --- a/mypy_self_check.ini +++ b/mypy_self_check.ini @@ -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 diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index 0781451e07ce..ef3f359e4989 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -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: ... @@ -3059,6 +3059,10 @@ 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" @@ -3066,7 +3070,8 @@ 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] diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test index 773a9ffd8274..a933acbf7f32 100644 --- a/test-data/unit/check-inference-context.test +++ b/test-data/unit/check-inference-context.test @@ -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 diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index cf5e3c438fac..91242eb62fcf 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -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]