Skip to content

Unexpected conditional expression type inference change #7986

Closed

Description

@JukkaL

#7955 caused this example to start generating type errors:

from typing import List, Union

def g(a: List[str], b: bool) -> bool:
    x = a and b
    y: bool
    return x or y  # Incompatible return value type (got "Union[List[str], bool]", expected "bool")

Previously, this generated no errors. It's unclear whether this fixed a false negative or whether this is a regression.

@Michael0x2a Do you have an idea of what might be going on?

Activity

  1. ilevkivskyi commented on Nov 20, 2019

    @ilevkivskyi
    Member

    I would say this is rather a bug (I am however not sure whether it previously worked on purpose or by coincidence).

    I think the inferred type of x should be like UnionType(Instance('list', can_be_true=False), Instance('bool')), and then the or in return statement should eliminate the false-only items from union.

  2. JukkaL commented on Nov 20, 2019

    @JukkaL
    CollaboratorAuthor

    Just to be clear: the new behavior is a bug, or the old behavior is a bug?

  3. Michael0x2a commented on Nov 20, 2019

    @Michael0x2a
    Collaborator

    The only thing I can think of is the changes to LastKnownValueEraser.visit_instance: now that we try erasing types if there are any args, that visitor will end up calling Instance.copy_modified more frequently -- and it doesn't seem that copy method actually preserves the can_be_true or can_be_false fields.

    I'm not 100% sure, but I feel the new behavior is probably a bug? I tried playing around with the example function, and I could never get it to return a list, so a inferred return type of bool is probably want we want.

    But maybe the deeper bug is that there's a discrepancy between how we handle last_known_value and can_be_true and can_be_false? It seems we want to erase the latter less aggressively -- so this would probably be yet another binder/"it would be nice if we had a more sophisticated abstract interpreter" issue?

  4. ilevkivskyi commented on Nov 20, 2019

    @ilevkivskyi
    Member

    Just to be clear: the new behavior is a bug, or the old behavior is a bug?

    IMO the new behaviour is a false positive.

  5. ilevkivskyi commented on Nov 20, 2019

    @ilevkivskyi
    Member

    @Michael0x2a

    so this would probably be yet another binder/"it would be nice if we had a more sophisticated abstract interpreter" issue?

    I think there is a chance a pretty simple fix exists. Will you have time to look into preserving can_be_true and can_be_false in Instance.copy_modified()? If not, I can look into this tomorrow.

  6. Michael0x2a commented on Nov 20, 2019

    @Michael0x2a
    Collaborator

    Sure, I can take a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions