Mismatched types, ssems to be missing a lifetime (?)

Hello, Iam not sure why I am getting this compiler diagnostic error coming up in VSC (my code is below):

error[E0308]: mismatched types
   --> src/main.rs:44:8
    |
33  | async fn select_http_response<ElementRef>(url: &str, xpath: &str) -> Result<Vec<ElementRef>> {
    |                               ---------- expected this type parameter
...
44  |     Ok(selection)
    |     -- ^^^^^^^^^ expected `Vec<ElementRef>`, found `Vec<ElementRef<'_>>`
    |     |
    |     arguments to this enum variant are incorrect
    |
    = note: expected struct `Vec<ElementRef>`
               found struct `Vec<ElementRef<'_>>`
help: the type constructed contains `Vec<ElementRef<'_>>` due to the type of the argument passed
   --> src/main.rs:44:5
    |
44  |     Ok(selection)
    |     ^^^---------^
    |        |
    |        this argument influences the type of `Ok`
async fn select_http_response<ElementRef>(url: &str, xpath: &str) -> Result<Vec<ElementRef>> {
    let response = reqwest::get(url).await?;
    assert!(response.status().is_success());

    let body = response.text().await?;
    // parses string of HTML as a document
    let fragment = Html::parse_document(&body);
    // parses based on a CSS selector
    let elements = Selector::parse(xpath);

    let selection = fragment.clone().select(&elements.unwrap()).collect::<Vec<_>>();
    Ok(selection)
}

#[tokio::main]
async fn main() -> Result<()> {
    let url: String = WWW_IMFDB_ORG.to_string() + "/wiki/Category:Rifle";
    let xpath: String = ".gallerytext > p > a".to_string();

    let guns: Vec<ElementRef> = select_http_response(&url, &xpath).await?;
}

There are two different types called ElementRef involved. There is the concrete ElementRef<'a> that seems to be from the scraper crate, and there is a type parameter named ElementRef that you created here:

async fn select_http_response<ElementRef>

If you use a different name for the type parameter, the error message will be easier to understand:

async fn select_http_response<T>(url: &str, xpath: &str)
    -> Result<Vec<T>> {

If you just want to use the ElementRef type from scraper, you should remove the type parameter completely. You will end up with something like this:

async fn select_http_response<'a>(url: &str, xpath: &str)
    -> Result<Vec<ElementRef<'a>>> {

However, I expect you will then run into errors saying that selection borrows from fragment which does not live long enough. Since the Html is local to the function, you can’t return an ElementRef that borrows from it. After the function returns, the Html is destroyed and the ElementRef is a dangling reference.

Instead, the caller may need to do something like call one function that parses and returns the Html, store that in a variable to keep it alive, and then call a second function that borrows the Html and returns the Vec<ElementRef>.

2 Likes

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.