Skip to content

T & <protocol with members 'x'> should not simplify to T if T.x is possibly unbound #578

@AlexWaygood

Description

@AlexWaygood

Summary

Consider the following snippet:

def b() -> bool:
    return False

class Foo:
    if b():
        x: int = 42

def f(y: Foo):
    if hasattr(y, "x"):
        reveal_type(y)  # revealed: Foo
        print(y.x)  # error[possibly-unbound-attribute]: Attribute `x` on type `Foo` is possibly unbound

https://play.ty.dev/4171e13d-f9e5-432d-baa9-fc25f414647e

In the hasattr() branch, we narrow the type of y to Foo & <protocol with members 'x'>, but then immediately simplify that intersection to Foo, since we know that all Foo members have an x member. But this simplification is incorrect, because it causes us to then emit a false positive when attempting to access the x member: we report the attribute as possibly unbound, even though the user just checked that it isn't!

We should only simplify these synthesized-protocol intersections if another element in the intersection has a definitely bound attribute of the relevant name.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions