Skip to content

Bad Type Variable resolution with outer context (dict.get) #2136

@randolf-scholz

Description

@randolf-scholz

Describe the Bug

In the example below, I create a dict-like class

from typing import Any, reveal_type

class Map[K, V]:
    def set(self, key: K, value: V) -> None: ...
    def get[T=None](self, key: Any, default: T = None, /) -> V | T: ...

d_any: Map[str, Any] = Map()

# as expected, these are both `Any | None`
reveal_type(d_any.get("key"))  # Any | None  ✅️
reveal_type(d_any.get("key", None))  # Any | None  ✅️
# outer context should not overrule the argument type!
result: str = reveal_type(d_any.get("key", None))  # Any | str ❌️
ERROR sandbox.py:13:44-48: Argument `None` is not assignable to parameter `default` with type `str` in function `Map.get`

This message is confusing, it should be "Any | None can't be assigned to str".

Explanation

d_any.get("key", None) produces Any | None, and we have str as outer context. This gives an unsolvable situation for the type variable T as we would need both T <: str and T :> None. It seems pyrefly gives priority to the outer constraint T <: str here, which seems misguided and leads to an illogical error message:

Instead, I believe priority should be given to the inner constraint T :> None and the error message should be that Any | None cannot be assigned to str as pyright does it (Code sample in pyright playground)

Sandbox Link

https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0BBdKQA0dSjABuMVFAD6TYjAA66VQGMoqOHDoBZVMQDaAaTEA1ALqJVdO3UwwwdODAYAKV1DBiA1jFJEOjM6SVkAVxgg8wBKOgBaAD46ADlcdCi6Qmzbe0dnNjcjABUAXjSMy08Ybz8AoKFRBydUcKgGIOK6UtT0mDEAejikunM6AB86YqDswlVVTDkMQP1DIzgGSjFGy27V4ncY%2BfQAYjptOhh8JXUGGEwxBgALeBhziTo8Z7oAA0aJ3oZH6qCTSWQKZgwdyLZaEQoeZQgfykRExOJ0M7-SYVN50QCg5IB4P5BUhk8kUUJhwjhbnciORiLEOLRdkxwgBOLshNUZ1w4TulDo6nSd3w-DgT15UEwdHQuH4uGklEobTezzeqEobHCNBg6H45IAhMS4G0Oi5NntQaSIUpoUsqfDaUiAgzATBmRjBGzJhsBYAZcgJIBEID50DgJHIiBAZwAqgxoBAmHQwOF0LcIOk4Md8sneDRUAw5OhtdgYJR3PggqwGMNkr6bOh7OI3OFKI2wIiUiWy0FgPgAL6I1RBkBkCRgKCkQgMWhQChnAAKpHHk5cGBwBEF6UgWsoBYz6DmpzoAGUYG8ngwGMQ4IgBgMx05J4ReGwBrqBphcOo4AMhegd1bfd0gGXMBVQMJoFQbBYC3ACIF3YDG1wYh40zI8yGedJ4kVOADz2REAGZCAARkIod0BAftg1QdNpAAMWgGAKDQLA8CIMgqKAA

See Also:

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions