Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
conformant = "Pass"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be updated to Partial if this is merged.

conformance_automated = "Pass"
conformance_automated = "Fail"
errors_diff = """
Line 204: Unexpected errors ['generics_variance_inference.py:204:1: error: Type `ShouldBeCovariant7[int]` is not assignable to `ShouldBeCovariant7[object]` (type parameter is covariant) [generics_variance_inference]']
"""
output = """
generics_variance_inference.py:24:5: error: Type `ClassA[float]` is not assignable to `ClassA[int]` (type parameter is invariant) [generics_variance_inference]
Expand All @@ -26,4 +27,6 @@ generics_variance_inference.py:169:1: error: Type `ShouldBeInvariant6[float]` is
generics_variance_inference.py:170:1: error: Type `ShouldBeInvariant6[int]` is not assignable to `ShouldBeInvariant6[float]` (type parameter is invariant) [generics_variance_inference]
generics_variance_inference.py:181:1: error: Type `ShouldBeCovariant6[float]` is not assignable to `ShouldBeCovariant6[int]` (type parameter is covariant) [generics_variance_inference]
generics_variance_inference.py:194:1: error: Type `ShouldBeContravariant2[int]` is not assignable to `ShouldBeContravariant2[float]` (type parameter is contravariant) [generics_variance_inference]
generics_variance_inference.py:204:1: error: Type `ShouldBeCovariant7[int]` is not assignable to `ShouldBeCovariant7[object]` (type parameter is covariant) [generics_variance_inference]
generics_variance_inference.py:205:1: error: Type `ShouldBeCovariant7[object]` is not assignable to `ShouldBeCovariant7[int]` (type parameter is covariant) [generics_variance_inference]
"""
12 changes: 10 additions & 2 deletions conformance/results/mypy/generics_variance_inference.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
conformant = "Pass"
conformant = "Partial"
notes = """
polymorphic functions with bound self type influence variance inference,
which is not part of the variance inference algorithm as described in the spec.
See gh-2281 for details.
"""
output = """
generics_variance_inference.py:24: error: Incompatible types in assignment (expression has type "ClassA[float, int, int]", variable has type "ClassA[int, int, int]") [assignment]
generics_variance_inference.py:25: error: Incompatible types in assignment (expression has type "ClassA[float, int, int]", variable has type "ClassA[float, float, int]") [assignment]
Expand All @@ -23,7 +28,10 @@ generics_variance_inference.py:169: error: Incompatible types in assignment (exp
generics_variance_inference.py:170: error: Incompatible types in assignment (expression has type "ShouldBeInvariant6[int]", variable has type "ShouldBeInvariant6[float]") [assignment]
generics_variance_inference.py:181: error: Incompatible types in assignment (expression has type "ShouldBeCovariant6[float]", variable has type "ShouldBeCovariant6[int]") [assignment]
generics_variance_inference.py:194: error: Incompatible types in assignment (expression has type "ShouldBeContravariant2[int]", variable has type "ShouldBeContravariant2[float]") [assignment]
generics_variance_inference.py:204: error: Incompatible types in assignment (expression has type "ShouldBeCovariant7[int]", variable has type "ShouldBeCovariant7[object]") [assignment]
generics_variance_inference.py:205: error: Incompatible types in assignment (expression has type "ShouldBeCovariant7[object]", variable has type "ShouldBeCovariant7[int]") [assignment]
"""
conformance_automated = "Pass"
conformance_automated = "Fail"
errors_diff = """
Line 204: Unexpected errors ['generics_variance_inference.py:204: error: Incompatible types in assignment (expression has type "ShouldBeCovariant7[int]", variable has type "ShouldBeCovariant7[object]") [assignment]']
"""
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ output = """
./generics_variance_inference.py:170:0: Incompatible assignment: expected generics_variance_inference.ShouldBeInvariant6[float | int], got generics_variance_inference.ShouldBeInvariant6[int] [incompatible_assignment]
./generics_variance_inference.py:181:0: Incompatible assignment: expected generics_variance_inference.ShouldBeCovariant6[int], got generics_variance_inference.ShouldBeCovariant6[float | int] [incompatible_assignment]
./generics_variance_inference.py:194:0: Incompatible assignment: expected generics_variance_inference.ShouldBeContravariant2[float | int], got generics_variance_inference.ShouldBeContravariant2[int] [incompatible_assignment]
./generics_variance_inference.py:205:0: Incompatible assignment: expected generics_variance_inference.ShouldBeCovariant7[int], got generics_variance_inference.ShouldBeCovariant7[object] [incompatible_assignment]
"""
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ ERROR generics_variance_inference.py:169:31-58: `ShouldBeInvariant6[float]` is n
ERROR generics_variance_inference.py:170:33-58: `ShouldBeInvariant6[int]` is not assignable to `ShouldBeInvariant6[float]` [bad-assignment]
ERROR generics_variance_inference.py:181:31-58: `ShouldBeCovariant6[float]` is not assignable to `ShouldBeCovariant6[int]` [bad-assignment]
ERROR generics_variance_inference.py:194:37-66: `ShouldBeContravariant2[int]` is not assignable to `ShouldBeContravariant2[float]` [bad-assignment]
ERROR generics_variance_inference.py:205:31-59: `ShouldBeCovariant7[object]` is not assignable to `ShouldBeCovariant7[int]` [bad-assignment]
"""
4 changes: 4 additions & 0 deletions conformance/results/pyright/generics_variance_inference.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ generics_variance_inference.py:194:37 - error: Type "ShouldBeContravariant2[int]
  "ShouldBeContravariant2[int]" is not assignable to "ShouldBeContravariant2[float]"
    Type parameter "T@ShouldBeContravariant2" is contravariant, but "int" is not a supertype of "float"
      "float" is not assignable to "int" (reportAssignmentType)
generics_variance_inference.py:205:31 - error: Type "ShouldBeCovariant7[object]" is not assignable to declared type "ShouldBeCovariant7[int]"
  "ShouldBeCovariant7[object]" is not assignable to "ShouldBeCovariant7[int]"
    Type parameter "T@ShouldBeCovariant7" is covariant, but "object" is not a subtype of "int"
      "object" is not assignable to "int" (reportAssignmentType)
"""
conformance_automated = "Pass"
errors_diff = """
Expand Down
28 changes: 21 additions & 7 deletions conformance/results/results.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions conformance/results/ty/generics_variance_inference.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ generics_variance_inference.py:169:31: error[invalid-assignment] Object of type
generics_variance_inference.py:170:33: error[invalid-assignment] Object of type `ShouldBeInvariant6[int]` is not assignable to `ShouldBeInvariant6[int | float]`
generics_variance_inference.py:181:31: error[invalid-assignment] Object of type `ShouldBeCovariant6[int | float]` is not assignable to `ShouldBeCovariant6[int]`
generics_variance_inference.py:194:37: error[invalid-assignment] Object of type `ShouldBeContravariant2[int]` is not assignable to `ShouldBeContravariant2[int | float]`
generics_variance_inference.py:205:31: error[invalid-assignment] Object of type `ShouldBeCovariant7[object]` is not assignable to `ShouldBeCovariant7[int]`
"""
12 changes: 11 additions & 1 deletion conformance/results/zuban/generics_variance_inference.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
conformance_automated = "Pass"
conformant = "Partial"
notes = """
polymorphic functions with bound self type influence variance inference,
which is not part of the variance inference algorithm as described in the spec.
See gh-2281 for details.
"""
conformance_automated = "Fail"
errors_diff = """
Line 200: Unexpected errors ['generics_variance_inference.py:200: error: Name "S" is not defined [name-defined]', 'generics_variance_inference.py:200: error: Name "S" is not defined [name-defined]']
"""
output = """
generics_variance_inference.py:24: error: Incompatible types in assignment (expression has type "ClassA[float, int, int]", variable has type "ClassA[int, int, int]") [assignment]
Expand All @@ -25,4 +32,7 @@ generics_variance_inference.py:169: error: Incompatible types in assignment (exp
generics_variance_inference.py:170: error: Incompatible types in assignment (expression has type "ShouldBeInvariant6[int]", variable has type "ShouldBeInvariant6[float]") [assignment]
generics_variance_inference.py:181: error: Incompatible types in assignment (expression has type "ShouldBeCovariant6[float]", variable has type "ShouldBeCovariant6[int]") [assignment]
generics_variance_inference.py:194: error: Incompatible types in assignment (expression has type "ShouldBeContravariant2[int]", variable has type "ShouldBeContravariant2[float]") [assignment]
generics_variance_inference.py:200: error: Name "S" is not defined [name-defined]
generics_variance_inference.py:200: error: Name "S" is not defined [name-defined]
generics_variance_inference.py:205: error: Incompatible types in assignment (expression has type "ShouldBeCovariant7[object]", variable has type "ShouldBeCovariant7[int]") [assignment]
"""
11 changes: 11 additions & 0 deletions conformance/tests/generics_variance_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,14 @@ class ShouldBeContravariant2[T](Parent_Contravariant[T]):

