1. 11
  1. 3

    The last example is pretty interesting.

    fn arc_borrow(foo: &Arc<String>) -> &str {
        foo.as_ref()
    }
    

    The borrow ensures that the underlying String outlives the function arc_borrow. It also conveniently provides a lifetime (an implicit one) to use for the return type.

    With a plain Arc argument, it’s possible that the Arc could decrement to 0 when dropped at the end of the function, so the compiler disallows returning a borrow of the String’s underlying data.

    1. 1

      This seems to be missing the point. The problem isn’t whether the Arc owns the string or not but what the lifetime of the Arc is. In all but the last example the Arc is dropped when the function returns, so anything it may be holding may be dropped. Therefore returning a reference to the contents isn’t possible.

      In the Arc<&str> example the Arc isn’t really relevant. The lifetime of the referenced string doesn’t depend on the lifetime of the Arc at all.

      In the final example &Arc<String> this works because the returned reference is explicitly tied to the lifetime of the Arc (borrow).

      What I do wish we had was the ability to have something like Arc<T>::map(self, impl Fn(&T) -> V) -> Arc<V> where you could borrow something from the Arc and wrap it back up in the an Arc. This would make the first example naturally work.

      fn arc_borrow(s: Arc<String>) -> Arc<&str> {
        s.map(|s| s.as_str())
      }
      

      Of course this example isn’t terribly exciting but it is very nice when trying to borrow a single field from Arc<AppState>.

      IIRC C++’s std::shared_ptr can do this.