Kirill
Kirill
или вот, второй вариант https://phpstan.org/r/ebe2d6dc-dd2e-4ab3-bfa0-d4e4b186f0f4
Kirill
без параметрических темплейтов
Kirill
у тебя аргумент в инвариантной позиции потому что
Kirill
поэтому он не даёт потомка засунуть
Kirill
и как видишь, в обоих вариантах важно что Child instanceof Parent
Юра
Ну так у тебя другой пример
Kirill
так ты себе подогнал пример под инвариантную позицию, лол)
Юра
Ты грубо говоря создал другую реализацию test для другого T
Юра
и там не вопрос ковариантности
Kirill
ну замени аргумент на возвращаемый результат и всё заработает
Юра
Еше раз твой пример не доказывает что MyArray<ParentClass> == MyArray<ChildClass>
Kirill
как раз доказывает
Kirill
убери инстансоф и всё поломается
Юра
по другой причине
Юра
короче )
Юра
нету времени сори
Aleksandr Khristenko
как раз доказывает
Нет. Они явно не равны. Там может быть один подтипом другого но явно не равны.
Юра
в твоем примере ты получил
/**
* @param MyArray<ParentClass> $a
* @return void
*/
function test_ParentClass(MyArray $a) {
}
/**
* @param MyArray<ChildClass> $a
* @return void
*/
function test_ChildClass(MyArray $a) {
}
Kirill
Юра
как увидишь разницу пиши
Kirill
эквивалентное равенство, а не строгое
Kirill
Kirill
а во втором?
Юра
ну так понятно
Юра
во втором ты явно добавил covariant
Kirill
ну да
Юра
а я говорил про по-дефолту
Kirill
так по дефолту замени аргумент на возвращаемое значение
Kirill
чтоб у тебя не в инвариантной позиции оно было
Kirill
я ж говорю, что ты подогнал пример под себя) а я его поправил просто
Юра
ты видимо упрямый шопипец
Aleksandr Khristenko
Kirill
ну типа вот это почему тогда работает если типы не эквивалентны? https://phpstan.org/r/159bb4e9-a8f2-46c5-adf4-6671d60835ec
Kirill
а, там список items может мутировать
Kirill
ща
Kirill
а, лол, вы правы
Kirill
переставил позицию и всё равно не работает
Kirill
Да
ты не прав, как и я)
Я проверил.
В стане будет A|B
Kirill
если заткнуть туда A instanceof B, то на выходе внутри стана будет non-empty-list<A|B>
Kirill
https://phpstan.org/r/34d49edb-2d16-46f5-92aa-e3ce1f1debf7
Юра
Ну это уже union type
Юра
Который никак опять же не относится к ковариантности
Kirill
ага
Юра
Но спасибо за фцию не знал что такое есть
Kirill
но я разные варианты попробовал
Kirill
и через dumpType подампил
Kirill
это оказалось самым интересным
Kirill
короче, я так понял - оно не вычисляет граф наследования для аргументов или что?
Юра
Ты про что именно?
Kirill
про Type<A> -> Type<B>
Kirill
потому что я потыркал и везде оно действительно разное
Kirill
т.е. работает не так, как я предполагал
Юра
Потому что по дефолту это разные типы
Юра
Если ты говоришь что это covariant
Юра
То должен соблюдать определенные правила
Юра
Нельзя просто так добавить это
Юра
Возможно стан будет ругаться если правила будут нарушены
Юра
Не
Kirill
*зависит от того где располагается T
Юра
Да
Kirill
а дальше уже согласно лисков сабтитьюшн
Юра
В принимаемых иди возвращаемых позициях
Юра
В других языках ещё другие могут быть позиции
Kirill
в возвращаемых сужение, в арументах расширение
Kirill
и согласно этим правилам или строгое соответсвие, или сабтайп в одну сторону или в другую
Kirill
но так как у тебя там нет использования, то допускается любое типа
Kirill
ну у меня в голове так было
Юра
Главное другое. Что По умолчанию это разные типы
Kirill
ну по дефолту строгое соответсвие
Kirill
я про это и говорю
Юра
Вариантность влияет ещё не только на допустимую позицию а и на то можно ли в наследниках переопределить метод и заменить тип на более строгий или более общий
Юра
Например аргумент обычно можно заменить на более общий
Юра
А ретурн на более специфичный
Юра
Хз как в пхп
Kirill
в рамках языка именно так
Kirill
и для свойств тоже
Kirill
но там чуть специфично