Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[red-knot] Port type inference tests to new test framework #13719

Merged
merged 19 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 18 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
@@ -0,0 +1,25 @@
# Assignment with annotations

## Annotation only transparent to local inference

```py
x = 1
x: int
y = x

reveal_type(y) # revealed: Literal[1]
```

## Violates own annotation

```py
x: int = 'foo' # error: [invalid-assignment] "Object of type `Literal["foo"]` is not assignable to `int`"

```

## Violates previous annotation

```py
x: int
x = 'foo' # error: [invalid-assignment] "Object of type `Literal["foo"]` is not assignable to `int`"
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Class attributes assignment

## Union of attributes

```py
if flag:
class C:
x = 1
else:
class C:
x = 2

y = C.x
reveal_type(y) # revealed: Literal[1, 2]
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Errors while declaring

## Violates previous assignment

```py
x = 1
x: str # error: [invalid-declaration] "Cannot declare type `str` for inferred type `Literal[1]`"
```

## Incompatible declarations

```py
if flag:
x: str
else:
x: int
x = 1 # error: [conflicting-declarations] "Conflicting declared types for `x`: str, int"
```

## Partial declarations

```py
if flag:
x: int
x = 1 # error: [conflicting-declarations] "Conflicting declared types for `x`: Unknown, int"
```

## Incompatible declarations with bad assignment

```py
if flag:
x: str
else:
x: int

# error: [conflicting-declarations]
# error: [invalid-assignment]
x = b'foo'
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Multi-target assignment

## Basic

```py
x = y = 1
reveal_type(x) # revealed: Literal[1]
reveal_type(y) # revealed: Literal[1]
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Unbound

## Maybe unbound

```py
if flag:
y = 3
x = y
reveal_type(x) # revealed: Unbound | Literal[3]
```

## Unbound

```py
x = foo; foo = 1
reveal_type(x) # revealed: Unbound
```

## Unbound class variable

Class variables can reference global variables unless overridden within the class scope.

```py
x = 1
class C:
y = x
if flag:
x = 2

reveal_type(C.x) # revealed: Unbound | Literal[2]
reveal_type(C.y) # revealed: Literal[1]
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Walrus operator

## Basic

```py
x = (y := 1) + 1
reveal_type(x) # revealed: Literal[2]
reveal_type(y) # revealed: Literal[1]
```

## Walrus self-addition

```py
x = 0
(x := x + 1)
reveal_type(x) # revealed: Literal[1]
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Binary operations on integers

## Basic Arithmetic

```py
a = 2 + 1
b = a - 4
c = a * b
d = c // 3
e = c / 3
f = 5 % 3

reveal_type(a) # revealed: Literal[3]
reveal_type(b) # revealed: Literal[-1]
reveal_type(c) # revealed: Literal[-3]
reveal_type(d) # revealed: Literal[-1]
reveal_type(e) # revealed: float
reveal_type(f) # revealed: Literal[2]
```

## Division by Zero

```py
# TODO: `a` should be `int` and `e` should be `float` once we support inference.
a = 1 / 0 # error: "Cannot divide object of type `Literal[1]` by zero"
b = 2 // 0 # error: "Cannot floor divide object of type `Literal[2]` by zero"
c = 3 % 0 # error: "Cannot reduce object of type `Literal[3]` modulo zero"
d = int() / 0 # error: "Cannot divide object of type `int` by zero"
e = 1.0 / 0 # error: "Cannot divide object of type `float` by zero"

reveal_type(a) # revealed: float
reveal_type(b) # revealed: int
reveal_type(c) # revealed: int
reveal_type(d) # revealed: @Todo
reveal_type(e) # revealed: @Todo
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Callable instance

## Dunder call

```py
class Multiplier:
def __init__(self, factor: float):
self.factor = factor

def __call__(self, number: float) -> float:
return number * self.factor

a = Multiplier(2.0)(3.0)

class Unit: ...

b = Unit()(3.0) # error: "Object of type `Unit` is not callable"

reveal_type(a) # revealed: float
reveal_type(b) # revealed: Unknown
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Constructor

```py
class Foo: ...

x = Foo()
reveal_type(x) # revealed: Foo
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Call expression

## Simple

```py
def get_int() -> int:
return 42

x = get_int()
reveal_type(x) # revealed: int
```

## Async

```py
async def get_int_async() -> int:
return 42

x = get_int_async()

# TODO: we don't yet support `types.CoroutineType`, should be generic `Coroutine[Any, Any, int]`
reveal_type(x) # revealed: @Todo
```

## Decorated

```py
from typing import Callable

def foo() -> int:
return 42

def decorator(func) -> Callable[[], int]:
return foo

@decorator
def bar() -> str:
return 'bar'

x = bar()

# TODO: should reveal `int`, as the decorator replaces `bar` with `foo`
reveal_type(x) # revealed: @Todo
```

## Invalid callable

```py
nonsense = 123
x = nonsense() # error: "Object of type `Literal[123]` is not callable"
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Union return from calls

## Union of return types

```py
if flag:
def f() -> int:
return 1
else:
def f() -> str:
return 'foo'

x = f()
reveal_type(x) # revealed: int | str
```

## Calling with an unknown union

```py
from nonexistent import f # error: [unresolved-import] "Cannot resolve import `nonexistent`"

if flag:
def f() -> int:
return 1

x = f()
reveal_type(x) # revealed: Unknown | int
```

## Non-callable elements in a union

If a variable in a union isn't callable, it should raise an error when called.

```py
if flag:
f = 1
else:
def f() -> int:
return 1

x = f() # error: "Object of type `Literal[1] | Literal[f]` is not callable (due to union element `Literal[1]`)"
reveal_type(x) # revealed: Unknown | int
```

## Multiple non-callable elements in a union

When more than one element of a union is not callable, the system should flag both.

```py
if flag:
f = 1
elif flag2:
f = 'foo'
else:
def f() -> int:
return 1

x = f() # error: "Object of type `Literal[1] | Literal["foo"] | Literal[f]` is not callable (due to union elements Literal[1], Literal["foo"])"
reveal_type(x) # revealed: Unknown | int
```

## All non-callable union elements

If none of the elements in a union are callable, the type system should raise an error.

```py
if flag:
f = 1
else:
f = 'foo'

x = f() # error: "Object of type `Literal[1] | Literal["foo"]` is not callable"
reveal_type(x) # revealed: Unknown
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Comparing integers

## Integer literals

```py
a = 1 == 1 == True
b = 1 == 1 == 2 == 4
c = False < True <= 2 < 3 != 6
d = 1 < 1
e = 1 > 1
f = 1 is 1
g = 1 is not 1
h = 1 is 2
i = 1 is not 7
j = 1 <= "" and 0 < 1

reveal_type(a) # revealed: Literal[True]
reveal_type(b) # revealed: Literal[False]
reveal_type(c) # revealed: Literal[True]
reveal_type(d) # revealed: Literal[False]
reveal_type(e) # revealed: Literal[False]
reveal_type(f) # revealed: bool
reveal_type(g) # revealed: bool
reveal_type(h) # revealed: Literal[False]
reveal_type(i) # revealed: Literal[True]
reveal_type(j) # revealed: @Todo | Literal[True]
```

## Integer instance

```py
# TODO: implement lookup of `__eq__` on typeshed `int` stub.
def int_instance() -> int: ...
a = 1 == int_instance()
b = 9 < int_instance()
c = int_instance() < int_instance()

reveal_type(a) # revealed: @Todo
reveal_type(b) # revealed: bool
reveal_type(c) # revealed: bool
```
Loading
Loading