Skip to content

SoquetT becomes a protocol#1721

Open
mpharrigan wants to merge 6 commits intoquantumlib:mainfrom
mpharrigan:2025-09/soquetprotocol
Open

SoquetT becomes a protocol#1721
mpharrigan wants to merge 6 commits intoquantumlib:mainfrom
mpharrigan:2025-09/soquetprotocol

Conversation

@mpharrigan
Copy link
Collaborator

@mpharrigan mpharrigan commented Sep 24, 2025

Switches the SoquetT union type alias to a typing.Protocol. This supports "duck typing", which is appropriate for the situation where SoquetT is used as a type annotation.

Specifically, SoquetT is now anything that has .shape and .item(*args). With the addition of these properties/methods to the Soquet class, now this is satisfied by Soquet and NDArray. Note: we can't use mypy to annotate things with NDArray[Soquet] now or before due to limitations in numpy.

When users or developers need to dispatch depending on whether a SoquetT is a single soquet or an array thereof, they should use the new BloqBuilder methods. The example from the new docstring:

        >>> soq_or_soqs: SoquetT
        ... if BloqBuilder.is_ndarray(soq_or_soqs):
        ...     first_soq = soq_or_soqs.reshape(-1).item(0)
        ... else:
        ...     # Note: `.item()` raises if not a single item.
        ...     first_soq = soq_or_soqs.item()

In the protocol implementations and bloq standard library, this PR:

  • Adds the typing protocol and introduces new methods to Soquet
  • Uses the type-narrowing idioms in the _infra/ and protocols modules. Following this, pytest passes but there are mypy issues in the bloqs/ standard library
  • Then, uses the type-narrowing idioms in the bloqs/ standard library.
  • uses new alias soq.dtype instead of soq.reg.dtype. (removed from this PR)

Regarding #1720: this PR shows the changes to the standard library that would be required to avoid isinstance(x, Soquet) checks

@mpharrigan mpharrigan force-pushed the 2025-09/soquetprotocol branch from 476259c to b8ff0f0 Compare September 25, 2025 21:11
@mpharrigan
Copy link
Collaborator Author

I've force-pushed a more restrained set of changes. Note that pytest-quick passes following commit 8496830 which includes absolutely no changes to the bloqs/ subdirectory. The changes needed to satisfy the type checker are found in b8ff0f0

@mhucka
Copy link
Contributor

mhucka commented Feb 26, 2026

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors SoquetT from a Union to a typing.Protocol to better support duck typing. This is a significant improvement that makes the type system more flexible and expressive. The changes throughout the codebase to adopt the new SoquetT protocol and the BloqBuilder.is_single/is_ndarray type guards are well-executed. My review includes a couple of suggestions to improve type consistency in the BloqBuilder's free and split methods to fully align with the new protocol-based approach.

@@ -1395,10 +1430,10 @@ def allocate(
def free(self, soq: Soquet, dirty: bool = False) -> None:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The type hint for soq is Soquet, but the implementation with BloqBuilder.is_single(soq) suggests it should handle SoquetT. This is inconsistent. To align with the goals of this PR and for type correctness, the type hint for soq should be SoquetT. This will allow type checkers to correctly analyze code that passes SoquetT objects to this method.

Suggested change
def free(self, soq: Soquet, dirty: bool = False) -> None:
def free(self, soq: SoquetT, dirty: bool = False) -> None:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I talk back to you? I consider the type annotations to be a form of documentation and certainly not infallible. This is supposed to be a single soquet, but the code will behave unpredictably if passed something else. The documented type annotation is what's "supposed" to happen, but the runtime code handles what may actually happen.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants