From eb5a54f16f04a6005b558ae086fbd43d97c7e2a7 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 01/18] [mypyc] feat: unwrap NewType types to their base types for optimized code paths --- mypyc/irbuild/mapper.py | 4 ++ mypyc/test-data/irbuild-str.test | 77 +++++++++++++++++++++++--------- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index 4a01255e2d5d..a60e7aa99bd3 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -73,6 +73,10 @@ def type_to_rtype(self, typ: Type | None) -> RType: typ = get_proper_type(typ) if isinstance(typ, Instance): + if typ.type.is_newtype: + # Unwrap NewType to its base type for rprimitive mapping + base_typeinfo = typ.type.bases[0].type + return self.type_to_rtype(Instance(base_typeinfo, [])) if typ.type.fullname == "builtins.int": return int_rprimitive elif typ.type.fullname == "builtins.float": diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index 4a4992d41a5d..bafab8f8133d 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -1,13 +1,15 @@ [case testStrSplit] -from typing import Optional, List +from typing import NewType, Optional, List, Union +NewStr = NewType("NewStr", str) -def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]: +def do_split(s: Union[str, NewStr], sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]: if sep is not None: if max_split is not None: return s.split(sep, max_split) else: return s.split(sep) return s.split() +[typing fixtures/typing-full.pyi] [out] def do_split(s, sep, max_split): s :: str @@ -56,12 +58,15 @@ L9: [case testStrEquality] +from typing import NewType, Union +NewStr = NewType("NewStr", str) def eq(x: str, y: str) -> bool: return x == y -def neq(x: str, y: str) -> bool: +def neq(x: str, y: Union[str, NewStr]) -> bool: return x != y +[typing fixtures/typing-full.pyi] [out] def eq(x, y): x, y :: str @@ -79,13 +84,14 @@ L0: return r1 [case testStrReplace] -from typing import Optional - -def do_replace(s: str, old_substr: str, new_substr: str, max_count: Optional[int] = None) -> str: +from typing import NewType, Optional, Union +NewStr = NewType("NewStr", str) +def do_replace(s: Union[str, NewStr], old_substr: str, new_substr: str, max_count: Optional[int] = None) -> str: if max_count is not None: return s.replace(old_substr, new_substr, max_count) else: return s.replace(old_substr, new_substr) +[typing fixtures/typing-full.pyi] [out] def do_replace(s, old_substr, new_substr, max_count): s, old_substr, new_substr :: str @@ -114,17 +120,19 @@ L5: unreachable [case testStrStartswithEndswithTuple] -from typing import Tuple +from typing import NewType, Tuple, Union +NewStr = NewType("NewStr", str) -def do_startswith(s1: str, s2: Tuple[str, ...]) -> bool: +def do_startswith(s1: Union[str, NewStr], s2: Tuple[str, ...]) -> bool: return s1.startswith(s2) -def do_endswith(s1: str, s2: Tuple[str, ...]) -> bool: +def do_endswith(s1: Union[str, NewStr], s2: Tuple[str, ...]) -> bool: return s1.endswith(s2) -def do_tuple_literal_args(s1: str) -> None: +def do_tuple_literal_args(s1: Union[str, NewStr]) -> None: x = s1.startswith(("a", "b")) y = s1.endswith(("a", "b")) +[typing fixtures/typing-full.pyi] [out] def do_startswith(s1, s2): s1 :: str @@ -165,11 +173,14 @@ L0: return 1 [case testStrToBool] -def is_true(x: str) -> bool: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def is_true(x: Union[str, NewStr]) -> bool: if x: return True else: return False +[typing fixtures/typing-full.pyi] [out] def is_true(x): x :: str @@ -185,11 +196,14 @@ L3: unreachable [case testStringFormatMethod] -def f(s: str, num: int) -> None: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def f(s: Union[str, NewStr], num: int) -> None: s1 = "Hi! I'm {}, and I'm {} years old.".format(s, num) s2 = ''.format() s3 = 'abc'.format() s4 = '}}{}{{{}}}{{{}'.format(num, num, num) +[typing fixtures/typing-full.pyi] [out] def f(s, num): s :: str @@ -217,11 +231,14 @@ L0: return 1 [case testFStrings_64bit] -def f(var: str, num: int) -> None: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def f(var: Union[str, NewStr], num: int) -> None: s1 = f"Hi! I'm {var}. I am {num} years old." s2 = f'Hello {var:>{num}}' s3 = f'' s4 = f'abc' +[typing fixtures/typing-full.pyi] [out] def f(var, num): var :: str @@ -267,7 +284,9 @@ L0: return 1 [case testStringFormattingCStyle] -def f(var: str, num: int) -> None: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def f(var: Union[str, NewStr], num: int) -> None: s1 = "Hi! I'm %s." % var s2 = "I am %d years old." % num s3 = "Hi! I'm %s. I am %d years old." % (var, num) @@ -322,7 +341,9 @@ L0: return 1 [case testEncode_64bit] -def f(s: str) -> None: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def f(s: Union[str, NewStr]) -> None: s.encode() s.encode('utf-8') s.encode('utf8', 'strict') @@ -340,6 +361,7 @@ def f(s: str) -> None: s.encode(encoding=encoding, errors=errors) s.encode('latin2') +[typing fixtures/typing-full.pyi] [out] def f(s): s :: str @@ -410,7 +432,9 @@ L0: return 1 [case testOrd] -def str_ord(x: str) -> int: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def str_ord(x: Union[str, NewStr]) -> int: return ord(x) def str_ord_literal() -> int: return ord("a") @@ -420,6 +444,7 @@ def bytes_ord_literal() -> int: return ord(b"a") def any_ord(x) -> int: return ord(x) +[typing fixtures/typing-full.pyi] [out] def str_ord(x): x :: str @@ -459,13 +484,16 @@ L0: return r6 [case testStrip] -def do_strip(s: str) -> None: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def do_strip(s: Union[str, NewStr]) -> None: s.lstrip("x") s.strip("y") s.rstrip("z") s.lstrip() s.strip() s.rstrip() +[typing fixtures/typing-full.pyi] [out] def do_strip(s): s, r0, r1, r2, r3, r4, r5, r6, r7, r8 :: str @@ -482,8 +510,11 @@ L0: return 1 [case testCountAll] -def do_count(s: str) -> int: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def do_count(s: Union[str, NewStr]) -> int: return s.count("x") # type: ignore [attr-defined] +[typing fixtures/typing-full.pyi] [out] def do_count(s): s, r0 :: str @@ -500,8 +531,11 @@ L0: return r4 [case testCountStart] -def do_count(s: str, start: int) -> int: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def do_count(s: Union[str, NewStr], start: int) -> int: return s.count("x", start) # type: ignore [attr-defined] +[typing fixtures/typing-full.pyi] [out] def do_count(s, start): s :: str @@ -520,8 +554,11 @@ L0: return r4 [case testCountStartEnd] -def do_count(s: str, start: int, end: int) -> int: +from typing import NewType, Union +NewStr = NewType("NewStr", str) +def do_count(s: Union[str, NewStr], start: int, end: int) -> int: return s.count("x", start, end) # type: ignore [attr-defined] +[typing fixtures/typing-full.pyi] [out] def do_count(s, start, end): s :: str From aea121dc32fecf5d5cdc7d83e0a0917a187283cd Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 02/18] Update mapper.py --- mypyc/irbuild/mapper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index a60e7aa99bd3..528fa3605b84 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -73,7 +73,8 @@ def type_to_rtype(self, typ: Type | None) -> RType: typ = get_proper_type(typ) if isinstance(typ, Instance): - if typ.type.is_newtype: + if typ.type.is_newtype and len(typ.type.bases) == 1: + # I'm pretty sure this length check always returns True but am not positive and False would break things # Unwrap NewType to its base type for rprimitive mapping base_typeinfo = typ.type.bases[0].type return self.type_to_rtype(Instance(base_typeinfo, [])) From 7f74980262b561764d55e3c4a6e75c908044f38d Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 03/18] Update irbuild-str.test --- mypyc/test-data/irbuild-str.test | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index bafab8f8133d..c79950af55d1 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -510,11 +510,11 @@ L0: return 1 [case testCountAll] -from typing import NewType, Union -NewStr = NewType("NewStr", str) -def do_count(s: Union[str, NewStr]) -> int: +#from typing import NewType, Union +#NewStr = NewType("NewStr", str) +def do_count(s: str) -> int: return s.count("x") # type: ignore [attr-defined] -[typing fixtures/typing-full.pyi] +#[typing fixtures/typing-full.pyi] [out] def do_count(s): s, r0 :: str @@ -531,11 +531,11 @@ L0: return r4 [case testCountStart] -from typing import NewType, Union -NewStr = NewType("NewStr", str) -def do_count(s: Union[str, NewStr], start: int) -> int: +#from typing import NewType, Union +#NewStr = NewType("NewStr", str) +def do_count(s: str, start: int) -> int: return s.count("x", start) # type: ignore [attr-defined] -[typing fixtures/typing-full.pyi] +#[typing fixtures/typing-full.pyi] [out] def do_count(s, start): s :: str @@ -554,11 +554,11 @@ L0: return r4 [case testCountStartEnd] -from typing import NewType, Union -NewStr = NewType("NewStr", str) -def do_count(s: Union[str, NewStr], start: int, end: int) -> int: +#from typing import NewType, Union +#NewStr = NewType("NewStr", str) +def do_count(s: str, start: int, end: int) -> int: return s.count("x", start, end) # type: ignore [attr-defined] -[typing fixtures/typing-full.pyi] +#[typing fixtures/typing-full.pyi] [out] def do_count(s, start, end): s :: str From e95b4c9ff255c5dea99a99aebf93090c233415c2 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 04/18] Update irbuild-str.test --- mypyc/test-data/irbuild-str.test | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index c79950af55d1..b8d405968f21 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -510,11 +510,11 @@ L0: return 1 [case testCountAll] -#from typing import NewType, Union -#NewStr = NewType("NewStr", str) +from typing import NewType, Union +NewStr = NewType("NewStr", str) def do_count(s: str) -> int: return s.count("x") # type: ignore [attr-defined] -#[typing fixtures/typing-full.pyi] +[builtins fixtures/string.pyi] [out] def do_count(s): s, r0 :: str @@ -531,11 +531,11 @@ L0: return r4 [case testCountStart] -#from typing import NewType, Union -#NewStr = NewType("NewStr", str) +from typing import NewType, Union +NewStr = NewType("NewStr", str) def do_count(s: str, start: int) -> int: return s.count("x", start) # type: ignore [attr-defined] -#[typing fixtures/typing-full.pyi] +[builtins fixtures/string.pyi] [out] def do_count(s, start): s :: str @@ -554,11 +554,11 @@ L0: return r4 [case testCountStartEnd] -#from typing import NewType, Union -#NewStr = NewType("NewStr", str) +from typing import NewType, Union +NewStr = NewType("NewStr", str) def do_count(s: str, start: int, end: int) -> int: return s.count("x", start, end) # type: ignore [attr-defined] -#[typing fixtures/typing-full.pyi] +[builtins fixtures/string.pyi] [out] def do_count(s, start, end): s :: str From 751d29070f5dd29bfd0e68dc20928c5681a49c23 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 05/18] Update irbuild-str.test --- mypyc/test-data/irbuild-str.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index b8d405968f21..ba824abb52b5 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -515,6 +515,7 @@ NewStr = NewType("NewStr", str) def do_count(s: str) -> int: return s.count("x") # type: ignore [attr-defined] [builtins fixtures/string.pyi] +[typing fixtures/typing-full.pyi] [out] def do_count(s): s, r0 :: str @@ -536,6 +537,7 @@ NewStr = NewType("NewStr", str) def do_count(s: str, start: int) -> int: return s.count("x", start) # type: ignore [attr-defined] [builtins fixtures/string.pyi] +[typing fixtures/typing-full.pyi] [out] def do_count(s, start): s :: str @@ -559,6 +561,7 @@ NewStr = NewType("NewStr", str) def do_count(s: str, start: int, end: int) -> int: return s.count("x", start, end) # type: ignore [attr-defined] [builtins fixtures/string.pyi] +[typing fixtures/typing-full.pyi] [out] def do_count(s, start, end): s :: str From 5193d35e571fc328222245e4e814acc8354ebe02 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 06/18] Create string.pyi --- mypyc/test-data/fixtures/string.pyi | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 mypyc/test-data/fixtures/string.pyi diff --git a/mypyc/test-data/fixtures/string.pyi b/mypyc/test-data/fixtures/string.pyi new file mode 100644 index 000000000000..9bd22edc5fbc --- /dev/null +++ b/mypyc/test-data/fixtures/string.pyi @@ -0,0 +1,10 @@ +from typing import Optional + +class int: pass +class str: pass + def count( + self, + substr: str, + start: Optional[int] = None, + end: Optional[int] = None, + ) -> int: pass From 11c5e708b00aaff7bc8403dd26b700fd1acf76b2 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 07/18] Update string.pyi --- mypyc/test-data/fixtures/string.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/test-data/fixtures/string.pyi b/mypyc/test-data/fixtures/string.pyi index 9bd22edc5fbc..8d2576ed00f9 100644 --- a/mypyc/test-data/fixtures/string.pyi +++ b/mypyc/test-data/fixtures/string.pyi @@ -1,7 +1,7 @@ from typing import Optional class int: pass -class str: pass +class str: def count( self, substr: str, From 1df19284c414396ab4237d7d82fb4229fb820c5b Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 08/18] Update string.pyi --- mypyc/test-data/fixtures/string.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/mypyc/test-data/fixtures/string.pyi b/mypyc/test-data/fixtures/string.pyi index 8d2576ed00f9..30ce7ad893f3 100644 --- a/mypyc/test-data/fixtures/string.pyi +++ b/mypyc/test-data/fixtures/string.pyi @@ -1,5 +1,6 @@ from typing import Optional +class dict: pass class int: pass class str: def count( From 8ca4b598faa209bf56aee4e80643cca5f2e7bb26 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 09/18] Update string.pyi --- mypyc/test-data/fixtures/string.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/mypyc/test-data/fixtures/string.pyi b/mypyc/test-data/fixtures/string.pyi index 30ce7ad893f3..7c15d99ce4df 100644 --- a/mypyc/test-data/fixtures/string.pyi +++ b/mypyc/test-data/fixtures/string.pyi @@ -1,6 +1,7 @@ from typing import Optional class dict: pass +class ellipsis: pass class int: pass class str: def count( From ec94ada70f58a9ce044804756acf6a1c66e50eb8 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 10/18] Update ir.py --- mypyc/test-data/fixtures/ir.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index 3776a3dcc79a..76afc1ea58cc 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -122,6 +122,7 @@ def rpartition(self, sep: str, /) -> Tuple[str, str, str]: ... def removeprefix(self, prefix: str, /) -> str: ... def removesuffix(self, suffix: str, /) -> str: ... def islower(self) -> bool: ... + def count(self, substr: str, start: Optional[int] = None, end: Optional[int] = None) -> int: pass class float: def __init__(self, x: object) -> None: pass From 4adc262e90d7c3152f9350ebdef0876e8bfc72f1 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 11/18] Delete mypyc/test-data/fixtures/string.pyi --- mypyc/test-data/fixtures/string.pyi | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 mypyc/test-data/fixtures/string.pyi diff --git a/mypyc/test-data/fixtures/string.pyi b/mypyc/test-data/fixtures/string.pyi deleted file mode 100644 index 7c15d99ce4df..000000000000 --- a/mypyc/test-data/fixtures/string.pyi +++ /dev/null @@ -1,12 +0,0 @@ -from typing import Optional - -class dict: pass -class ellipsis: pass -class int: pass -class str: - def count( - self, - substr: str, - start: Optional[int] = None, - end: Optional[int] = None, - ) -> int: pass From dea2c67f7a428e07787f216b8b12440c1653ef2b Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 12/18] Update irbuild-str.test --- mypyc/test-data/irbuild-str.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index ba824abb52b5..6b90bad93ecb 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -514,7 +514,7 @@ from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str) -> int: return s.count("x") # type: ignore [attr-defined] -[builtins fixtures/string.pyi] +[builtins fixtures/ir.pyi] [typing fixtures/typing-full.pyi] [out] def do_count(s): @@ -536,7 +536,7 @@ from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str, start: int) -> int: return s.count("x", start) # type: ignore [attr-defined] -[builtins fixtures/string.pyi] +[builtins fixtures/ir.pyi] [typing fixtures/typing-full.pyi] [out] def do_count(s, start): @@ -560,7 +560,7 @@ from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str, start: int, end: int) -> int: return s.count("x", start, end) # type: ignore [attr-defined] -[builtins fixtures/string.pyi] +[builtins fixtures/ir.pyi] [typing fixtures/typing-full.pyi] [out] def do_count(s, start, end): From 0cb656744563dca8edda55236b96587bc34e15d2 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 13/18] Update irbuild-str.test --- mypyc/test-data/irbuild-str.test | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index 6b90bad93ecb..be3f68d298c6 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -513,8 +513,7 @@ L0: from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str) -> int: - return s.count("x") # type: ignore [attr-defined] -[builtins fixtures/ir.pyi] + return s.count("x") [typing fixtures/typing-full.pyi] [out] def do_count(s): @@ -535,8 +534,7 @@ L0: from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str, start: int) -> int: - return s.count("x", start) # type: ignore [attr-defined] -[builtins fixtures/ir.pyi] + return s.count("x", start) [typing fixtures/typing-full.pyi] [out] def do_count(s, start): @@ -559,8 +557,7 @@ L0: from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str, start: int, end: int) -> int: - return s.count("x", start, end) # type: ignore [attr-defined] -[builtins fixtures/ir.pyi] + return s.count("x", start, end) [typing fixtures/typing-full.pyi] [out] def do_count(s, start, end): From ae23b30a37edab195c92bd00288c66facea75d2f Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 14/18] fix: ir --- mypyc/test-data/irbuild-str.test | 67 +++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index be3f68d298c6..a908e8ec76c3 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -519,16 +519,26 @@ def do_count(s: str) -> int: def do_count(s): s, r0 :: str r1 :: native_int - r2 :: bit - r3 :: object - r4 :: int + r2, r3, r4 :: bit + r5, r6, r7 :: int L0: r0 = 'x' r1 = CPyStr_Count(s, r0, 0) r2 = r1 >= 0 :: signed - r3 = box(native_int, r1) - r4 = unbox(int, r3) - return r4 + r3 = r1 <= 4611686018427387903 :: signed + if r3 goto L1 else goto L2 :: bool +L1: + r4 = r1 >= -4611686018427387904 :: signed + if r4 goto L3 else goto L2 :: bool +L2: + r5 = CPyTagged_FromInt64(r1) + r6 = r5 + goto L4 +L3: + r7 = r1 << 1 + r6 = r7 +L4: + return r6 [case testCountStart] from typing import NewType, Union @@ -542,16 +552,26 @@ def do_count(s, start): start :: int r0 :: str r1 :: native_int - r2 :: bit - r3 :: object - r4 :: int + r2, r3, r4 :: bit + r5, r6, r7 :: int L0: r0 = 'x' r1 = CPyStr_Count(s, r0, start) r2 = r1 >= 0 :: signed - r3 = box(native_int, r1) - r4 = unbox(int, r3) - return r4 + r3 = r1 <= 4611686018427387903 :: signed + if r3 goto L1 else goto L2 :: bool +L1: + r4 = r1 >= -4611686018427387904 :: signed + if r4 goto L3 else goto L2 :: bool +L2: + r5 = CPyTagged_FromInt64(r1) + r6 = r5 + goto L4 +L3: + r7 = r1 << 1 + r6 = r7 +L4: + return r6 [case testCountStartEnd] from typing import NewType, Union @@ -565,13 +585,24 @@ def do_count(s, start, end): start, end :: int r0 :: str r1 :: native_int - r2 :: bit - r3 :: object - r4 :: int + r2, r3, r4 :: bit + r5, r6, r7 :: int L0: r0 = 'x' r1 = CPyStr_CountFull(s, r0, start, end) r2 = r1 >= 0 :: signed - r3 = box(native_int, r1) - r4 = unbox(int, r3) - return r4 + r3 = r1 <= 4611686018427387903 :: signed + if r3 goto L1 else goto L2 :: bool +L1: + r4 = r1 >= -4611686018427387904 :: signed + if r4 goto L3 else goto L2 :: bool +L2: + r5 = CPyTagged_FromInt64(r1) + r6 = r5 + goto L4 +L3: + r7 = r1 << 1 + r6 = r7 +L4: + return r6 + From 1f36615a7c2623a35fefae6e5631ad34ef99cd28 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 15/18] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypyc/test-data/irbuild-str.test | 1 - 1 file changed, 1 deletion(-) diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index a908e8ec76c3..3f915b75c27e 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -605,4 +605,3 @@ L3: r6 = r7 L4: return r6 - From 63398e4ee34bc3daa37f49eeb409c7fc91567e2c Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:00:35 +0000 Subject: [PATCH 16/18] Update irbuild-str.test --- mypyc/test-data/irbuild-str.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mypyc/test-data/irbuild-str.test b/mypyc/test-data/irbuild-str.test index 3f915b75c27e..3e69325a454b 100644 --- a/mypyc/test-data/irbuild-str.test +++ b/mypyc/test-data/irbuild-str.test @@ -509,7 +509,7 @@ L0: r8 = CPyStr_RStrip(s, 0) return 1 -[case testCountAll] +[case testCountAll_64bit] from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str) -> int: @@ -540,7 +540,7 @@ L3: L4: return r6 -[case testCountStart] +[case testCountStart_64bit] from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str, start: int) -> int: @@ -573,7 +573,7 @@ L3: L4: return r6 -[case testCountStartEnd] +[case testCountStartEnd_64bit] from typing import NewType, Union NewStr = NewType("NewStr", str) def do_count(s: str, start: int, end: int) -> int: From b52c277e8bdd96013f361daf027bb22cd16ca93a Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Sun, 3 Aug 2025 17:57:58 +0000 Subject: [PATCH 17/18] chore: refactor --- mypyc/irbuild/mapper.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index 528fa3605b84..6adc08a9cc1c 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -76,8 +76,7 @@ def type_to_rtype(self, typ: Type | None) -> RType: if typ.type.is_newtype and len(typ.type.bases) == 1: # I'm pretty sure this length check always returns True but am not positive and False would break things # Unwrap NewType to its base type for rprimitive mapping - base_typeinfo = typ.type.bases[0].type - return self.type_to_rtype(Instance(base_typeinfo, [])) + return self.type_to_rtype(typ.type.bases[0]) if typ.type.fullname == "builtins.int": return int_rprimitive elif typ.type.fullname == "builtins.float": From 11f248193d4aba1039210ee892e46e4bd222a371 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Sun, 3 Aug 2025 18:02:35 +0000 Subject: [PATCH 18/18] feat: assert --- mypyc/irbuild/mapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index 6adc08a9cc1c..815688d90fb6 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -73,9 +73,9 @@ def type_to_rtype(self, typ: Type | None) -> RType: typ = get_proper_type(typ) if isinstance(typ, Instance): - if typ.type.is_newtype and len(typ.type.bases) == 1: - # I'm pretty sure this length check always returns True but am not positive and False would break things + if typ.type.is_newtype: # Unwrap NewType to its base type for rprimitive mapping + assert len(typ.type.bases) == 1, typ.type.bases return self.type_to_rtype(typ.type.bases[0]) if typ.type.fullname == "builtins.int": return int_rprimitive