Skip to content

Commit

Permalink
Support infer variance
Browse files Browse the repository at this point in the history
Summary:
We begin support for `infer_variance` and add a unittest.

TODO:
Three conformance tests that respectively use:
- dataclass
- property
- final

I looked at is setting the "self" parameter to be bivariant, which seems correct according to Vitousek's writeup on the variance for self types https://fb.workplace.com/notes/flow-inference-redesign/variance-of-the-this-parameter-in-methods/2804686066457515 , but doing so is not giving me the right results.

Reviewed By: stroxler

Differential Revision: D64702381

fbshipit-source-id: 53db8adaea91b46f4b8891465dbcecfbc1c30dac
  • Loading branch information
migeed-z authored and facebook-github-bot committed Oct 25, 2024
1 parent 0d20f3a commit 54e7df4
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
46 changes: 46 additions & 0 deletions source/analysis/test/integration/typeVariableTest.ml
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,52 @@ let test_type_variable_scoping =
"Incompatible variable type [9]: vcontra1_1 is declared to have type \
`ShouldBeContravariant1[float]` but is used as type `ShouldBeContravariant1[int]`.";
];
(* TODO migeedz: vo5_1 should not raise an error. Tried considering the "self" parameter as
bivariant and that did not solve the issue. *)
labeled_test_case __FUNCTION__ __LINE__
@@ assert_type_errors
{|
from typing import Generic, TypeVar, Iterator
T = TypeVar("T", infer_variance=True)
class ShouldBeCovariant1(Generic[T]):
def __getitem__(self, index: int) -> T:
...
def __iter__(self) -> Iterator[T]:
...
vco1_1: ShouldBeCovariant1[float] = ShouldBeCovariant1[int]() # OK
vco1_2: ShouldBeCovariant1[int] = ShouldBeCovariant1[float]() # E
K = TypeVar("K", infer_variance=True)
class ShouldBeCovariant5(Generic[K]):
def __init__(self, x: K) -> None:
self._x = x
def x(self) -> K:
return self._x
vo5_1: ShouldBeCovariant5[float] = ShouldBeCovariant5[int](1) # OK
vo5_2: ShouldBeCovariant5[int] = ShouldBeCovariant5[float](1.0) # E
|}
[
"Incompatible variable type [9]: vco1_2 is declared to have type \
`ShouldBeCovariant1[int]` but is used as type `ShouldBeCovariant1[float]`.";
"Incompatible variable type [9]: vo5_1 is declared to have type \
`ShouldBeCovariant5[float]` but is used as type `ShouldBeCovariant5[int]`.";
"Incompatible variable type [9]: vo5_2 is declared to have type \
`ShouldBeCovariant5[int]` but is used as type `ShouldBeCovariant5[float]`.";
];
labeled_test_case __FUNCTION__ __LINE__
@@ assert_type_errors
{|
Expand Down
6 changes: 6 additions & 0 deletions source/analysis/type.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3149,6 +3149,12 @@ module Variable = struct
}
when String.equal (Identifier.sanitized name) "contravariant" ->
Some Record.PreInferenceVariance.P_Contravariant
| {
Call.Argument.name = Some { Node.value = name; _ };
value = { Node.value = Constant Constant.True; _ };
}
when String.equal (Identifier.sanitized name) "infer_variance" ->
Some Record.PreInferenceVariance.P_Undefined
| _ -> None
in
List.find_map arguments ~f:variance_definition
Expand Down

0 comments on commit 54e7df4

Please sign in to comment.