# Deferred annotations

## Deferred annotations in stubs always resolve

`mod.pyi`:

```pyi
def get_foo() -> Foo: ...

class Foo: ...
```

```py
from mod import get_foo

reveal_type(get_foo())  # revealed: Foo
```

## Deferred annotations in regular code fail

In (regular) source files, annotations are *not* deferred. This also tests that imports from
`__future__` that are not `annotations` are ignored.

```py
from __future__ import with_statement as annotations

# error: [unresolved-reference]
def get_foo() -> Foo: ...

class Foo: ...

reveal_type(get_foo())  # revealed: Unknown
```

## Deferred annotations in regular code with `__future__.annotations`

If `__future__.annotations` is imported, annotations *are* deferred.

```py
from __future__ import annotations

def get_foo() -> Foo:
    return Foo()

class Foo: ...

reveal_type(get_foo())  # revealed: Foo
```

## Deferred self-reference annotations in a class definition

```toml
[environment]
python-version = "3.12"
```

```py
from __future__ import annotations

class Foo:
    this: Foo
    # error: [unresolved-reference]
    _ = Foo()
    # error: [unresolved-reference]
    [Foo for _ in range(1)]
    a = int

    def f(self, x: Foo):
        reveal_type(x)  # revealed: Foo

    def g(self) -> Foo:
        _: Foo = self
        return self

    class Bar:
        foo: Foo
        b = int

        def f(self, x: Foo):
            return self
        # error: [unresolved-reference]
        def g(self) -> Bar:
            return self
        # error: [unresolved-reference]
        def h[T: Bar](self):
            pass

        class Baz[T: Foo]:
            pass

        # error: [unresolved-reference] "Name `Foo` used when not defined"
        # error: [unresolved-reference] "Name `Bar` used when not defined"
        class Qux(Foo, Bar, Baz):
            pass

        # error: [unresolved-reference] "Name `Foo` used when not defined"
        # error: [unresolved-reference] "Name `Bar` used when not defined"
        class Quux[_T](Foo, Bar, Baz):
            pass

        # error: [unresolved-reference]
        type S = a
        type T = b
        type U = Foo
        # error: [unresolved-reference]
        type V = Bar
        type W = Baz

    def h[T: Bar]():
        # error: [unresolved-reference]
        return Bar()
    type Baz = Foo
```

## Non-deferred self-reference annotations in a class definition

```toml
[environment]
python-version = "3.12"
```

```py
class Foo:
    # error: [unresolved-reference]
    this: Foo
    ok: "Foo"
    # error: [unresolved-reference]
    _ = Foo()
    # error: [unresolved-reference]
    [Foo for _ in range(1)]
    a = int

    # error: [unresolved-reference]
    def f(self, x: Foo):
        reveal_type(x)  # revealed: Unknown
    # error: [unresolved-reference]
    def g(self) -> Foo:
        _: Foo = self
        return self

    class Bar:
        # error: [unresolved-reference]
        foo: Foo
        b = int

        # error: [unresolved-reference]
        def f(self, x: Foo):
            return self
        # error: [unresolved-reference]
        def g(self) -> Bar:
            return self
        # error: [unresolved-reference]
        def h[T: Bar](self):
            pass

        class Baz[T: Foo]:
            pass

        # error: [unresolved-reference] "Name `Foo` used when not defined"
        # error: [unresolved-reference] "Name `Bar` used when not defined"
        class Qux(Foo, Bar, Baz):
            pass

        # error: [unresolved-reference] "Name `Foo` used when not defined"
        # error: [unresolved-reference] "Name `Bar` used when not defined"
        class Quux[_T](Foo, Bar, Baz):
            pass

        # error: [unresolved-reference]
        type S = a
        type T = b
        type U = Foo
        # error: [unresolved-reference]
        type V = Bar
        type W = Baz

    def h[T: Bar]():
        # error: [unresolved-reference]
        return Bar()
    type Qux = Foo

def _():
    class C:
        # error: [unresolved-reference]
        def f(self) -> C:
            return self
```

## Base class references

### Not deferred by __future__.annotations

```py
from __future__ import annotations

class A(B):  # error: [unresolved-reference]
    pass

class B:
    pass
```

### Deferred in stub files

```pyi
class A(B): ...
class B: ...
```

## Default argument values

### Not deferred in regular files

```py
# error: [unresolved-reference]
def f(mode: int = ParseMode.test):
    pass

class ParseMode:
    test = 1
```

### Deferred in stub files

Forward references in default argument values are allowed in stub files.

```pyi
def f(mode: int = ParseMode.test): ...

class ParseMode:
    test: int
```

### Undefined names are still errors in stub files

```pyi
# error: [unresolved-reference]
def f(mode: int = NeverDefined.test): ...
```

## Class keyword arguments

### Not deferred in regular files

```py
# error: [unresolved-reference]
class Foo(metaclass=SomeMeta):
    pass

class SomeMeta(type):
    pass
```

### Deferred in stub files

Forward references in class keyword arguments are allowed in stub files.

```pyi
class Foo(metaclass=SomeMeta): ...
class SomeMeta(type): ...
```

### Undefined names are still errors in stub files

```pyi
# error: [unresolved-reference]
class Foo(metaclass=NeverDefined): ...
```

## Lambda default argument values

### Not deferred in regular files

```py
# error: [unresolved-reference]
f = lambda x=Foo(): x

class Foo:
    pass
```

### Deferred in stub files

Forward references in lambda default argument values are allowed in stub files.

```pyi
f = lambda x=Foo(): x

class Foo: ...
```

### Undefined names are still errors in stub files

```pyi
# error: [unresolved-reference]
f = lambda x=NeverDefined(): x
```
