LINUX.ORG.RU

Rust: несовпадение типов

 


0

2

Есть типа такой код:

   fn run_input_device(dev: &str) {
        let input = MidiInput::new("Some input").unwrap();
        let ports = input.ports();
        let mut port = Option::None;
        for i in &ports {
            if input.port_name(&i).unwrap() == dev {
                port = Some(i);
            }
        };

        let callback = move |stamp: u64, message: &[u8], _| {
            // println!("{}: {:?} (len = {})", stamp, message, message.len());}, ());
            let st = format!("{}: {:?} (len = {}\n", stamp, message, message.len());
            std::io::stdout().write_all(st.as_bytes()).unwrap();
            std::io::stdout().flush().unwrap(); 
        };

        if port.is_some() {
            let conn = input.connect(port.unwrap(), "midir-read-input", callback, ());
        loop {}
    }
}

Компилятор чихает следующим:

    |
116 |             let conn = input.connect(port.unwrap(), "midir-read-input", callback, ());
    |                              ^^^^^^^ one type is more general than the other
    |
    = note: expected type `FnOnce<(u64, &[u8], &mut ())>`
               found type `for<'r> FnOnce<(u64, &'r [u8], &mut ())>`

error: aborting due to previous error
При этом, что характерно, если поставить в аргументы функции connect() вместо названия замыкания его тело, то всё работает на ура. Ничкего не понимаю.

★★★★★

Последнее исправление: meliafaro (всего исправлений: 1)

Скорее всего проблема здесь:

let callback = move |stamp: u64, message: &[u8], _| {
                                                 ^~

так как Rust очень… креативен в выводе типа и лайфтайма у _. Ему надо намекнуть, что это не любой тип, а именно ссылка. Тогда он догадается, что у неё должно быть такое же время жизни, что и у message:

let callback = move |stamp: u64, message: &[u8], _: &_| {

Если подставить замыкание напрямую, то его полёт немного более ограничен.

ilammy ★★★
()
Последнее исправление: ilammy (всего исправлений: 1)
Ответ на: комментарий от ilammy

Чудеса на виражах, ты зацени: let callback: for<'r, 's> fn(u64, &'r [u8], &'s mut _) -> _ = ну и дальше тело коллбэка. Чедесен ваш Раст, да дюже к смекалистости горазд.

meliafaro ★★★★★
() автор топика
Ответ на: комментарий от meliafaro

В Хаскеле так же. Если типы где-то не сходятся, укажи явно, что ты имел в виду, и тогда или ошибка переедет в место возникновения, а не вызова, или компилятор поймёт, что ты имеешь в виду.

unC0Rr ★★★★★
()

А если дать ему самому всё вывести, что будет?

let callback = move |stamp, message, _| {
    /*...*/
};
anonymous
()

А ведь это простейший прикладной код. И эти люди ругают C++, потому что в хроме дескать дофига багов. Но ведь хром на 10 порядков сложнее того кода, что обычно на расте пишут.

anonymous
()
Ответ на: комментарий от anonymous

И? Тут простейший прикладной код с потенциальной ошибкой не компилится. А в C++ - компилится, но не работает. Либо работает, но в каком-то отдельном случае - некорректно.

anonymous
()
Ответ на: комментарий от anonymous

Толстота. От какой-то части - защитит, от какой-то - нет.

anonymous
()
Ответ на: комментарий от MOPKOBKA

2/3 уязвимостей про память, от ошибок с которой rust защищает.

Ну и как у мозиллы успехи с браузером на расте? В сложном проекте предсказуемо произошел обосрамс? Нет сложного софта, нет уязвимостей? Какой действительно сложный софт написан на расте?

anonymous
()

я понял. растаманам лень учить спп, но они не достаточно умны, что бы выучить хацкель.

anonymous
()
Ответ на: комментарий от anonymous

не достаточно

Хейтеры Раста не в состоянии выучить русский.

meliafaro ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.