c1: ShouldBeContravariant2[int] = ShouldBeContravariant2[float]() # OK
c2: ShouldBeContravariant2[float] = ShouldBeContravariant2[int]() # E

class ShouldBeCovariant7[T]:
def get(self) -> T:
raise NotImplementedError

def add[S](self: "ShouldBeCovariant7[S]", other: list[S]) -> "ShouldBeCovariant7[S]":

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure it's correct for this method not to affect variance. (Assuming the class were named C instead for brevity) C[object] has method add taking list[object], where C[int] has method add taking list[int]. That means neither C[object] nor C[int] can safely be substituted for the other, and C should be invariant in T.

So it seems to me that if the algorithm in the spec says this class should be covariant, that might be a bug in the spec text.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I believe this argument in its current form relies on circular reasoning, because whether or not C[int].add allows list[object] argument depends on whether or not C is considered covariant in S in the first place.

Let's remember that x.add(items) is basically syntactic sugar for type(x).add(x, items). Then, given x: C[int] and items: list[objects] our constraints are:

  1. C[int] <: C[S] from assigning x to self
  2. list[object] <: list[S] from assigning items to other

The first constraint is equivalent to S=int if we presume that C is invariant in S, and equivalent to int <: S if C is presumed covariant in S. In the latter case S=object is a solution.

Let's make the example more concrete:

class C[T]:
    def __init__(self, vals: list[T]) -> None:
        self._vals: Sequence[T] = vals

   def get(self, idx: int) -> T:
       return self._vals[idx]
       
    def add[S](self: C[S], items: list[S]) -> C[S]:
        return C([*self._vals, *items])

Do you have a concrete example were treating C covariantly leads to a runtime error? Then I'd gladly change this PR to assert invariance.

raise NotImplementedError


d1: ShouldBeCovariant7[object] = ShouldBeCovariant7[int]() # OK
d2: ShouldBeCovariant7[int] = ShouldBeCovariant7[object]() # E
Loading