# PEP 695 rules (`UP040`, `UP046`, `UP047`)

```toml
target-version = "py313"

[lint]
preview = true
select = [
    "non-pep695-type-alias",
    "non-pep695-generic-class",
    "non-pep695-generic-function",
]
```

## Defaulted `TypeVar` before a non-defaulted one

In a PEP 695 type parameter list, a non-defaulted type parameter cannot follow a defaulted one, and
reordering the parameters would change how positional arguments bind when subscripting the alias,
class, or function. There is no valid, equivalent type parameter list in this case, so no diagnostic
is emitted (see [#27021](https://github.com/astral-sh/ruff/issues/27021)).

### `non-pep695-type-alias` (`UP040`)

#### No diagnostic for a `TypeAlias` annotation

```py
from typing import TypeAlias, TypeVar

T = TypeVar("T", default=int)
S = TypeVar("S")

Pair: TypeAlias = tuple[T, S]
```

#### No diagnostic for a `TypeAliasType` call

```py
from typing import TypeAliasType, TypeVar

T = TypeVar("T", default=int)
S = TypeVar("S")

Pair = TypeAliasType("Pair", tuple[T, S], type_params=(T, S))
```

#### The fix is still offered when the non-defaulted `TypeVar` comes first

```py
from typing import TypeAlias, TypeVar

T = TypeVar("T", default=int)
S = TypeVar("S")

Pair: TypeAlias = tuple[S, T]  # snapshot: non-pep695-type-alias
```

```snapshot
error[UP040]: Type alias `Pair` uses `TypeAlias` annotation instead of the `type` keyword
 --> src/mdtest_snippet.py:6:1
  |
6 | Pair: TypeAlias = tuple[S, T]  # snapshot: non-pep695-type-alias
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: Use the `type` keyword
  |
5 |
  - Pair: TypeAlias = tuple[S, T]  # snapshot: non-pep695-type-alias
6 + type Pair[S, T = int] = tuple[S, T]  # snapshot: non-pep695-type-alias
  |
note: This is an unsafe fix and may change runtime behavior
```

#### The fix is still offered when all of the type variables have defaults

```py
from typing import TypeAlias, TypeVar

T = TypeVar("T", default=int)
S = TypeVar("S", default=str)

Pair: TypeAlias = tuple[T, S]  # error: [non-pep695-type-alias]
```

### `non-pep695-generic-class` (`UP046`)

#### No diagnostic when a defaulted `TypeVar` precedes a non-defaulted one

```py
from typing import Generic, TypeVar

T = TypeVar("T", default=int)
S = TypeVar("S")

class Pair(Generic[T, S]):
    t: T
    s: S
```

#### The fix is still offered when the non-defaulted `TypeVar` comes first

```py
from typing import Generic, TypeVar

T = TypeVar("T", default=int)
S = TypeVar("S")

class Pair(Generic[S, T]):  # snapshot: non-pep695-generic-class
    t: T
    s: S
```

```snapshot
error[UP046]: Generic class `Pair` uses `Generic` subclass instead of type parameters
 --> src/mdtest_snippet.py:6:12
  |
6 | class Pair(Generic[S, T]):  # snapshot: non-pep695-generic-class
  |            ^^^^^^^^^^^^^
help: Use type parameters
  |
5 |
  - class Pair(Generic[S, T]):  # snapshot: non-pep695-generic-class
6 + class Pair[S, T = int]:  # snapshot: non-pep695-generic-class
7 |     t: T
  |
note: This is an unsafe fix and may change runtime behavior
```

### `non-pep695-generic-function` (`UP047`)

#### No diagnostic when a defaulted `TypeVar` precedes a non-defaulted one

```py
from typing import TypeVar

T = TypeVar("T", default=int)
S = TypeVar("S")

def pair(t: T, s: S) -> tuple[T, S]:
    return (t, s)
```

#### The fix is still offered when the non-defaulted `TypeVar` comes first

```py
from typing import TypeVar

T = TypeVar("T", default=int)
S = TypeVar("S")

def pair(s: S, t: T) -> tuple[S, T]:  # snapshot: non-pep695-generic-function
    return (s, t)
```

```snapshot
error[UP047]: Generic function `pair` should use type parameters
 --> src/mdtest_snippet.py:6:5
  |
6 | def pair(s: S, t: T) -> tuple[S, T]:  # snapshot: non-pep695-generic-function
  |     ^^^^^^^^^^^^^^^^
help: Use type parameters
  |
5 |
  - def pair(s: S, t: T) -> tuple[S, T]:  # snapshot: non-pep695-generic-function
6 + def pair[S, T = int](s: S, t: T) -> tuple[S, T]:  # snapshot: non-pep695-generic-function
7 |     return (s, t)
  |
note: This is an unsafe fix and may change runtime behavior
```
