&String
을 어떻게 &str
로 자동으로 변환되는지가 궁금하여 글을 작성한다.
rust
코드를 보다보면 &str
을 매개변수로 받는데 String
타입의 참조를 넘겨도 컴파일에러가 발생하지 않는 것을 볼 수 있다. 아래는 예시 코드이다.
fn main() {
let s = String::from("안녕하세요 wanki 입니다.");
do_something(&s); // &String을 넘겨준다.
}
fn do_something(s: &str) {
println!("{}", s);
}
&String
-> &str
이 자동으로 변환이 되는건가? 라고 생각했다.
fn print_type<T>(s: T) {
println!("{}", type_name::<T>());
}
위 함수를 만들어서 매개변수의 타입을 출력하도록 하였다.
// String type에 &를 붙이면 자동으로 변환이 되는가?
let string = String::from("wanki");
let str = &string;
print_type(str);
print_type(string);
출력 값
&alloc::string::String
alloc::string::String
즉, &
를 붙인다고해서 &String
-> &str
자동 변환이 이루어지지 않는다.
그렇다면 어떻게 매개변수로 넘겼을 때는 자동으로 변환이 되는 것일까?
정답은 바로 Deref
때문이다. Deref
는 *
를 통해서 연관 타입 Target
값으로 변환해주는 트레이트이다. rust에서는 함수의 매개변수로 값을 넘길 때 타입이 다르다면 Deref를 통해 역참조 강제(Deref coercion)
를 시도하는 것이다.
&String
으로 넘긴 매개변수는 &(*String)
으로 역참조 강제
를 시도한 뒤 타입이 일치하다면 컴파일이 된다.
String
은 Deref가 구현이 되어있다. 아래와 같다.
#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for String {
type Target = str;
#[inline]
fn deref(&self) -> &str {
self.as_str()
}
}
참조 http://doc.rust-lang.org/src/alloc/string.rs.html#2604
정리하자면 매개변수로 넘긴 변수의 타입이 일치하지 않는 경우 역참조 강제
를 하게 된다. 이 과정에서 *
를 명시적으로 사용하지 않아도 컴파일러가 알아서 처리하게된다.
Deref
를 구현한 타입의 경우 매개변수의 타입이 일치하지 않는 경우에 역참조 강제
를 통해서 *
을 명시적으로 상요하지 않고 컴파일러가 알아서 처리하도록 한다. Deref
에 대해 이해도가 올라간 것 같다.
Deref를 통해 역참조 강제(Deref coercion)를 시도한다니.. 좋은 정보 감사합니다!