Skip to content

Commit 172578d

Browse files
Merge remote-tracking branch 'upstream/master' into fix-dict-unpacking-20706
2 parents 6e9f1e4 + 6fa04e4 commit 172578d

19 files changed

Lines changed: 412 additions & 57 deletions

mypy/checker.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4470,6 +4470,14 @@ def infer_variable_type(
44704470
is_lvalue_final=name.is_final,
44714471
is_lvalue_member=isinstance(lvalue, MemberExpr),
44724472
)
4473+
and not (
4474+
# Trust None assignments to dunder methods
4475+
# This is a bit ad-hoc, but it improves protocol
4476+
# (non-)assignability, for instance `__hash__ = None`
4477+
self.scope.active_class()
4478+
and is_dunder(name.name)
4479+
and isinstance(get_proper_type(init_type), NoneType)
4480+
)
44734481
and not self.no_partial_types
44744482
):
44754483
# We cannot use the type of the initialization expression for full type
@@ -8637,7 +8645,6 @@ def reduce_and_conditional_type_maps(ms: list[TypeMap], *, use_meet: bool) -> Ty
86378645

86388646

86398647
BUILTINS_CUSTOM_EQ_CHECKS: Final = {
8640-
"builtins.bytes",
86418648
"builtins.bytearray",
86428649
"builtins.memoryview",
86438650
"builtins.list",

mypyc/analysis/dataflow.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
FloatNeg,
2525
FloatOp,
2626
GetAttr,
27+
GetElement,
2728
GetElementPtr,
2829
Goto,
2930
IncRef,
@@ -271,6 +272,9 @@ def visit_float_comparison_op(self, op: FloatComparisonOp) -> GenAndKill[T]:
271272
def visit_load_mem(self, op: LoadMem) -> GenAndKill[T]:
272273
return self.visit_register_op(op)
273274

275+
def visit_get_element(self, op: GetElement) -> GenAndKill[T]:
276+
return self.visit_register_op(op)
277+
274278
def visit_get_element_ptr(self, op: GetElementPtr) -> GenAndKill[T]:
275279
return self.visit_register_op(op)
276280

mypyc/analysis/ircheck.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
FloatNeg,
2323
FloatOp,
2424
GetAttr,
25+
GetElement,
2526
GetElementPtr,
2627
Goto,
2728
IncRef,
@@ -449,6 +450,9 @@ def visit_load_mem(self, op: LoadMem) -> None:
449450
def visit_set_mem(self, op: SetMem) -> None:
450451
pass
451452

453+
def visit_get_element(self, op: GetElement) -> None:
454+
pass
455+
452456
def visit_get_element_ptr(self, op: GetElementPtr) -> None:
453457
pass
454458

mypyc/analysis/selfleaks.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
FloatNeg,
1717
FloatOp,
1818
GetAttr,
19+
GetElement,
1920
GetElementPtr,
2021
Goto,
2122
InitStatic,
@@ -179,6 +180,9 @@ def visit_float_comparison_op(self, op: FloatComparisonOp) -> GenAndKill:
179180
def visit_load_mem(self, op: LoadMem) -> GenAndKill:
180181
return CLEAN
181182

183+
def visit_get_element(self, op: GetElement) -> GenAndKill:
184+
return CLEAN
185+
182186
def visit_get_element_ptr(self, op: GetElementPtr) -> GenAndKill:
183187
return CLEAN
184188

mypyc/codegen/emitfunc.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
FloatNeg,
4343
FloatOp,
4444
GetAttr,
45+
GetElement,
4546
GetElementPtr,
4647
Goto,
4748
IncRef,
@@ -795,6 +796,12 @@ def visit_set_mem(self, op: SetMem) -> None:
795796
if dest != src:
796797
self.emit_line(f"*({dest_type} *){dest} = {src};")
797798

799+
def visit_get_element(self, op: GetElement) -> None:
800+
dest = self.reg(op)
801+
src = self.reg(op.src)
802+
dest_type = self.ctype(op.type)
803+
self.emit_line(f"{dest} = ({dest_type}){src}.{op.field};")
804+
798805
def visit_get_element_ptr(self, op: GetElementPtr) -> None:
799806
dest = self.reg(op)
800807
src = self.reg(op.src)

mypyc/ir/ops.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ def set_sources(self, new: list[Value]) -> None:
337337
(self.src,) = new
338338

339339
def stolen(self) -> list[Value]:
340+
if not self.dest.type.is_refcounted:
341+
return []
340342
return [self.src]
341343

342344
def accept(self, visitor: OpVisitor[T]) -> T:
@@ -1679,9 +1681,36 @@ def accept(self, visitor: OpVisitor[T]) -> T:
16791681
return visitor.visit_set_mem(self)
16801682

16811683

1684+
@final
1685+
class GetElement(RegisterOp):
1686+
"""Get the value of a struct element from a struct value."""
1687+
1688+
error_kind = ERR_NEVER
1689+
is_borrowed = True
1690+
1691+
def __init__(self, src: Value, field: str, line: int = -1) -> None:
1692+
super().__init__(line)
1693+
assert isinstance(src.type, RStruct)
1694+
self.type = src.type.field_type(field)
1695+
self.src = src
1696+
self.src_type = src.type
1697+
self.field = field
1698+
1699+
def sources(self) -> list[Value]:
1700+
return [self.src]
1701+
1702+
def set_sources(self, new: list[Value]) -> None:
1703+
(self.src,) = new
1704+
1705+
def accept(self, visitor: OpVisitor[T]) -> T:
1706+
return visitor.visit_get_element(self)
1707+
1708+
16821709
@final
16831710
class GetElementPtr(RegisterOp):
1684-
"""Get the address of a struct element.
1711+
"""Get the address of a struct element from a pointer to a struct.
1712+
1713+
If you have a struct value, use GetElement instead.
16851714
16861715
Note that you may need to use KeepAlive to avoid the struct
16871716
being freed, if it's reference counted, such as PyObject *.
@@ -1691,6 +1720,7 @@ class GetElementPtr(RegisterOp):
16911720

16921721
def __init__(self, src: Value, src_type: RType, field: str, line: int = -1) -> None:
16931722
super().__init__(line)
1723+
assert not isinstance(src.type, RStruct)
16941724
self.type = pointer_rprimitive
16951725
self.src = src
16961726
self.src_type = src_type
@@ -2008,6 +2038,10 @@ def visit_load_mem(self, op: LoadMem) -> T:
20082038
def visit_set_mem(self, op: SetMem) -> T:
20092039
raise NotImplementedError
20102040

2041+
@abstractmethod
2042+
def visit_get_element(self, op: GetElement) -> T:
2043+
raise NotImplementedError
2044+
20112045
@abstractmethod
20122046
def visit_get_element_ptr(self, op: GetElementPtr) -> T:
20132047
raise NotImplementedError

mypyc/ir/pprint.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
FloatNeg,
3030
FloatOp,
3131
GetAttr,
32+
GetElement,
3233
GetElementPtr,
3334
Goto,
3435
IncRef,
@@ -280,6 +281,9 @@ def visit_load_mem(self, op: LoadMem) -> str:
280281
def visit_set_mem(self, op: SetMem) -> str:
281282
return self.format("set_mem %r, %r :: %t*", op.dest, op.src, op.dest_type)
282283

284+
def visit_get_element(self, op: GetElement) -> str:
285+
return self.format("%r = %r.%s", op, op.src, op.field)
286+
283287
def visit_get_element_ptr(self, op: GetElementPtr) -> str:
284288
return self.format("%r = get_element_ptr %r %s :: %t", op, op.src, op.field, op.src_type)
285289

mypyc/ir/rtypes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,13 +865,21 @@ def __init__(self, name: str, names: list[str], types: list[RType]) -> None:
865865
self.name = name
866866
self.names = names
867867
self.types = types
868+
self.is_refcounted = any(t.is_refcounted for t in self.types)
869+
868870
# generate dummy names
869871
if len(self.names) < len(self.types):
870872
for i in range(len(self.types) - len(self.names)):
871873
self.names.append("_item" + str(i))
872874
self.offsets, self.size = compute_aligned_offsets_and_size(types)
873875
self._ctype = name
874876

877+
def field_type(self, name: str) -> RType:
878+
for n, t in zip(self.names, self.types):
879+
if n == name:
880+
return t
881+
assert False, f"{self.name} has no field '{name}'"
882+
875883
def accept(self, visitor: RTypeVisitor[T]) -> T:
876884
return visitor.visit_rstruct(self)
877885

0 commit comments

Comments
 (0)