<?php

interface Stringable
{
    /** @return string */
    function __toString();
}

/**
 * @template TClass as object
 */
class ReflectionAttribute
{
    const IS_INSTANCEOF = 2;

    private function __construct()
    {
    }

    /**
     * @return non-empty-string
     *
     * @psalm-pure
     */
    public function getName() : string
    {
    }

    /**
     * @psalm-pure
     * @return int-mask-of<Attribute::TARGET_*>
     */
    public function getTarget() : int
    {
    }

    /** @psalm-pure */
    public function isRepeated() : bool
    {
    }

    public function getArguments() : array
    {
    }

    /**
     * @return TClass
     */
    public function newInstance() : object
    {
    }

    /**
     * @return never-return
     */
    private function __clone()
    {
    }
}

/**
 * @template-covariant T as object
 *
 * @property-read class-string<T> $name
 */
class ReflectionClass implements Reflector {
    /**
     * @return non-empty-string|false
     * @psalm-pure
     */
    public function getFileName(): string|false {}

    /**
     * @return positive-int|false
     * @psalm-pure
     */
    public function getStartLine(): int|false {}

    /**
     * @return positive-int|false
     * @psalm-pure
     */
    public function getEndLine(): int|false {}

    /**
     * @return non-empty-string|false
     * @psalm-pure
     */
    public function getDocComment(): string|false {}

    /**
     * @template J as object
     * @param self<J>|class-string<J> $class
     * @psalm-assert-if-true self<T&J> $this
     * @psalm-pure
     */
    public function isSubclassOf(self|string $class): bool {}

    /**
     * @template J as object
     * @param self<J>|interface-string<J> $interface
     * @psalm-assert-if-true self<T&J> $this
     * @psalm-pure
     */
    public function implementsInterface(self|string $interface): bool {}

    /**
     * @return non-empty-string|false
     *
     * @psalm-pure
     */
    public function getExtensionName(): string|false {}

    /**
     * @param list<mixed>|array<string, mixed> $args
     *
     * @return T
     */
    public function newInstanceArgs(array $args): object {}
}

/** @psalm-immutable */
class ReflectionClassConstant
{
    public const IS_PUBLIC = 1;
    public const IS_PROTECTED = 2;
    public const IS_PRIVATE = 4;

    /** @return non-empty-string|false */
    public function getDocComment(): string|false {}
}

abstract class ReflectionFunctionAbstract implements Reflector
{
    /**
     * @return non-empty-string|false
     *
     * @psalm-pure
     */
    public function getDocComment(): string|false {}

    /**
     * @return positive-int|false
     *
     * @psalm-pure
     */
    public function getStartLine(): int|false {}

    /**
     * @return positive-int|false
     *
     * @psalm-pure
     */
    public function getEndLine(): int|false {}

    /**
     * @return non-empty-string|false
     *
     * @psalm-pure
     */
    public function getFileName(): string|false {}

    /**
     * @return non-empty-string|false
     *
     * @psalm-pure
     */
    public function getExtensionName(): string|false {}
}

/** @psalm-immutable */
class Attribute
{
    public int $flags;

    public const TARGET_CLASS = 1;
    public const TARGET_FUNCTION = 2;
    public const TARGET_METHOD = 4;
    public const TARGET_PROPERTY = 8;
    public const TARGET_CLASS_CONSTANT = 16;
    public const TARGET_PARAMETER = 32;
    public const TARGET_ALL = 63;
    public const IS_REPEATABLE = 64;

    /**
     * @param int-mask-of<self::*> $flags
     */
    public function __construct(int $flags = self::TARGET_ALL)
    {
    }
}

class ReflectionProperty implements Reflector
{
    /**
     * @return non-empty-string|false
     *
     * @psalm-pure
     */
    public function getDocComment(): string|false {}
}

/** @psalm-immutable */
class ReflectionUnionType extends ReflectionType {
    /** @return non-empty-list<ReflectionNamedType> */
    public function getTypes(): array {}
}

class UnhandledMatchError extends Error {}

/**
 * @psalm-immutable
 *
 * @template-covariant Start of string|DateTimeInterface
 * @implements IteratorAggregate<int, DateTimeInterface>
 */
class DatePeriod implements IteratorAggregate
{
    const EXCLUDE_START_DATE = 1;
    /**
     * @param Start $start
     * @param (Start is string ? 0|self::EXCLUDE_START_DATE : DateInterval) $interval
     * @param (Start is string ? never : (DateTimeInterface|positive-int)) $end
     * @param (Start is string ? never : 0|self::EXCLUDE_START_DATE) $options
     */
    public function __construct($start, $interval = 0, $end = 1, $options = 0) {}

    /** @psalm-return (Start is string ? Iterator<int, DateTime> : Iterator<int, Start>) */
    public function getIterator(): Iterator {}
}

/**
 * @psalm-pure
 *
 * @param resource|null $context
 *
 * @return ($associative is false|0 ? list<string> : array<string, string|list<string>>)|false
 *
 * @psalm-taint-sink ssrf $url
 */
function get_headers(string $url, bool $associative = false, $context = null) : array|false {}

/**
 * @psalm-pure
 *
 * @psalm-flow ($values) -> return
 */
function pack(string $format, mixed ...$values): string {}

final class CurlHandle
{
    private function __construct()
    {
    }
}

final class CurlMultiHandle
{
    private function __construct()
    {
    }
}

final class CurlShareHandle
{
    private function __construct()
    {
    }
}
