Repository: rust
Issue: Clippy fails to fix unnecessary_to_owned
Labels: C-bug,A-clippy

Clippy told me to file a bug report after it reports three occurrences of "unnecessary_to_owned" in a single method that it can't fix.

```
hdt$ cargo clippy --fix 
    Checking hdt v0.0.8 (/home/konrad/tmp/hdt)
warning: failed to automatically apply fixes suggested by rustc to crate `hdt`

after fixes were automatically applied the compiler reported errors within these files:

  * src/hdt_graph.rs

This likely indicates a bug in either rustc or cargo itself [...]

The following errors were reported:
error[E0521]: borrowed data escapes outside of function
  --> src/hdt_graph.rs:86:14
   |
51 | fn auto_term<T: Data>(s: &str) -> Result<Term<T>, TermError> {
   |                       -  - let's call the lifetime of this reference `'1`
   |                       |
   |                       `s` is a reference that is only valid in the function body
...
86 |         _ => Term::<T>::new_iri(s),
   |              ^^^^^^^^^^^^^^^^^^^^^
   |              |
   |              `s` escapes the function body here
   |              argument requires that `'1` must outlive `'static`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0521`.
Original diagnostics will follow.

warning: unnecessary use of `to_owned`
  --> src/hdt_graph.rs:69:25
   |
69 |                         rest[tag_index + 1..].to_owned(),
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `&rest[tag_index + 1..]`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
   = note: `#[warn(clippy::unnecessary_to_owned)]` on by default

warning: unnecessary use of `to_owned`
  --> src/hdt_graph.rs:85:43
   |
85 |         Some('_') => Term::<T>::new_bnode(s[2..].to_owned()),
   |                                           ^^^^^^^^^^^^^^^^^ help: use: `&s[2..]`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned

warning: unnecessary use of `to_owned`
  --> src/hdt_graph.rs:86:33
   |
86 |         _ => Term::<T>::new_iri(s.to_owned()),
   |                                 ^^^^^^^^^^^^ help: use: `s`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned

warning: `hdt` (lib) generated 3 warnings (run `cargo clippy --fix --lib -p hdt` to apply 3 suggestions)
warning: `hdt` (lib test) generated 3 warnings (3 duplicates)
    Finished dev [unoptimized + debuginfo] target(s) in 0.88s
```

The method in question is:

```rust
pub trait Data:
    AsRef<str> + Clone + Eq + From<std::boxed::Box<str>> + From<String> + From<&'static str> + Hash
{
}
impl<T> Data for T where
    T: AsRef<str> + Clone + Eq + From<std::boxed::Box<str>> + From<String> + From<&'static str> + Hash
{
}

impl<T: Data> HdtGraph<T> {
    /// Wrapper around Hdt.
    pub const fn new(hdt: Hdt) -> Self {
        HdtGraph { hdt, phantom: PhantomData {} }                                    
    }
    /// Size in bytes on the heap.
    pub fn size_in_bytes(&self) -> usize {
        self.hdt.size_in_bytes()
    }
}
        
const XSD_STRING: &str = "http://www.w3.org/2001/XMLSchema#string";
        
/// Create the correct Sophia term for a given resource string.
/// Slow, use the appropriate method if you know which type (Literal, URI, or blank node) the string has.
fn auto_term<T: Data>(s: &str) -> Result<Term<T>, TermError> {
    match s.chars().next() {
        None => Err(TermError::InvalidIri(String::new())),
        Some('"') => match s.rfind('"') {
            None => Err(TermError::UnsupportedDatatype(s.to_owned())),
            Some(index) => {
                let lex = s[1..index].to_owned();
                let rest = &s[index + 1..];
                // literal with no language tag and no datatype
                if rest.is_empty() {    
                    //let dt_string: sophia::term::iri::Iri<&str> = Iri::<&str>::new_unchecked(XSD_STRING);
                    let dt_string = Iri::<&str>::new_unchecked(XSD_STRING);
                    return Ok(Term::<T>::from(Literal::new_dt(lex, dt_string)));
                }
                // either language tag or datatype
                if let Some(tag_index) = rest.find('@') {
                    return Ok(Term::<T>::from(Literal::new_lang_unchecked(
                        lex,
                        rest[tag_index + 1..].to_owned(),
                    )));
                }
                // datatype
                let mut dt_split = rest.split("^^");
                dt_split.next(); // empty
                match dt_split.next() {
                    Some(dt) => {
                        let unquoted = dt[1..dt.len() - 1].to_owned().into_boxed_str();
                        let dt = Iri::<Box<str>>::new_unchecked(unquoted);
                        Ok(Term::<T>::from(Literal::new_dt(lex, dt)))
                    }
                    None => Err(TermError::UnsupportedDatatype(s.to_owned())),
                }
            }
        },
        Some('_') => Term::<T>::new_bnode(s[2..].to_owned()),
        _ => Term::<T>::new_iri(s.to_owned()),
    }
}
```

`rustc --version --verbose`:
```
rustc 1.68.0-nightly (77429957a 2023-01-01)
binary: rustc
commit-hash: 77429957a0e9c90a26c89def061ffdd4bae5ccb9
commit-date: 2023-01-01
host: x86_64-unknown-linux-gnu
release: 1.68.0-nightly
LLVM version: 15.0.6
```

The problem can be replicated in <https://github.com/KonradHoeffner/hdt/commit/197b72879a041cea1ee1546281b1b21286d42051>.