169 похожих чатов

Что-То я думал, что понимаю, как работает реификация, но как-то

не могу объяснить такое поведение, как ниже.
Может кто-то поможет?
import kotlin.reflect.KType

fun main() {
println(object : KTypeToken<List<*>>() {}.type)
println(typeOf<List<*>>())
}

abstract class KTypeToken<T> {
val type: KType = this::class.supertypes.first { it.classifier == KTypeToken::class }.arguments[0].type!!
}

inline fun <reified T> typeOf(): KType = object : KTypeToken<T>() {}.type

Выводит
kotlin.collections.List<*>
[ERROR : Unknown type parameter 0. Please try recompiling module containing "[container not found]"]

42 ответов

73 просмотра

А причём тут реификация? То, что ошибка странно, но там ведь даже она не используется вроде

Andrey-Antipov Автор вопроса
Ilya
А причём тут реификация? То, что ошибка странно, н...

Нет, она используется в функции typeOf для параметра T

Andrey-Antipov Автор вопроса
Ilya
Так оно и без reified скомпилится

Да, компилится, но что-то не работает :(

Andrey Antipov
Да, компилится, но что-то не работает :(

Та же ошибка? А без inline тоже не работает?

Andrey-Antipov Автор вопроса
Ilya
Та же ошибка? А без inline тоже не работает?

Без inline и не будет 100%. Там же трюк с анонимным наследником KTypeToken, чтобы сохранить в рантайме информацию о типе, подставленном вместо T, который стирается. А если без inline и reified, то эта информация и не доедет до момента создания наследника, создастся как наследник сырого типа. Не понятно, почему с inline и reified не доезжает.

Vladimir Petraković
Так-то не должно 🤔

Почему? Насколько я знаю оно не скомпилится ток если T::class используется

Andrey-Antipov Автор вопроса

я не знаю почему вы так долго это обсуждаете, reified сохраняет класс и не стирает его, но вы в typeOf его используете как дженерик класса, который в любом случае е может быть reified, так что то, что вы делаете в инлайн функции - бессмысленно.

Ilya
Почему? Насколько я знаю оно не скомпилится ток ес...

Так здесь точно так же нужен конкретный тип

Vladimir Petraković
Так здесь точно так же нужен конкретный тип

Мы же просто дженерик в класс передаём, это делали в джаве и без reified

Vladimir Petraković
Ну вообще да, он может и стереться

Ну он и сотрётся, я об этом с самого начала и говорю)

Может, это из-за wildcard?

Vladimir Petraković
В такой функции не должен

В функции нет, а в классе да

Andrey-Antipov Автор вопроса
Vladimir Petraković
Может, это из-за wildcard?

Нет: fun main() { println(object : KTypeToken<List<String>>() {}.type) println(kTypeOf<List<String>>()) } kotlin.collections.List<kotlin.String> [ERROR : Unknown type parameter 0. Please try recompiling module containing "[container not found]"]

Andrey-Antipov Автор вопроса
Ilya
И всё-таки попробуйте без inline

Пробовал уже. Тот же результат

Ilya
И всё-таки попробуйте без inline

Без inline вызов этой функции не будет приводить к созданию нового анонимного класса, в котором сохранится информация о типе

Vladimir Petraković
Без inline вызов этой функции не будет приводить к...

Так если оно и без inline и с inline не работает, то в данном случае это не важно, я просто локализирую проблему

Andrey Antipov
Без inline и не будет 100%. Там же трюк с анонимны...

предполагаю что нужно иссью, не подумали, что так будут использовать

Aλex Sokol
предполагаю что нужно иссью, не подумали, что так ...

Там проблема только с самой функцией, а не с inline или reified

Ilya
Там проблема только с самой функцией, а не с inlin...

нет, проблема с тем, что reified типы не доезжают до анонимных наследников

Andrey Antipov
Без inline и не будет 100%. Там же трюк с анонимны...

Этот трюк не работает. Сохраняйте T::class.

Andrey-Antipov Автор вопроса
Ilmir
Этот трюк не работает. Сохраняйте T::class.

И как мне T::class поможет сохранить в рантайме полную информацию о типе List<String>?

Ilmir
Этот трюк не работает. Сохраняйте T::class.

А как оно тогда там работает? https://t.me/kotlin_lang/223602

Ilmir
Этот трюк не работает. Сохраняйте T::class.

и что даже иссью не надо писать, не сделать это никак?

Andrey-Antipov Автор вопроса
Ilmir
Этот трюк не работает. Сохраняйте T::class.

И да, сам трюк с анонимным классом, прекрасно работает. А вот inline reified функция на его основе - нет

Vladimir Petraković
А как оно тогда там работает? https://t.me/kotlin_...

Через сохранение типа и передачи его же в родителя. Очень хитро сделано: https://github.com/FasterXML/jackson-core/blob/9e33b3a5b53c7bce13ae2a00dcf097fcab919969/src/main/java/com/fasterxml/jackson/core/type/TypeReference.java

Andrey-Antipov Автор вопроса
Ilmir
Через сохранение типа и передачи его же в родителя...

Ну внутри там всё хитро, конечно. Но как это связано с тем, что в одном случае компилятор создаёт классы с конкретным типом для каждого вызова инлайн-функции, а в другом - нет?

Aλex Sokol
и что даже иссью не надо писать, не сделать это ни...

Ишью надо делать. По идее, это баг в kotlin.reflect, так как в джавовом рефлекшне всё работает.

Andrey-Antipov Автор вопроса
Andrey Antipov
Это не в рефлекшене проблема

Ну ХЗ. До ввода typeOf, официальный workaround использовал джавовый рефлекшн: https://gist.github.com/udalov/bb6f398c2e643ee69586356fdd67e9b1. А то, что reified T не передаётся в класс - это логично, если учесть, что инлайнер работает на байткоде, а там уже java.lang.Object вместо T.

Vladimir Petraković
Ну внутри там всё хитро, конечно. Но как это связа...

В одном он вкомпиливает нужный тип сразу, а в другом - через байткод, к котором T уже стирается.

Andrey-Antipov Автор вопроса
Ilmir
Ну ХЗ. До ввода typeOf, официальный workaround исп...

Да, похоже бага в kotlin.reflection. Если написать аналогичный код для java.reflection, то reified inline работает

Похожие вопросы

Обсуждают сегодня

30500 за редактор? )
Владимир
47
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Подскажите пожалуйста, как в CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); получить наз...
A Z
7
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
1
Он в одиночку это дело запилил или была какая-то команда?
Aquinary
12
~ 2m21s  nix shell github:nixos/nixpkgs#stack ~  stack ghc -- --version error: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:...
Rebuild your mind.
6
Всем привет, нужна как никогда, нужна помощь с IO в загрузчике. Пишу в code16 после установки сегментных регистров, пишу вывод символа. Пробовал 2 варианта: # 1 mov $0x0E, %a...
Shadow Akira
14
Карта сайта