TGViewer
Пых Пых @phpyh · 7.86K subscribers
Post #950 8.12K
Горю с PHPStan

Все привыкли ограничивать дженерики типов сверху (upper bound): @template T of U. Но бывают ситуации, когда дженерик логично ограничить снизу (lower bound), в частности другим дженериком.

Пример. Представьте, что существует ссылка на какое-то значение и нужно заапкастить (преобразовать в супертип) тип значения в этой ссылке:


use Psr\Log\LoggerInterface as Logger;
use Monolog\Logger as Monolog;
use Typhoon\Type;

/**
* @template T
*/
interface Ref
{
/**
* @template S, где S — супертип для T
* @param Type<S> $super
* @return self<S>
*/
public function as(Type $super): self;
}

/**
* @param Ref<Monolog> $ref
* @return Ref<Logger>
*/
function upcastLogger(Ref $ref): Ref
{
return $ref->as(Type\objectT(Logger::class));
}


В Java wildcards это выражается так: ? super T. В Scala оператором: [S >: T].

В PHPStan, о чудо, тоже начали об этом думать аж в 2021 году: phpstan/phpstan/issues/5179.

Я был в курсе, и, не глядя в issue, решил попробовать. Пишу:


/**
* @template S super T
* @param Type<S> $super
* @return self<S>
*/
public function as(Type $super): self;


Анализатор говорит No issues!, я радостно продолжаю работать. А потом намеренно пробую вызвать $ref->as(Type\stringT) и всё равно вижу No issues!

Разбираюсь и понимаю, что PHPStan поддержал пару лет назад синтаксис super, но только в PHPDoc-парсере! Исходный тикет в анализаторе всё ещё не закрыт!

Представьте, что в PHP добавили property hooks только на уровне синтаксиса — по факту они вообще не работают. Как вам такая фича?

Между PHP-анализатором и PHPDoc-парсером есть фундаментальный каплинг (то есть, кохижен). Нельзя поправить одно и не учесть это в другом. Нормально разделять компоненты и делать один более универсальным, но тогда должны быть фича-флаги, при помощи которых второй компонент выключает (opt-out) или не включает (opt-in) неподдерживаемое поведение в первом.
⸻
Этот пост я разместил неделю назад в 🐘 PHPeople.
GitHub Lower bounds support · Issue #5179 · phpstan/phpstan Support of lower bounds for generics / templates Hi, first of all, thanks for all the great work, that has been done on generics lately. To have generics more complete I suggest to introduce lower ...
  • 😁 30
  • 👍 12
  • ❤ 3
  • 🤯 3
  • 🥴 3
More from @phpyh
  1. Sep 15, 2026Сейчас один человек с AI может выполнять работу целого IT-отдела. Только хуёво
  2. Sep 12, 2026Спасибо за заявки! Всем напишу в понедельник. Осталось 1 место.
  3. Sep 11, 2026Хардкорный курс асинхронного PHP https://hardcourse.ru/php/async
  4. Sep 11, 2026Ещё полчасика надо — сайт готов, расписываю программу! 🙏
  5. Sep 10, 2026Краткое содержание: завтра в 12:00 открываю набор на Хардкорный курс асинхронного PHP с уч…
  6. Sep 10, 2026Post #1011
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →