facebook / facebook/pyrefly

Support all cases of contextual typing for overloads

Open
#860 1 comment 0 reactions 0 assignees View on GitHub
contextual-typing overloads
Dominant language
Rust
Stars
7k
Forks
516
PR merge metrics
No merged PRs in 30d

Description

### Describe the Bug

We turned off contextual typing altogether in 09eee7f79b0f9478c27e44b7065bfff7aefc2ef6 to avoid quadratic behavior. We then loosened this in b3d99be2471f0587bc922f9c0d141fb754a7332c to continue contextually typing containers like lists, so in many cases we will succeed with contextual typing.

We should support contextual typing for _all_ contextually sensitive expressions in an overloaded call, including nested function calls, comprehensions, walrus, if/else expressions, etc. But we need to be careful to enable this without introducing unacceptable worst-case performance.

Suggestions:
* Identify contextually-insensitive expressions before calls, infer types for them just once
* Optimize overload selection to filter out overloads based on signature mismatch, before trying types
* Limit contextual typing to some fixed depth, to avoid worst case time when the above strategies don't apply

```
from typing import overload

class A: ...
class B(A): ...

@overload
def foo[T](xs: list[T]) -> list[T]: ...
@overload
def foo[T](xs: set[T]) -> set[T]: ...
def foo[T](xs: list[T] | set[T]) -> list[T] | set[T]:
return xs

x1: list[A] = foo([B()]) # should suceed
x2: list[A] = foo(foo([B()])) # should succeed
```

### Sandbox Link

_No response_

### (Only applicable for extension issues) IDE Information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.