Skip to content

Commit 3cd64fc

Browse files
committed
wip
1 parent 6423ef7 commit 3cd64fc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+303
-239
lines changed

.idea/watcherTasks.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mypy/binder.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ def assign_type(
311311
) -> None:
312312
# We should erase last known value in binder, because if we are using it,
313313
# it means that the target is not final, and therefore can't hold a literal.
314-
if not mypy.options._based:
315-
type = remove_instance_last_known_values(type)
314+
# HUUHHH?????
315+
# type = remove_instance_last_known_values(type)
316316

317317
if self.type_assignments is not None:
318318
# We are in a multiassign from union, defer the actual binding,

mypy/checker.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3514,12 +3514,7 @@ def check_assignment(
35143514
if not (isinstance(lvalue, NameExpr) and lvalue.is_special_form):
35153515
self.binder.assign_type(lvalue, rvalue_type, lvalue_type, False)
35163516

3517-
elif (
3518-
not mypy.options._based
3519-
and lvalue.node
3520-
and lvalue.node.is_inferred
3521-
and rvalue_type
3522-
):
3517+
elif lvalue.node and lvalue.node.is_inferred and rvalue_type:
35233518
# for literal values
35243519
# Don't use type binder for definitions of special forms, like named tuples.
35253520
if not (isinstance(lvalue, NameExpr) and lvalue.is_special_form):
@@ -3531,14 +3526,16 @@ def check_assignment(
35313526
if inferred:
35323527
type_context = self.get_variable_type_context(inferred)
35333528
rvalue_type = self.expr_checker.accept(rvalue, type_context=type_context)
3534-
if not mypy.options._based and not isinstance(lvalue.node.type, PartialType):
3535-
self.binder.assign_type(lvalue, rvalue_type, rvalue_type, False)
3529+
original_rvalue_type = rvalue_type
35363530
if not (
35373531
inferred.is_final
35383532
or (isinstance(lvalue, NameExpr) and lvalue.name == "__match_args__")
35393533
):
35403534
rvalue_type = remove_instance_last_known_values(rvalue_type)
3541-
self.infer_variable_type(inferred, lvalue, rvalue_type, rvalue)
3535+
if self.infer_variable_type(inferred, lvalue, rvalue_type, rvalue):
3536+
self.binder.assign_type(
3537+
lvalue, original_rvalue_type, original_rvalue_type, False
3538+
)
35423539

35433540
self.check_assignment_to_slots(lvalue)
35443541

@@ -4491,12 +4488,13 @@ def is_definition(self, s: Lvalue) -> bool:
44914488

44924489
def infer_variable_type(
44934490
self, name: Var, lvalue: Lvalue, init_type: Type, context: Context
4494-
) -> None:
4491+
) -> bool:
44954492
"""Infer the type of initialized variables from initializer type."""
4493+
valid = True
44964494
if isinstance(init_type, DeletedType):
44974495
self.msg.deleted_as_rvalue(init_type, context)
44984496
elif (
4499-
not is_valid_inferred_type(init_type, is_lvalue_final=name.is_final)
4497+
not (valid := is_valid_inferred_type(init_type, is_lvalue_final=name.is_final))
45004498
and not self.no_partial_types
45014499
):
45024500
# We cannot use the type of the initialization expression for full type
@@ -4523,6 +4521,7 @@ def infer_variable_type(
45234521
init_type = strip_type(init_type)
45244522

45254523
self.set_inferred_type(name, lvalue, init_type)
4524+
return valid
45264525

45274526
def infer_partial_type(self, name: Var, lvalue: Lvalue, init_type: Type) -> bool:
45284527
init_type = get_proper_type(init_type)

mypy/checkexpr.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3677,10 +3677,14 @@ def visit_bytes_expr(self, e: BytesExpr) -> Type:
36773677

36783678
def visit_float_expr(self, e: FloatExpr) -> Type:
36793679
"""Type check a float literal (trivial)."""
3680+
if mypy.options._based:
3681+
return self.infer_literal_expr_type(e.value, "builtins.float")
36803682
return self.named_type("builtins.float")
36813683

36823684
def visit_complex_expr(self, e: ComplexExpr) -> Type:
36833685
"""Type check a complex literal."""
3686+
if mypy.options._based:
3687+
return self.infer_literal_expr_type(e.value, "builtins.complex")
36843688
return self.named_type("builtins.complex")
36853689

36863690
def visit_ellipsis(self, e: EllipsisExpr) -> Type:

mypy/expandtype.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from contextlib import contextmanager
34
from typing import Final, Iterable, Mapping, Sequence, TypeVar, cast, overload
45

56
from mypy.nodes import ARG_STAR, FakeInfo, Var
@@ -185,6 +186,16 @@ def __init__(self, variables: Mapping[TypeVarId, Type]) -> None:
185186
super().__init__()
186187
self.variables = variables
187188
self.recursive_tvar_guard: dict[TypeVarId, Type | None] = {}
189+
self._erase_literals = False
190+
191+
@contextmanager
192+
def erase_literals(self):
193+
_erase_literals = self._erase_literals
194+
self._erase_literals = True
195+
try:
196+
yield
197+
finally:
198+
self._erase_literals = _erase_literals
188199

189200
def visit_unbound_type(self, t: UnboundType) -> Type:
190201
return t
@@ -211,7 +222,8 @@ def visit_erased_type(self, t: ErasedType) -> Type:
211222
return t
212223

213224
def visit_instance(self, t: Instance) -> Type:
214-
args = self.expand_types_with_unpack(list(t.args))
225+
with self.erase_literals():
226+
args = self.expand_types_with_unpack(list(t.args))
215227

216228
if isinstance(t.type, FakeInfo):
217229
# The type checker expands function definitions and bodies
@@ -238,7 +250,7 @@ def visit_type_var(self, t: TypeVarType) -> Type:
238250
if t.id.is_self():
239251
t = t.copy_modified(upper_bound=t.upper_bound.accept(self))
240252
repl = self.variables.get(t.id, t)
241-
if not mypy.options._based and isinstance(repl, ProperType) and isinstance(repl, Instance):
253+
if self._erase_literals and isinstance(repl, ProperType) and isinstance(repl, Instance):
242254
# TODO: do we really need to do this?
243255
# If I try to remove this special-casing ~40 tests fail on reveal_type().
244256
return repl.copy_modified(last_known_value=None)
@@ -410,17 +422,18 @@ def visit_callable_type(self, t: CallableType) -> CallableType:
410422

411423
var_arg = t.var_arg()
412424
needs_normalization = False
413-
if var_arg is not None and isinstance(var_arg.typ, UnpackType):
414-
needs_normalization = True
415-
arg_types = self.interpolate_args_for_unpack(t, var_arg.typ)
416-
else:
417-
arg_types = self.expand_types(t.arg_types)
418-
expanded = t.copy_modified(
419-
arg_types=arg_types,
420-
ret_type=t.ret_type.accept(self),
421-
type_guard=t.type_guard and cast(TypeGuardType, t.type_guard.accept(self)),
422-
type_is=(t.type_is.accept(self) if t.type_is is not None else None),
423-
)
425+
with self.erase_literals():
426+
if var_arg is not None and isinstance(var_arg.typ, UnpackType):
427+
needs_normalization = True
428+
arg_types = self.interpolate_args_for_unpack(t, var_arg.typ)
429+
else:
430+
arg_types = self.expand_types(t.arg_types)
431+
expanded = t.copy_modified(
432+
arg_types=arg_types,
433+
ret_type=t.ret_type.accept(self),
434+
type_guard=t.type_guard and cast(TypeGuardType, t.type_guard.accept(self)),
435+
type_is=(t.type_is.accept(self) if t.type_is is not None else None),
436+
)
424437
if needs_normalization:
425438
return expanded.with_normalized_var_args()
426439
return expanded

mypy/join.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
is_protocol_implementation,
1919
is_subtype,
2020
)
21+
from mypy.typeops import make_simplified_union
2122
from mypy.types import (
2223
AnyType,
2324
CallableType,
@@ -232,7 +233,7 @@ def join_simple(declaration: Type | None, s: Type, t: Type) -> ProperType:
232233
if declaration is None or is_subtype(value, declaration):
233234
return value
234235

235-
return declaration
236+
return value
236237

237238

238239
def trivial_join(s: Type, t: Type) -> Type:

mypy/meet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type:
197197
# Special case: 'int' can't be narrowed down to a native int type such as
198198
# i64, since they have different runtime representations.
199199
return original_declared
200-
if mypy.options._based and isinstance(narrowed, Instance) and narrowed.last_known_value:
200+
if isinstance(narrowed, Instance) and narrowed.last_known_value:
201201
return narrowed
202202
return meet_types(original_declared, original_narrowed)
203203
elif isinstance(declared, (TupleType, TypeType, LiteralType)):

mypy/types.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,6 @@ def __init__(
633633
column: int = -1,
634634
scopename: str | None = None,
635635
) -> None:
636-
print(f"{fullname} {id}")
637636
super().__init__(name, fullname, id, upper_bound, default, line, column)
638637
assert values is not None, "No restrictions must be represented by empty list"
639638
self.values = values

mypy/typeshed/stdlib/builtins.pyi

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,6 @@ class int:
388388
def __abs__(self) -> int: ...
389389
@type_function
390390
def __hash__(self) -> int: ...
391-
@overload
392-
def __bool__(self: 0) -> False: ...
393-
@overload
394391
def __bool__(self) -> bool: ...
395392
@type_function
396393
def __index__(self) -> int: ...
@@ -501,9 +498,6 @@ class float:
501498
def __abs__(self) -> float: ...
502499
@type_function
503500
def __hash__(self) -> int: ...
504-
@overload
505-
def __bool__(self: 0.0) -> False: ...
506-
@overload
507501
def __bool__(self) -> bool: ...
508502

509503
class complex:
@@ -537,9 +531,6 @@ class complex:
537531
def __pos__(self) -> complex: ...
538532
def __abs__(self) -> float: ...
539533
def __hash__(self) -> int: ...
540-
# @overload
541-
# def __bool__(self: 0j) -> False: ...
542-
# @overload
543534
def __bool__(self) -> bool: ...
544535
if sys.version_info >= (3, 11):
545536
def __complex__(self) -> complex: ...
@@ -687,9 +678,6 @@ class str(Sequence[str]):
687678
def __ne__(self, value: object, /) -> bool: ...
688679
def __rmul__(self, value: SupportsIndex, /) -> str: ... # type: ignore[misc]
689680
def __getnewargs__(self) -> tuple[str]: ...
690-
@overload
691-
def __bool__(self: Literal[""]) -> False: ...
692-
@overload
693681
def __bool__(self) -> bool: ...
694682

695683
class bytes(Sequence[int]):
@@ -840,9 +828,6 @@ class bytes(Sequence[int]):
840828
@type_function
841829
def __ge__(self, value: bytes, /) -> bool: ...
842830
def __getnewargs__(self) -> tuple[bytes]: ...
843-
@overload
844-
def __bool__(self: Literal[b""]) -> False: ...
845-
@overload
846831
def __bool__(self) -> bool: ...
847832
if sys.version_info >= (3, 11):
848833
@type_function
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[case narrowToLiteral]
1+
[case testNarrowToLiteral]
22
a = "a"
33
reveal_type(a) # Revealed type is "'a'" (narrowed from "str")
44
a = "b"
@@ -7,3 +7,11 @@ b = a
77
reveal_type(b) # Revealed type is "'b'" (narrowed from "str")
88
b = "c"
99
reveal_type(b) # Revealed type is "'c'" (narrowed from "str")
10+
11+
12+
[case testNarrowToLiteralGeneric]
13+
from helper import T
14+
def f(t: T) -> T: ...
15+
16+
a = f(1)
17+
reveal_type(a) # revealed type is "1" (narrowed from "int")

test-data/unit/check-based-bare-literals.test

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,21 @@ reveal_type(c) # N: Revealed type is "False"
1818
c2: False | str
1919
reveal_type(c2) # N: Revealed type is "False | str"
2020

21-
d: 1.1 # E: Invalid type: float literals cannot be used as a type [valid-type]
22-
d2: 1.1 | str # E: Invalid type: float literals cannot be used as a type [valid-type]
23-
24-
e: 1j # E: Invalid type: complex literals cannot be used as a type [valid-type]
25-
e2: 1j | str # E: Invalid type: complex literals cannot be used as a type [valid-type]
21+
d: 1.1
22+
reveal_type(d) # N: Revealed type is "1.1"
23+
d2: 1.1 | str
24+
reveal_type(d2) # N: Revealed type is "1.1 | str"
2625
[builtins fixtures/tuple.pyi]
2726

2827

28+
[case testBareLiteralLiteralsComplex]
29+
e: 1j
30+
reveal_type(e) # N: Revealed type is "1j"
31+
e2: 1j | str
32+
reveal_type(e2) # N: Revealed type is "1j | str"
33+
[builtins fixtures/dict.pyi]
34+
35+
2936
[case testNoBareLiteralLiterals]
3037
# flags: --python-version 3.10
3138

@@ -109,3 +116,7 @@ import a
109116
from typing import TypeVar
110117
T = TypeVar("T", 1, 2)
111118
a: 1 | 2
119+
120+
121+
[case testBareLiteralComplex-writescache]
122+
a: 1j

test-data/unit/check-based-misc.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ main:3:5:3:31: error: Unused "type: ignore" comment [unused-ignore]
2525

2626
[case testNarrowOnInitialAssignment]
2727
a: object = 1
28-
reveal_type(a) # N: Revealed type is "int" (narrowed from "object")
28+
reveal_type(a) # N: Revealed type is "1" (narrowed from "object")
2929

3030

3131
[case testNarrowWithAny]
@@ -35,7 +35,7 @@ from typing import Any, Union
3535
a: Union[int, Any]
3636
if bool():
3737
a = 1
38-
reveal_type(a) # N: Revealed type is "int" (narrowed from "int | Any")
38+
reveal_type(a) # N: Revealed type is "1" (narrowed from "int | Any")
3939
b: Any = 1
4040
reveal_type(b) # N: Revealed type is "Any"
4141
c: Any
@@ -199,7 +199,7 @@ a = False
199199
b: object
200200
if a:
201201
b = 1
202-
reveal_type(b) # N: Revealed type is "int" (narrowed from "object")
202+
reveal_type(b) # N: Revealed type is "1" (narrowed from "object")
203203

204204

205205
[case testRedundantExprOnWhileTrue]

test-data/unit/check-based-type-function.test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class int:
2020
def m(self, other: "int") -> "int":
2121
return self + 1
2222

23+
class dict: ...
24+
2325

2426
[case typeFunctionReportError]
2527
from basedtyping import type_function, TypeFunctionError
@@ -36,6 +38,7 @@ def main():
3638
F(False)
3739
reveal_type(F(True)) # E: this is an error [the-code] \
3840
# N: Revealed type is "Never"
41+
[builtins fixtures/exception.pyi]
3942

4043

4144
[case typeFunctionReportRaises]
@@ -50,3 +53,4 @@ def main():
5053
F(False)
5154
reveal_type(F(True)) # E: Invocation raises TypeError: this is an error [call-raises] \
5255
# N: Revealed type is "Never"
56+
[builtins fixtures/exception.pyi]

test-data/unit/check-based-type-render.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ a = 1 # E: Incompatible types in assignment (expression has type "int", variabl
9797
[case testNarrowedFrom]
9898
a: object
9999
a = 1
100-
reveal_type(a) # N: Revealed type is "int" (narrowed from "object")
100+
reveal_type(a) # N: Revealed type is "1" (narrowed from "object")
101101

102102

103103
[case testNarrowedFromClass]

test-data/unit/check-based-typevar.test

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,39 @@ class A(Generic[T]): ...
4747

4848
a = A[Any]() # E: Expression type contains "Any" (has type "A[Any]") [no-any-expr]
4949
[builtins fixtures/tuple.pyi]
50+
51+
52+
[case testInferLiteralGeneric]
53+
def f0[T](t: T) -> T:
54+
return t
55+
56+
57+
reveal_type(f0(17)) # N: Revealed type is "17"
58+
59+
60+
def f1[T](t: T) -> (list[T],):
61+
return ([t],)
62+
63+
64+
reveal_type(f1(17)) # N: Revealed type is "(list[int])"
65+
66+
67+
def f2[T](t: T) -> (T,):
68+
return (t,)
69+
70+
71+
reveal_type(f2(17)) # N: Revealed type is "(17)"
72+
73+
74+
def f3[T](t: T) -> list[T]:
75+
return [t]
76+
77+
78+
reveal_type(f3(17)) # N: Revealed type is "list[int]"
79+
80+
81+
def f4[T](t: T) -> (T, list[T]):
82+
return [t]
83+
84+
# maybe this should be: (int, list[int])
85+
reveal_type(f4(17)) # N: Revealed type is "(1, list[int])"

0 commit comments

Comments
 (0)