Αλεχ
спасибо
Cat
Alex
Alex
Cat
мне, если честно, казалось, что эта функциональность не для этого придумана; ну да ладно
Alex
Alex
Alex
:)))
Alex
Спасибо, товарищи. Вроде осознал.
Alex
Одно осталось не ясным.
Alex
Если в качестве возвращаемого типа генерится тип-обёртка, реализующий указанный трейт, то каким образом он далее разворачивается, если далее этот тип считается исходным?
Например при fn()-> impl Iterator<Item=&i32>{ [42].iter() }
вернётся "тайно-магически-сгенерённая" обёртка-итератор, содержащий результат от [42].iter(). Т.е. итератор в итераторе. Так?
Αλεχ
#[no_mangle]
pub extern fn foobarbaz() -> impl Fn() -> i32 {
|| 10
}
становится
; Function Attrs: nounwind uwtable
define void @foobarbaz() unnamed_addr #1 !dbg !74 {
start:
ret void, !dbg !78
}
Αλεχ
лентяй даже тип не записывает
Alex
Или вернётся исходный - именно тот, что вернулся из [42].iter() ?
Αλεχ
Αλεχ
по крайней мере я минус трактую так
Αλεχ
так я вот и спросил поэтому
պլհկ
Alex
Alex
Αλεχ
задница какая-то нарисована
Αλεχ
доктор, что со мной?
Cat
чё пристал
Αλεχ
Αλεχ
это ты пристал
Cat
ладн
Alex
исходный
Т.е. структура-обёртка генерится только для Fn?
Cat
Cat
а просто "трейт" итератор
Cat
где внутри у него будет Item=... и прочее, что необходимо
Cat
если бы возвращался изначальный тип, то это были бы темплейты из С++, которые генерируют уникальную функцию для каждого типа
Alex
Я понял про всё кроме функций (не ||{})
պլհկ
но Fn это не функция
պլհկ
а ||{}
պլհկ
функция это fn
Alex
Пример:
fn foo() -> impl Fn {
fn inner()->(){}
inner
}
let what_type = foo();
Cat
Fn трейт разве?
պլհկ
да
Cat
воу, пора спать точно
Alex
Что в what_type и что там реально будет лежать?
պլհկ
function pointer
Cat
Αλεχ
Alex
Αλεχ
#[no_mangle]
pub extern fn foobarbaz() -> impl Fn() -> i32 {
|| 10
}
становится
; Function Attrs: nounwind uwtable
define void @foobarbaz() unnamed_addr #1 !dbg !74 {
start:
ret void, !dbg !78
}
Αλεχ
видим, что impl fn становится unnamed_addr #1
Αλεχ
кстати удобно no_mangle использовать, чтобы в LLVM находить нужную функцию
Alex
Круто. Теперь понял!
Alex
Спасибо!
Αλεχ
да всегда пожалуйста :D
Αλεχ
я вот научился LLVM компилятором пользоваться пока разбирался
Alex
А можно ещё вопрос?
- это риторически вопрос. Всё равно спрошу.
Alex
Кто может для идиота по русски разъяснить в какой момент статик диспатч превращается в дайнамик?
Например
let foo :AsRef<_> = something; foo.as_ref();
let bar :&mut AsRef<_> = something_else; bar.as_ref();
fn foo_fn<T>(foo: AsRef<T>) { foo.as_ref(); }
fn oof_fn<T>(foo: &AsRef<T>) { foo.as_ref(); }
Что здесь is dynamic dispatch and why?
Αλεχ
Пусть меня поправят, если я ошибаюсь
Αλεχ
но динамик диспатч происходит если ты передаешь трейт объект
Αλεχ
это любой бокс на трейт
Αλεχ
и передача через трейт параметр
Alex
պլհկ
Alex
Cat
а я думал статик это fn<T: Clone> a(t: T), а динамик это fn a(t: &Clone)
Αλεχ
ЯТП в первых двух случаях компилятор будет достаточно умный чтобы соптимизировать, а при вызове функций он передает трейт объект, значит в последних двух будет динамика
Αλεχ
ну это то же, что я и сказал
Cat
ну ок, значит очень сильно туплю
Αλεχ
Αλεχ
когда ты делаешь t: T
Αλεχ
у тебя компилятор генерирует для каждого типа нужную перегрузку
Αλεχ
где передается конкретная структура
Cat
стой, я-то не против
Αλεχ
которая естественно статика
Αλεχ
а когда &Clone - одна функция которая принимает динамический объект
Alex
Αλεχ
Αλεχ
в ООП у тебя объект хранит в себе инфу о типе
Αλεχ
так работают виртуальные вызовы