@@ -236,46 +236,92 @@ assert_type(keep([]), list[Any])
236236 "# ,
237237) ;
238238
239+ testcase ! (
240+ test_any_bounded_typevar_preserves_structure,
241+ r#"
242+ from typing import Any, assert_type, overload
243+
244+ class Array[S, D]: ...
245+
246+ @overload
247+ def stack[S: tuple[int, int, *tuple[Any, ...]], D](
248+ xs: list[Array[S, D]],
249+ ) -> Array[S, D]: ...
250+ @overload
251+ def stack[D](xs: list[Array[tuple[int], D]]) -> Array[tuple[int, int], D]: ...
252+ def stack(xs):
253+ return Array()
254+
255+ a: Array[tuple[int], int] = Array()
256+ assert_type(stack([a, a]), Array[tuple[int, int], int])
257+ b: Array[tuple[int, int, int], str] = Array()
258+ assert_type(stack([b, b]), Array[tuple[int, int, int], str])
259+
260+ def keep[T: dict[float, Any]](x: T) -> T: ...
261+ assert_type(keep({0: "a"}), dict[float, str])
262+ "# ,
263+ ) ;
264+
265+ testcase ! (
266+ test_any_bounded_typevar_preserves_subclass,
267+ r#"
268+ from typing import Any, assert_type
269+
270+ class Scalar[T]:
271+ def item(self) -> T: ...
272+ class Float32(Scalar[float]): ...
273+ class Array[S, D]:
274+ def scalar(self) -> D: ...
275+
276+ def stack[T: Scalar[Any]](
277+ xs: list[T | Array[tuple[int], T]],
278+ ) -> Array[tuple[int, int], T]: ...
279+
280+ a: Array[tuple[int], Float32] = Array()
281+ assert_type(stack([a, a]), Array[tuple[int, int], Float32])
282+ "# ,
283+ ) ;
284+
285+ // The `Any` in the element bound supplies no hint for a nested empty literal.
239286testcase ! (
240287 test_any_bounded_typevar_nested_empty_literal,
241288 r#"
242289from typing import Any, reveal_type
243290
244291def keep[T: list[Any]](x: T) -> T: ...
245292
246- reveal_type(keep([[]])) # E: revealed type: list[list[Any ]]
247- reveal_type(keep([[], [1]])) # E: revealed type: list[list[int] | list[Any ]]
248- reveal_type(keep([[] for _ in [0]])) # E: revealed type: list[list[Any ]]
249- reveal_type(keep([set()])) # E: revealed type: list[set[Any ]]
250- reveal_type(keep([list()])) # E: revealed type: list[list[Any ]]
251- reveal_type(keep([{}])) # E: revealed type: list[dict[Any, Any ]]
293+ reveal_type(keep([[]])) # E: revealed type: list[list[@_ ]]
294+ reveal_type(keep([[], [1]])) # E: revealed type: list[list[int] | list[@_ ]]
295+ reveal_type(keep([[] for _ in [0]])) # E: revealed type: list[list[@_ ]]
296+ reveal_type(keep([set()])) # E: revealed type: list[set[@_ ]]
297+ reveal_type(keep([list()])) # E: revealed type: list[list[@_ ]]
298+ reveal_type(keep([{}])) # E: revealed type: list[dict[@_, @_ ]]
252299 "# ,
253300) ;
254301
255302// https://github.com/facebook/pyrefly/issues/3265
256303// Any in a bound should preserve the concrete element types asserted below.
257304testcase ! (
258- bug = "Any bounds erase inferred container element types" ,
259305 test_any_bounded_typevar_container_hints,
260306 r#"
261307from typing import Any, Iterator, Protocol, assert_type
262308
263309def keep_set[T: set[Any]](x: T) -> T: ...
264310def keep_dict[T: dict[Any, Any]](x: T) -> T: ...
265- assert_type(keep_set({0}), set[int]) # E: assert_type(set[Any], set[int]) failed
266- assert_type(keep_set({x for x in [0]}), set[int]) # E: assert_type(set[Any], set[int]) failed
267- assert_type(keep_dict({0: "a"}), dict[int, str]) # E: assert_type(dict[Any, Any], dict[int, str]) failed
268- assert_type(keep_dict({x: str(x) for x in [0]}), dict[int, str]) # E: assert_type(dict[Any, Any], dict[int, str]) failed
311+ assert_type(keep_set({0}), set[int])
312+ assert_type(keep_set({x for x in [0]}), set[int])
313+ assert_type(keep_dict({0: "a"}), dict[int, str])
314+ assert_type(keep_dict({x: str(x) for x in [0]}), dict[int, str])
269315assert_type(keep_dict({}), dict[Any, Any])
270- assert_type(keep_dict({0: []}), dict[int, list[Any]]) # E: assert_type(dict[Any, Any], dict[int, list[Any]]) failed
316+ assert_type(keep_dict({0: []}), dict[int, list[Any]])
271317
272318class ReturnsIterator[T](Protocol):
273319 def __iter__(self) -> T: ...
274320
275321def iterator[I: Iterator[Any]](x: ReturnsIterator[I]) -> I: ...
276322assert_type(iterator([0]), Iterator[int])
277- assert_type(iterator({0}), Iterator[int]) # E: assert_type(Iterator[Any], Iterator[int]) failed
278- assert_type(iterator({0: "a"}), Iterator[int]) # E: assert_type(Iterator[Any], Iterator[int]) failed
323+ assert_type(iterator({0}), Iterator[int])
324+ assert_type(iterator({0: "a"}), Iterator[int])
279325
280326# Concrete bounds and explicit Any annotations still supply contextual types.
281327def floats[T: list[float]](x: T) -> T: ...
0 commit comments