Cannot infer type IsA<Cancellable> when cancellable is not provided

I am not using threads and I am trying to use gio::FileExt::query_info. It will not compile because I did not provide a cancellable type in the option. The docs say I can just provide a None, but this is not working. What type and how would I implement it so the compiler can accept a None?

error[E0283]: type annotations needed
  --> src/main.rs:16:42
   |
16 |     let info: gio::FileInfo = match file.query_info(
   |                                          ^^^^^^^^^^ cannot infer type for type parameter `P` declared
   |                                                     on the associated function `query_info`
   |
   = note: cannot satisfy `_: IsA<Cancellable>`

My test code is

use gio::File;

fn main() {
    let mut filename = glib::get_user_data_dir().unwrap();
    filename.push("recipes.db");

    let file = File::new_for_path(filename);

    assert!(should_try_load(&file));
}

fn should_try_load (file: &gio::File) -> bool {
    use gio::FileExt;
    let mut result = false;

    let info: gio::FileInfo = match file.query_info(
        &gio::FILE_ATTRIBUTE_TIME_MODIFIED,
        gio::FileQueryInfoFlags::NONE,
        None) {
            Ok(x) => x,
            Err(x) => return result,
    };

    if info.has_attribute(&gio::FILE_ATTRIBUTE_TIME_MODIFIED) {
        let now = glib::DateTime::new_now_utc();
        let mtime = info.get_modification_date_time()
                        .unwrap_or_else(|| now.clone());

        result = now.difference(&mtime) < 86400000000; //G_TIME_SPAN_DAY
    }

    return result
}

You should use either gio::NONE_CANCELLABLE or None::<&gio::Cancellable>

To give some background: The reason behind that being that a) gio::Cancellable is subclassable (you can implement your own subclasses of it, for whatever reason), and b) Option::<&gio::Cancellable> and Option<&YourCancellable> being different types and the compiler not being able to know that for this specific function it doesn’t make any difference.

And example where b) would make a difference is a function that would do other things based on the type than just handling a None value as “not existing”.

For example a

fn unwrap_or_default<T: Default>(v: Option<T>) -> T {
    match v {
        None => T::default(),
        Some(v) => v,
    }
}

To solve this one could imagine using generic type parameter defaults, like on traits or structs, but that’s unfortunately not possible (yet). See https://github.com/rust-lang/rust/issues/36887 for some discussion around that. That would allow us marking this function as “I don’t care what the type is if it’s None, just give me any”.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.