Cannot infer type of AsRef<path>

use  std::env::{current_exe, current_dir};
use std::path::{Path, PathBuf};

fn main() -> Result<(), Error> {
    println!("{:?}", current_exe());
    let path = Path::new("");
    parse_flinks(&path, None);
    Ok(())
}
fn parse_flinks<P: AsRef<Path>, Q: AsRef<Path>>(path_to_flink: &P, q: Option<Q>) -> Result<(), Error>{
    let q = match &q {
        Some(name) => name.as_ref(),
        None => Path::new("default.json"),
    };
//...
    Ok(())
}

parse_flinks(&path, &None);
   |     ^^^^^^^^^^^^ cannot infer type for type parameter `Q` declared on the function `parse_flinks`

What is needed for accessible None argument?

If you want to call the function like this, you’ll need to manually specify the type of the parameter Q. Either in the function call, i.e. something like parse_flinks::<_, &Path>(&path, None), or for the None, so something like parse_flinks(&path, None::<&Path>). If you want better user experience, you could consider creating two distinct methods, e.g. fn parse_flinks<P: ?Sized + AsRef<Path>>(path_to_flink: &P) as well as fn parse_flinks_with_q<P: ?Sized + AsRef<Path>, Q: ?Sized + AsRef<Path>>(path_to_flink: &P, q: &Q) (where the implementation of the parse_flinks just calls parse_flinks_with_q with the appropriate default value in the second argument).

1 Like

Without ?Sized

58  |     parse_flinks_with_q(path_to_flink, &None::<Path>);
    |     -------------------                ^^^^^^^^^^^^^ doesn't have a size known at compile-time

With

514 | pub enum Option<T> {
    |                 ^ required by this bound in `std::option::Option`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
53  - fn parse_flinks_with_q<P: ?Sized + AsRef<Path>, Q: ?Sized + AsRef<Path>>(path_to_flink: &P, q: &Option<Q>){
53  + fn parse_flinks_with_q<P: ?Sized + AsRef<Path>, Q: AsRef<Path>>(path_to_flink: &P, q: &Option<Q>){
    | 

What i wrote:

fn parse_flinks_with_q<P: ?Sized + AsRef<Path>, Q: ?Sized + AsRef<Path>>(path_to_flink: &P, q: &Option<Q>){
    
}

fn parse_flinks<P: ?Sized + AsRef<Path>>(path_to_flink: &P){
    parse_flinks_with_q(path_to_flink, &None::<Path>);
}

I think didn't understand)

Could you be more specific about what you didn’t understand? Option<T> does not support unsized arguments for T; but in your original example an argument like &P where P: AsRef<Path> could support unsized types, so I added an ?Sized bound where it’s appropriate in my code examples. This has the effect that you can pass types like &Path or &str directly for the &P argument instead of needing to create double-indirections like &&Path or &&str.

Another alternative is to drop the &s entirely in the argument types and do thing s like fn parse_flinks<P: AsRef<Path>>(path_to_flink: P) instead of fn parse_flinks<P: ?Sized + AsRef<Path>>(path_to_flink: &P). The former is even a bit more general.

By the way, note that my suggestion was to have parse_flinks_with_q not take an Option anymore at all.

If you do still want an option, then parse_flinks_with_q<P: …, Q: AsRef<Path>>(…, q: Option<Q>) would probably be the best option (but something like parse_flinks_with_q<P: …, Q: ?Sized + AsRef<Path>>(…, q: Option<&Q>) would work, too).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.