Skip to content

Commit a2e010d

Browse files
Michael0x2aJukkaL
authored andcommitted
Preserve can_be_true and can_be_false when copying types (python#7991)
This pull request modifies the `last_known_value` eraser so it always copies over the previously inferred value of the `can_be_true` and `can_be_false` fields. This isn't entirely typesafe -- for example, we can sometimes accidentally infer the wrong result if we try reassigning variables or call a mutating function : ``` def bad1(a: List[str], b: bool) -> bool: x = a and b a = ["foo"] y: bool return x or y # Should be an error def bad2(a: List[str], b: bool) -> bool: x = a and b a.append("foo") y: bool return x or y # Should be an error ``` But this was apparently the old behavior/something mypy wasn't previously able to detect, so I guess this is fine for now. I also decided against modifying every `copy_modified` method in all the type classes because of this reason: I wanted to limit the spread of this potentially misleading additional inferred info. Fixes python#7986, probably.
1 parent 989626a commit a2e010d

File tree

2 files changed

+13
-1
lines changed

2 files changed

+13
-1
lines changed

mypy/erasetype.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,13 @@ class LastKnownValueEraser(TypeTranslator):
142142
def visit_instance(self, t: Instance) -> Type:
143143
if not t.last_known_value and not t.args:
144144
return t
145-
return t.copy_modified(
145+
new_t = t.copy_modified(
146146
args=[a.accept(self) for a in t.args],
147147
last_known_value=None,
148148
)
149+
new_t.can_be_true = t.can_be_true
150+
new_t.can_be_false = t.can_be_false
151+
return new_t
149152

150153
def visit_type_alias_type(self, t: TypeAliasType) -> Type:
151154
# Type aliases can't contain literal values, because they are

test-data/unit/check-expressions.test

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,15 @@ b = bool()
343343
reveal_type(s and b or b) # N: Revealed type is 'builtins.bool'
344344
[builtins fixtures/bool.pyi]
345345

346+
[case testRestrictedBoolAndOrWithGenerics]
347+
from typing import List
348+
349+
def f(a: List[str], b: bool) -> bool:
350+
x = a and b
351+
y: bool
352+
return reveal_type(x or y) # N: Revealed type is 'builtins.bool'
353+
[builtins fixtures/list.pyi]
354+
346355
[case testNonBooleanOr]
347356
c, d, b = None, None, None # type: (C, D, bool)
348357
if int():

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy