2

I have this small snippet which works but doesn't look very elegant.

use git2::{Config, Repository}; // git2 = "0.9.2"
use std::path::Path;

fn main() {
    let absolute_path = "Some existing git repository";
    let repo_option = Repository::open(&Path::new(absolute_path));
    let repo = match repo_option {
        Ok(expr) => expr,
        Err(_) => {
            return;
        }
    };

    let remote = match repo.find_remote("origin") {
        Ok(remote) => remote,
        Err(_) => {
            return;
        }
    };

    let url = match remote.url() {
        Some(url) => url,
        None => {
            return;
        }
    };
}

I tried doing this, but it throws errors about "can not return value referencing function parameter repo":

let repo_option = Repository::open(&Path::new(absolute_path));
let url = repo_option
    .and_then(|repo| repo.find_remote("origin"))
    .and_then(|remote| remote.url().ok_or(git2::Error::from_str("failed")));

Complete error output:

error[E0515]: cannot return value referencing function parameter `repo`
  --> src/main.rs:38:26
   |
38 |         .and_then(|repo| repo.find_remote("origin"))
   |                          ----^^^^^^^^^^^^^^^^^^^^^^
   |                          |
   |                          returns a value referencing data owned by the current function
   |                          `repo` is borrowed here

error[E0515]: cannot return value referencing function parameter `remote`
  --> src/main.rs:39:28
   |
39 |         .and_then(|remote| remote.url().ok_or(git2::Error::from_str("failed")));
   |                            ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                            |
   |                            returns a value referencing data owned by the current function
   |                            `remote` is borrowed here

How can I overcome this error?

The intention of asking this question is to learn effective usage of combinators. How do you unwrap a Result on Ok or return from the function on Err? is a related question that solves the issue, but I am confused with the lifetimes while using combinators.

Followed the example from this question How do you unwrap a Result on Ok or return from the function on Err?

In this snippet, I am using repo_option as as_ref, so I that should get Result<&S,&T> but it fails.

    let url = repo_option
        .as_ref()
        .and_then(|repo| repo.find_remote("origin"))
        .and_then(|remote| remote.url().as_ref().ok_or(git2::Error::from_str("failed")))
        .unwrap();

errors:

error[E0308]: mismatched types
  --> src/main.rs:39:26
   |
39 |         .and_then(|repo| repo.find_remote("origin"))
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `git2::error::Error`
   |
   = note: expected type `std::result::Result<_, &git2::error::Error>`
              found type `std::result::Result<git2::remote::Remote<'_>, git2::error::Error>`
ansrivas
  • 597
  • 2
  • 9
  • 14
  • It looks like your question might be answered by the answers of [How do I borrow a reference to what is inside an Option?](https://stackoverflow.com/a/46394300/155423). (replace `Option` with `Result`) If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 13 '19 at 00:42

1 Answers1

1

as_ref() doesn't solve the problem because and_then() is design to consume the value, not to borrow it. As you can see, Remote borrow &self and url() too.

I strongly recommend you to just use ?:

use git2::{Config, Repository}; // git2 = "0.9.2"
use std::path::Path;

fn main() -> Result<(), git2::Error> {
    let absolute_path = "Some existing git repository";
    let repo = Repository::open(&Path::new(absolute_path))?;
    let remote = repo.find_remote("origin")?;
    let url = remote.url().ok_or(git2::Error::from_str("failed"))?;
    Ok(())
}
Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • Thank you for this information: `because and_then() is design to consume the value` Makes absolute sense now :) – ansrivas Aug 13 '19 at 18:50