Measured on v5/clr-resolution (visible only once IReverseEnumerable[int] became nameable again — P4 remediation R4; at 311252e33 the annotation itself was SPY0202, so the mismatch was masked).
class Bag:
_items: list[int]
def __init__(self) -> None:
self._items = [4, 5]
def __reversed__(self) -> Iterator[int]:
return reversed(self._items)
def take(r: IReverseEnumerable[int]) -> None:
for x in r:
print(x)
def main() -> None:
take(Bag())
error[SPY0220]: Cannot pass argument of type 'Bag' to parameter of type 'IReverseEnumerable[int32]'
Changing the parameter to IReverseEnumerable[Iterator[int]] makes the argument bind (it then fails later on #1808, iterating an interface-typed receiver), so the synthesized interface's type argument is the __reversed__ return annotation verbatim rather than its element type.
The generator shape is correct: def __reversed__(self) -> int: yield ... synthesizes IReverseEnumerable[int] and take(c) binds (SynthesizedInterfaceVisibilityTests.Reversed_Class_ElementTypeFromAnnotation, and Integration/TestFixtures/interop/sharpy_interface_by_name_1625.spy). Only the non-generator arm — an explicit Iterator[T] / IEnumerator[T] return — takes the annotation unpeeled.
The element-type decision belongs to the one iterable-element decider (InferReversedElementType and friends), which should unwrap an iterator/iterable return the same way the generator arm does. Same family as the P9 ClassifyIterableSource consolidation.
Measured on
v5/clr-resolution(visible only onceIReverseEnumerable[int]became nameable again — P4 remediation R4; at311252e33the annotation itself was SPY0202, so the mismatch was masked).Changing the parameter to
IReverseEnumerable[Iterator[int]]makes the argument bind (it then fails later on #1808, iterating an interface-typed receiver), so the synthesized interface's type argument is the__reversed__return annotation verbatim rather than its element type.The generator shape is correct:
def __reversed__(self) -> int: yield ...synthesizesIReverseEnumerable[int]andtake(c)binds (SynthesizedInterfaceVisibilityTests.Reversed_Class_ElementTypeFromAnnotation, andIntegration/TestFixtures/interop/sharpy_interface_by_name_1625.spy). Only the non-generator arm — an explicitIterator[T]/IEnumerator[T]return — takes the annotation unpeeled.The element-type decision belongs to the one iterable-element decider (
InferReversedElementTypeand friends), which should unwrap an iterator/iterable return the same way the generator arm does. Same family as the P9ClassifyIterableSourceconsolidation.