diff --git a/conformance/third_party/conformance.exp b/conformance/third_party/conformance.exp index e119b986f7..c8c9269ed6 100644 --- a/conformance/third_party/conformance.exp +++ b/conformance/third_party/conformance.exp @@ -1800,17 +1800,6 @@ "stop_column": 16, "stop_line": 66 }, - { - "code": -2, - "column": 12, - "concise_description": "Returned type `Literal[True]` is not assignable to declared return type `None`", - "description": "Returned type `Literal[True]` is not assignable to declared return type `None`", - "line": 71, - "name": "bad-return", - "severity": "error", - "stop_column": 16, - "stop_line": 71 - }, { "code": -2, "column": 11, diff --git a/pyrefly/lib/alt/unwrap.rs b/pyrefly/lib/alt/unwrap.rs index bde9e52f93..416e3cb3b6 100644 --- a/pyrefly/lib/alt/unwrap.rs +++ b/pyrefly/lib/alt/unwrap.rs @@ -447,9 +447,10 @@ impl<'ctx, 'answer, Ans: LookupAnswer> AnswersSolver<'ctx, 'answer, Ans> { let send_ty = self .resolve_var_opt(ty, send_ty) .unwrap_or_else(|| self.heap.mk_none()); + // Iterator and Iterable annotations do not constrain the generator's return value. let return_ty = self .resolve_var_opt(ty, return_ty) - .unwrap_or_else(|| self.heap.mk_none()); + .unwrap_or_else(|| self.heap.mk_any_implicit()); Some((yield_ty, send_ty, return_ty)) } else { None diff --git a/pyrefly/lib/test/yields.rs b/pyrefly/lib/test/yields.rs index e3cf7b747c..fff19c6134 100644 --- a/pyrefly/lib/test/yields.rs +++ b/pyrefly/lib/test/yields.rs @@ -639,6 +639,36 @@ def g() -> Iterator[list[int]] | Iterator[list[str]]: "#, ); +testcase!( + test_iterator_annotation_with_return_value, + r#" +from collections.abc import Generator, Iterable, Iterator +from typing import assert_type + +def gen(x: int) -> Iterator[int] | int: + yield from range(4) + return 5 + +assert_type(gen(0), Iterator[int] | int) + +def iterator() -> Iterator[int]: + yield 1 + return "done" + +def iterable() -> Iterable[int]: + yield 1 + return "done" + +def bad_yield() -> Iterator[int] | int: + yield "oops" # E: Yielded type `Literal['oops']` is not assignable to declared yield type `int` + return 5 + +def explicit_return_type() -> Generator[int, None, None] | int: + yield 1 + return 5 # E: Returned type `Literal[5]` is not assignable to declared return type `None` + "#, +); + testcase!( test_return_is_incompatible_with_generator, r#"