This code is from standard library. what does &**self
here?
impl AsRef<OsStr> for String {
#[inline]
fn as_ref(&self) -> &OsStr {
(&**self).as_ref()
}
}
This code is from standard library. what does &**self
here?
impl AsRef<OsStr> for String {
#[inline]
fn as_ref(&self) -> &OsStr {
(&**self).as_ref()
}
}
Follow the individual expressions from innermost to outermost:
self
is of type &String
. This is determined by the function signature. So, it's a pointer to a pointer to text.*self
is of type String
; we've looked at where the reference points.**self
is of type str
; we've looked at where the String
points.&**self
is of type &str
; we've taken a reference to the str
.as_ref()
call's input is &str
and its output is &OsStr
, so it must be calling the impl AsRef<OsStr> for str
.In general, &**self
will appear when:
String
)&self
(here, AsRef::as_ref()
)str
)Often this sort of deep dereferencing is unnecessary because method lookup will auto-dereference for you, but in this case, self.as_ref()
would just end up invoking impl AsRef<OsStr> for String
itself, creating infinite recursion. Explicitly dereferencing reaches the implementation that is actually needed.
In this sort of situation, I usually prefer to use a more explicit form of the call so that I get a compile error instead of infinite recursion if I get something wrong:
str::as_ref(&**self)
or
self.as_str().as_ref()
Nit: Because as_ref
takes &self
, the relevant implementation is actually AsRef<OsStr> for str
.
how do we know *String
will result in str
? there is any code in the std library for that?
Yes; the deref operator *
is overloaded for String
via an implementation of std::ops::Deref<Target=str>
.
Whoops, yes, of course. I knew that, but wrote the wrong thing. Fixed.
additionally, this style can be used to then rely on deref-coercion, and write:
str::as_ref(self)