From becb55b4d350af142cd9c0a1e482cf16d4cfea15 Mon Sep 17 00:00:00 2001 From: KotlinIsland <65446343+kotlinisland@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:57:59 +1000 Subject: [PATCH] infer return types --- .mypy/baseline.json | 30 +++--- CHANGELOG.md | 2 + docs/source/based_inference.rst | 19 ++++ mypy/checker.py | 96 ++++++++++++++++--- mypy/checkexpr.py | 40 +++++--- mypy/semanal.py | 26 +++-- mypy/test/testcmdline.py | 1 + mypy/types.py | 3 + .../unit/check-based-default-return.test | 20 ++-- ...heck-based-infer-function-return-type.test | 32 +++++++ .../check-based-infer-function-types.test | 6 +- test-data/unit/check-based-untyped.test | 5 - test-data/unit/check-expressions.test | 1 - test-data/unit/check-incremental.test | 3 +- test-data/unit/check-inference-context.test | 5 +- test-data/unit/check-optional.test | 2 +- 16 files changed, 207 insertions(+), 84 deletions(-) create mode 100644 test-data/unit/check-based-infer-function-return-type.test diff --git a/.mypy/baseline.json b/.mypy/baseline.json index c9c61bae3..585133386 100644 --- a/.mypy/baseline.json +++ b/.mypy/baseline.json @@ -1989,7 +1989,7 @@ "code": "explicit-override", "column": 4, "message": "Method \"type_context\" is not using @override but is overriding a method in class \"mypy.plugin.CheckerPluginInterface\"", - "offset": 456, + "offset": 464, "src": "def type_context(self) -> list[Type | None]:", "target": "mypy.checker" }, @@ -1997,7 +1997,7 @@ "code": "explicit-override", "column": 4, "message": "Method \"visit_overloaded_func_def\" is not using @override but is overriding a method in class \"mypy.visitor.NodeVisitor\"", - "offset": 191, + "offset": 198, "src": "def visit_overloaded_func_def(self, defn: OverloadedFuncDef, do_items=True) -> None:", "target": "mypy.checker.TypeChecker.visit_overloaded_func_def" }, @@ -2029,7 +2029,7 @@ "code": "explicit-override", "column": 4, "message": "Method \"visit_class_def\" is not using @override but is overriding a method in class \"mypy.visitor.NodeVisitor\"", - "offset": 1113, + "offset": 1151, "src": "def visit_class_def(self, defn: ClassDef) -> None:", "target": "mypy.checker.TypeChecker.visit_class_def" }, @@ -2093,7 +2093,7 @@ "code": "truthy-bool", "column": 23, "message": "\"signature\" has type \"Type\" which does not implement __bool__ or __len__ so it could always be true in boolean context", - "offset": 169, + "offset": 172, "src": "if signature:", "target": "mypy.checker.TypeChecker.check_assignment" }, @@ -2245,7 +2245,7 @@ "code": "explicit-override", "column": 4, "message": "Method \"visit_if_stmt\" is not using @override but is overriding a method in class \"mypy.visitor.NodeVisitor\"", - "offset": 111, + "offset": 123, "src": "def visit_if_stmt(self, s: IfStmt) -> None:", "target": "mypy.checker.TypeChecker.visit_if_stmt" }, @@ -2639,7 +2639,7 @@ "code": "truthy-bool", "column": 34, "message": "\"item_name_expr\" has type \"Expression\" which does not implement __bool__ or __len__ so it could always be true in boolean context", - "offset": 424, + "offset": 430, "src": "key_context = item_name_expr or item_arg", "target": "mypy.checkexpr.ExpressionChecker.validate_typeddict_kwargs" }, @@ -3055,7 +3055,7 @@ "code": "explicit-override", "column": 4, "message": "Method \"visit_await_expr\" is not using @override but is overriding a method in class \"mypy.visitor.ExpressionVisitor\"", - "offset": 21, + "offset": 33, "src": "def visit_await_expr(self, e: AwaitExpr, allow_none_return: bool = False) -> Type:", "target": "mypy.checkexpr.ExpressionChecker.visit_await_expr" }, @@ -6859,7 +6859,7 @@ "code": "redundant-expr", "column": 19, "message": "Condition is always false", - "offset": 375, + "offset": 377, "src": "if e.type is None:", "target": "mypy.errors.Errors.render_messages" }, @@ -32695,7 +32695,7 @@ "code": "explicit-override", "column": 4, "message": "Method \"__repr__\" is not using @override but is overriding a method in class \"builtins.object\"", - "offset": 96, + "offset": 97, "src": "def __repr__(self) -> str:", "target": "mypy.types.Type.__repr__" }, @@ -33631,7 +33631,7 @@ "code": "explicit-override", "column": 4, "message": "Method \"describe\" is not using @override but is overriding a method in class \"mypy.types.AnyType\"", - "offset": 59, + "offset": 61, "src": "def describe(self) -> str:", "target": "mypy.types.UntypedType.describe" }, @@ -36585,19 +36585,11 @@ "src": "def attrgetter(name: str) -> operator.attrgetter[Any]:", "target": "mypy.util.attrgetter" }, - { - "code": "no-any-expr", - "column": 11, - "message": "Expression type contains \"Any\" (has type \"attrgetter[Any]\")", - "offset": 1, - "src": "return operator.attrgetter(name)", - "target": "mypy.util.attrgetter" - }, { "code": "no-any-expr", "column": 7, "message": "Expression has type \"Any\"", - "offset": 4, + "offset": 5, "src": "if orjson is not None:", "target": "mypy.util.json_dumps" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 738997f59..bef77132f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Basedmypy Changelog ## [Unreleased] +### Added +- infer return types and generator types ## [2.9.1] ### Fixed diff --git a/docs/source/based_inference.rst b/docs/source/based_inference.rst index c067e0ca6..63af8ec82 100644 --- a/docs/source/based_inference.rst +++ b/docs/source/based_inference.rst @@ -60,3 +60,22 @@ When a parameter is named `_`, it's type will be inferred as `object`: reveal_type(_) # Revealed type is "object" This is to help with writing functions for callbacks where you don't care about certain parameters. + + +Return Type Inferred +-------------------- + +.. code-block:: python + + def f(): # Revealed type is "() -> 1" + return 1 + + +Generator Type Inferred +----------------------- + +.. code-block:: python + + def f(): # Revealed type is "() -> Generator[1, str, 2]" + a: str = yield 1 + return 2 diff --git a/mypy/checker.py b/mypy/checker.py index 0fdb34335..0c04a407f 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4,7 +4,7 @@ import itertools from collections import defaultdict -from contextlib import ExitStack, contextmanager +from contextlib import ExitStack, contextmanager, nullcontext from typing import ( AbstractSet, Callable, @@ -23,7 +23,7 @@ cast, overload, ) -from typing_extensions import TypeAlias as _TypeAlias +from typing_extensions import ContextManager, TypeAlias as _TypeAlias import mypy.checkexpr from mypy import errorcodes as codes, join, message_registry, nodes, operators @@ -249,7 +249,9 @@ # Maximum length of fixed tuple types inferred when narrowing from variadic tuples. MAX_PRECISE_TUPLE_SIZE: Final = 8 -DeferredNodeType: _TypeAlias = Union[FuncDef, LambdaExpr, OverloadedFuncDef, Decorator] +DeferredNodeType: _TypeAlias = Union[ + FuncDef, LambdaExpr, OverloadedFuncDef, Decorator, AssignmentStmt +] FineGrainedDeferredNodeType: _TypeAlias = Union[FuncDef, MypyFile, OverloadedFuncDef] @@ -260,7 +262,7 @@ class DeferredNode(NamedTuple): node: DeferredNodeType # And its TypeInfo (for semantic analysis self type handling - active_typeinfo: TypeInfo | None + active_typeinfo: TypeInfo | FuncItem | None # Same as above, but for fine-grained mode targets. Only top-level functions/methods @@ -452,6 +454,12 @@ def __init__( # always the next if statement to have a redundant expression self.allow_redundant_expr = False + self.should_defer_current_node = False + """when a parent node should be defered""" + self.inferred_return_types: list[Type] = [] + self.inferred_yield_types: list[Type] = [] + self.inferred_send_types: list[Type] = [] + @property def type_context(self) -> list[Type | None]: return self.expr_checker.type_context @@ -551,10 +559,15 @@ def check_second_pass( # (self.pass_num, type_name, node.fullname or node.name)) done.add(node) with ExitStack() as stack: - if active_typeinfo: + cm: ContextManager[object] = nullcontext() + if isinstance(active_typeinfo, FuncItem): + stack.enter_context(self.scope.push_function(active_typeinfo)) + cm = self.tscope.function_scope(active_typeinfo) + elif active_typeinfo: stack.enter_context(self.tscope.class_scope(active_typeinfo)) stack.enter_context(self.scope.push_class(active_typeinfo)) - self.check_partial(node) + with cm: + self.check_partial(node) return True def check_partial(self, node: DeferredNodeType | FineGrainedDeferredNodeType) -> None: @@ -579,7 +592,9 @@ def check_top_level(self, node: MypyFile) -> None: assert not self.current_node_deferred # TODO: Handle __all__ - def defer_node(self, node: DeferredNodeType, enclosing_class: TypeInfo | None) -> None: + def defer_node( + self, node: DeferredNodeType, enclosing_class: TypeInfo | FuncItem | None + ) -> None: """Defer a node for processing during next type-checking pass. Args: @@ -1577,6 +1592,12 @@ def check_func_def( new_frame = self.binder.push_frame() new_frame.types[key] = narrowed_type self.binder.declarations[key] = old_binder.declarations[key] + inferred_return_types = self.inferred_return_types + self.inferred_return_types = [] + inferred_yield_types = self.inferred_yield_types + self.inferred_yield_types = [] + inferred_send_types = self.inferred_send_types + self.inferred_send_types = [] with self.scope.push_function(defn): # We suppress reachability warnings for empty generator functions # (return; yield) which have a "yield" that's unreachable by definition @@ -1591,6 +1612,37 @@ def check_func_def( if _is_empty_generator_function(item) or len(expanded) >= 2: self.binder.suppress_unreachable_warnings() self.accept(item.body) + if self.options.default_return: + if not self.binder.is_unreachable(): + self.inferred_return_types.append(NoneType()) + + ret_type = get_proper_type(typ.ret_type) + if ( + isinstance(ret_type, UntypedType) + and ret_type.type_of_any == TypeOfAny.to_be_inferred + ): + ret_type = make_simplified_union(self.inferred_return_types) + item.type = typ.copy_modified(ret_type=ret_type) + if self.inferred_yield_types or self.inferred_send_types: + yield_type = ( + make_simplified_union(self.inferred_yield_types) + if self.inferred_yield_types + else self.named_type("builtins.object") + ) + # `Never` here isn't ideal, and neither is `object`, so we just go with the default typevar value + send_type = ( + make_simplified_intersection(self.inferred_send_types) + if self.inferred_send_types + else NoneType() + ) + assert isinstance(item.type, CallableType) + item.type.ret_type = Instance( + self.lookup_typeinfo("typing.Generator"), + [yield_type, send_type, item.type.ret_type], + ) + self.inferred_return_types = inferred_return_types + self.inferred_yield_types = inferred_yield_types + self.inferred_send_types = inferred_send_types unreachable = self.binder.is_unreachable() if new_frame is not None: self.binder.pop_frame(True, 0) @@ -1783,13 +1835,14 @@ def check_for_missing_annotations(self, fdef: FuncItem) -> None: if not fdef.arguments or ( len(fdef.arguments) == 1 and (fdef.arg_names[0] in ("self", "cls")) ): - self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) - if not has_return_statement(fdef) and not fdef.is_generator: - self.note( - 'Use "-> None" if function does not return a value', - fdef, - code=codes.NO_UNTYPED_DEF, - ) + if not self.options.default_return: + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) + if not has_return_statement(fdef) and not fdef.is_generator: + self.note( + 'Use "-> None" if function does not return a value', + fdef, + code=codes.NO_UNTYPED_DEF, + ) else: self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef) elif isinstance(fdef.type, CallableType): @@ -3260,6 +3313,9 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: s.new_syntax, override_infer=s.unanalyzed_type is not None, ) + if self.should_defer_current_node: + self.defer_node(s, self.scope.top_function()) + self.should_defer_current_node = False if s.is_alias_def: self.check_type_alias_rvalue(s) @@ -5055,6 +5111,18 @@ def check_return_stmt(self, s: ReturnStmt) -> None: if defn.is_async_generator: self.fail(message_registry.RETURN_IN_ASYNC_GENERATOR, s) return + if defn.type: + assert isinstance(defn.type, CallableType) + proper_type = get_proper_type(defn.type.ret_type) + infer = ( + isinstance(proper_type, UntypedType) + and proper_type.type_of_any == TypeOfAny.to_be_inferred + ) + else: + infer = True + if infer: + self.inferred_return_types.append(typ) + return # Returning a value of type Any is always fine. if isinstance(typ, AnyType): # (Unless you asked to be warned in that case, and the diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index e447ea0e4..c4f8a4e7c 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -629,7 +629,7 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> fullname == p or fullname.startswith(f"{p}.") for p in self.chk.options.untyped_calls_exclude ): - if callee_type.implicit: + if callee_type.implicit and not self.chk.options.infer_function_types: self.msg.untyped_function_call(callee_type, e) if fullname is None and member is not None: assert object_type is not None @@ -638,7 +638,13 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> fullname == p or fullname.startswith(f"{p}.") for p in self.chk.options.untyped_calls_exclude ): - if callee_type.implicit: + proper_type = get_proper_type(callee_type.ret_type) + if ( + isinstance(proper_type, UntypedType) + and proper_type.type_of_any == TypeOfAny.to_be_inferred + ): + self.chk.current_node_deferred = True + elif callee_type.implicit and not self.chk.options.infer_function_types: self.msg.untyped_function_call(callee_type, e) elif has_untyped_type(callee_type): # Get module of the function, to get its settings @@ -6290,22 +6296,34 @@ def not_ready_callback(self, name: str, context: Context) -> None: def visit_yield_expr(self, e: YieldExpr) -> Type: return_type = self.chk.return_types[-1] expected_item_type = self.chk.get_generator_yield_type(return_type, False) + proper_type = get_proper_type(return_type) + infer = ( + isinstance(proper_type, UntypedType) + and proper_type.type_of_any == TypeOfAny.to_be_inferred + ) + if infer and self.type_context[-1]: + self.chk.inferred_send_types.append(self.type_context[-1]) if e.expr is None: - if ( + if infer: + self.chk.inferred_yield_types.append(NoneType()) + elif ( not isinstance(get_proper_type(expected_item_type), (NoneType, AnyType)) and self.chk.in_checked_function() ): self.chk.fail(message_registry.YIELD_VALUE_EXPECTED, e) else: actual_item_type = self.accept(e.expr, expected_item_type) - self.chk.check_subtype( - actual_item_type, - expected_item_type, - e, - message_registry.INCOMPATIBLE_TYPES_IN_YIELD, - "actual type", - "expected type", - ) + if infer: + self.chk.inferred_yield_types.append(actual_item_type) + else: + self.chk.check_subtype( + actual_item_type, + expected_item_type, + e, + message_registry.INCOMPATIBLE_TYPES_IN_YIELD, + "actual type", + "expected type", + ) return self.chk.get_generator_receive_type(return_type, False) def visit_await_expr(self, e: AwaitExpr, allow_none_return: bool = False) -> Type: diff --git a/mypy/semanal.py b/mypy/semanal.py index 2f34392c4..352d1b942 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -8044,8 +8044,8 @@ def is_unannotated_any(typ_: Type) -> bool: typ = self.named_type("builtins.object") arg_types.append(typ or UntypedType()) ret_type = None - if self.options.default_return and self.options.disallow_untyped_defs: - ret_type = NoneType() + if self.options.default_return: + ret_type = UntypedType() if any(not isinstance(get_proper_type(t), AnyType) for t in arg_types) or ret_type: defn.type = CallableType( arg_types or [UntypedType() for _ in defn.arg_kinds], @@ -8059,19 +8059,8 @@ def is_unannotated_any(typ_: Type) -> bool: implicit=not self.options.disallow_untyped_defs, ) elif defn.type: - assert isinstance(defn.type, CallableType) - if ( - self.options.default_return - and is_unannotated_any(defn.type.ret_type) - and ( - isinstance(defn.unanalyzed_type, CallableType) - and not self.options.disallow_untyped_defs - and any(defn.unanalyzed_type.arg_types) - or self.options.disallow_untyped_defs - ) - ): - defn.type.ret_type = NoneType() if self.options.infer_function_types: + assert isinstance(defn.type, CallableType) for i, arg in enumerate(defn.arguments): ret = None if is_unannotated_any(defn.type.arg_types[i]): @@ -8083,6 +8072,15 @@ def is_unannotated_any(typ_: Type) -> bool: defn.type.arg_types[i] = ret if all(char == "_" for char in arg.variable.name): defn.type.arg_types[i] = self.named_type("builtins.object") + if not self.options.default_return or not defn.type: + return + assert isinstance(defn.type, CallableType) + proper_type = get_proper_type(defn.type.ret_type) + if isinstance(proper_type, UntypedType): + if is_trivial_body(defn.body): + defn.type.ret_type = NoneType() + else: + proper_type.type_of_any = TypeOfAny.to_be_inferred def is_trivial_body(block: Block) -> bool: diff --git a/mypy/test/testcmdline.py b/mypy/test/testcmdline.py index cc2c6058c..ea41b2dcf 100644 --- a/mypy/test/testcmdline.py +++ b/mypy/test/testcmdline.py @@ -68,6 +68,7 @@ def test_python_cmdline(testcase: DataDrivenTestCase, step: int) -> None: if not based: args.append("--no-strict") args.append("--no-default-return") + args.append("--no-infer-function-types") if "--pretty" not in args: args.append("--no-pretty") args.append("--no-color-output") diff --git a/mypy/types.py b/mypy/types.py index 6036065c4..dc7d63c3a 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -214,6 +214,7 @@ class TypeOfAny: # used to ignore Anys inserted by the suggestion engine when # generating constraints. suggestion_engine: Final = 9 + to_be_inferred: Final = 111 def deserialize_type(data: JsonDict | str) -> Type: @@ -1247,6 +1248,8 @@ def describe_type_of_any(type_of_any: int = self.type_of_any) -> str | None: return "from a limitation" elif type_of_any == TypeOfAny.suggestion_engine: return "from a suggestion" + elif type_of_any == TypeOfAny.to_be_inferred: + return "uninferred" assert False, f"unreachable: {type_of_any}" description = self.__class__.__name__.split("Type")[0] diff --git a/test-data/unit/check-based-default-return.test b/test-data/unit/check-based-default-return.test index 8d013fe6e..770db9d02 100644 --- a/test-data/unit/check-based-default-return.test +++ b/test-data/unit/check-based-default-return.test @@ -21,7 +21,7 @@ reveal_type(A.g) # N: Revealed type is "def (self: __main__.A, i: int) -> None" # flags: --allow-untyped-defs --allow-any-expr def f(): ... -reveal_type(f) # N: Revealed type is "def () -> Untyped" +reveal_type(f) # N: Revealed type is "def () -> None" def g(i: int): ... reveal_type(g) # N: Revealed type is "def (i: int) -> None" @@ -34,8 +34,8 @@ class A: def h(self, i: int): ... def i(self, i: int, j): ... # E: Function is missing a type annotation for one or more arguments [no-untyped-def] -reveal_type(A.f) # N: Revealed type is "def (self: __main__.A) -> Untyped" -reveal_type(A.g) # N: Revealed type is "def (self: __main__.A, i: Untyped) -> Untyped" +reveal_type(A.f) # N: Revealed type is "def (self: __main__.A) -> None" +reveal_type(A.g) # N: Revealed type is "def (self: __main__.A, i: Untyped) -> None" reveal_type(A.h) # N: Revealed type is "def (self: __main__.A, i: int) -> None" reveal_type(A.i) # N: Revealed type is "def (self: __main__.A, i: int, j: Untyped) -> None" @@ -44,7 +44,7 @@ reveal_type(A.i) # N: Revealed type is "def (self: __main__.A, i: int, j: Untyp # flags: --allow-incomplete-defs --allow-untyped-defs --allow-any-expr def f(i): ... -reveal_type(f) # N: Revealed type is "def (i: Untyped) -> Untyped" +reveal_type(f) # N: Revealed type is "def (i: Untyped) -> None" def g(i: int, j): ... reveal_type(g) # N: Revealed type is "def (i: int, j: Untyped) -> None" @@ -55,23 +55,23 @@ class A: def h(self, i: int): ... def i(self, i: int, j): ... -reveal_type(A.f) # N: Revealed type is "def (self: __main__.A) -> Untyped" -reveal_type(A.g) # N: Revealed type is "def (self: __main__.A, i: Untyped) -> Untyped" +reveal_type(A.f) # N: Revealed type is "def (self: __main__.A) -> None" +reveal_type(A.g) # N: Revealed type is "def (self: __main__.A, i: Untyped) -> None" reveal_type(A.h) # N: Revealed type is "def (self: __main__.A, i: int) -> None" reveal_type(A.i) # N: Revealed type is "def (self: __main__.A, i: int, j: Untyped) -> None" [case testGenerator] -def f(): # E: The return type of a generator function should be "Generator" or one of its supertypes [misc] +def f(): yield -def g(i: int): # E: The return type of a generator function should be "Generator" or one of its supertypes [misc] +def g(i: int): yield class A: - def f(self): # E: The return type of a generator function should be "Generator" or one of its supertypes [misc] + def f(self): yield - def g(self, i: int): # E: The return type of a generator function should be "Generator" or one of its supertypes [misc] + def g(self, i: int): yield diff --git a/test-data/unit/check-based-infer-function-return-type.test b/test-data/unit/check-based-infer-function-return-type.test new file mode 100644 index 000000000..9da159089 --- /dev/null +++ b/test-data/unit/check-based-infer-function-return-type.test @@ -0,0 +1,32 @@ +[case testInferReturnType] +def m(): + a: int = f() + b = f() + reveal_type(b) # N: Revealed type is "int" + e: str = f() # E: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment] + +def f(): + return 1 + +c: int = f() +d: str = f() # E: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment] + +reveal_type(f) # N: Revealed type is "def () -> 1" + + +[case testInferGenerator] +from typing import Generator +class A: ... +class B: ... +def f(): + yield 1 + a: A = yield 2 + b: B = yield 3 + return 4 + +reveal_type(f) # N: Revealed type is "def () -> typing.Generator[1 | 2 | 3, __main__.A & __main__.B, 4]" + +def f2(): + yield + +reveal_type(f2) # N: Revealed type is "def () -> typing.Generator[None, None, None]" diff --git a/test-data/unit/check-based-infer-function-types.test b/test-data/unit/check-based-infer-function-types.test index 9269404a1..f88ab6213 100644 --- a/test-data/unit/check-based-infer-function-types.test +++ b/test-data/unit/check-based-infer-function-types.test @@ -350,10 +350,8 @@ class S: def foo(a=1): 1 + "" -foo() # E: Call to untyped function "foo" in typed context [no-untyped-call] -reveal_type(foo) # E: Expression type contains "Any" (has type "def (a: int=...) -> Untyped") [no-any-expr] \ - # E: Expression type contains "Any" (has type "def (a: int=...) -> Untyped") [no-any-expr] \ - # N: Revealed type is "def (a: int =) -> Untyped" +foo() +reveal_type(foo) # N: Revealed type is "def (a: int =) -> None" # because it's inferred def bar(a=1) -> None: 1 + "" # E: Unsupported operand types for + ("int" and "str") [operator] diff --git a/test-data/unit/check-based-untyped.test b/test-data/unit/check-based-untyped.test index cfd5d4ad7..68531d4ba 100644 --- a/test-data/unit/check-based-untyped.test +++ b/test-data/unit/check-based-untyped.test @@ -70,16 +70,11 @@ f2(1) # E: Call to incomplete function "f2" in typed context [no-untyped-call] from basedtyping import Untyped class A: - @property - def foo(self): ... - @foo.setter - def foo(self, value): ... @property def bar(self) -> Untyped: ... @bar.setter def bar(self, value: Untyped) -> None: ... a: A -a.foo = 1 # E: Usage of untyped name "foo" in typed context [no-untyped-usage] a.bar = 1 # E: Usage of untyped name "bar" in typed context [no-untyped-usage] [builtins fixtures/property.pyi] diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index baac06425..6235c9f7a 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1260,7 +1260,6 @@ if int(): if int(): f = lambda: '' \ # E: Incompatible types in assignment (expression has type "Callable[[], str]", variable has type "Callable[[], int]") \ - # E: Incompatible return value type (got "str", expected "int") [case testVoidLambda] import typing diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index f3cf83e6e..4a5744691 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -5,7 +5,8 @@ -- -- You can add an empty section like `[delete mod.py.2]` to delete `mod.py` -- before the second run. --- +--ck + -- Errors expected in the first run should be in the `[out1]` section, and -- errors expected in the second run should be in the `[out2]` section, and so on. -- If a section is omitted, it is expected there are no errors on that run. diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test index a16b61817..d9f939955 100644 --- a/test-data/unit/check-inference-context.test +++ b/test-data/unit/check-inference-context.test @@ -676,7 +676,6 @@ g = lambda x: 1 # type: Callable[..., str] [builtins fixtures/dict.pyi] [out] main:6: error: Incompatible types in assignment (expression has type "Callable[[Any], int]", variable has type "Callable[..., str]") -main:6: error: Incompatible return value type (got "int", expected "str") [case testEllipsisContextForLambda2] from typing import TypeVar, Callable @@ -706,7 +705,7 @@ f(lambda x: 0 if isinstance(x, B) else 1, A())() # E: "int" not callable f(lambda x: x if isinstance(x, B) else B(), A(), r=B())() # E: "B" not callable f( lambda x: # E: Argument 1 to "f" has incompatible type "Callable[[A], A]"; expected "Callable[[A], B]" - B() if isinstance(x, B) else x, # E: Incompatible return value type (got "A", expected "B") + B() if isinstance(x, B) else x, A(), r=B()) [builtins fixtures/isinstance.pyi] @@ -893,7 +892,6 @@ def f(a: T, b: S) -> None: c = lambda x: x # type: Callable[[T], S] [out] main:5: error: Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Callable[[T], S]") -main:5: error: Incompatible return value type (got "T", expected "S") [case testLambdaInGenericClass] from typing import TypeVar, Callable, Generic @@ -904,7 +902,6 @@ class A(Generic[T]): c = lambda x: x # type: Callable[[T], S] [out] main:6: error: Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Callable[[T], S]") -main:6: error: Incompatible return value type (got "T", expected "S") [case testRevealTypeContext] from typing import TypeVar, Callable, Generic diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test index 91feff357..b48296df7 100644 --- a/test-data/unit/check-optional.test +++ b/test-data/unit/check-optional.test @@ -693,7 +693,7 @@ class A: def f(self, x: Optional['A']) -> None: assert x - lambda: (self.y, x.a) # E: Cannot determine type of "y" + lambda: (self.y, x.a) # E: Cannot determine type of "y" self.y = int() [builtins fixtures/isinstancelist.pyi]