먼저 짚고 넘어가야할건 Rust에선 &T가 하나의 독립적인 타입이라
T랑은 별도로 자기만의 트레잇 구현과 메소드들을 가진다는것임
그러면 &&&Foo가 어떻게 Foo의 메소드를 땡겨쓰는걸까?
비밀은 바로 Deref trait인데
이걸 구현한 타입이면 컴파일러가 그 대상 타입의 레퍼런스를 따라 올라가면서 트레잇 구현과 메소드를 찾아보려고 시도함
그리고 &T가 바로 그 Deref를 구현하고있음
&T가 T를 대상으로 Deref를 구현하고있음
여기서 중요한건 Deref는 Deref(T)같은 제네릭 인자대신 Target이라는 associated type을 갖고있는데
이것은 Deref 구현이 항상 *유일* 하다는것을 의미함
Rust에 익숙치 않은 사람은 마치 &T가 &T가 된거처럼 볼수 있을건데
실제로는 Self가 &T라서 &&T가 &T가 되는거임
다시 코드로 돌아와서 컴파일러의 Deref 과정을 따라가보자
1. &&&Foo에는 foo 메소드가 없다
2. &&&Foo는 &&Foo에 대한 Deref를 구현하고있다
3. &&Foo에는 foo 메소드가 없다
4 .&&Foo는 &Foo에 대한 Deref를 구현하고 있다
5. &Foo에는 foo 메소드가 없다
6. &Foo는 Foo에 대한 Deref를 구현하고 있다
7. Foo에는 *&self를 사용하는[1]* foo 메소드가 있다
8. 2 4 6을 따라서 각각의 Deref 구현을 한번씩 사용해 Foo의 참조를 얻고 그걸 메소드에 사용
[1] 여기서 foo가 &mut self라면 DerefMut가 필요하고 self라면 DerefMove같은 트레잇은 아직 없어서 Foo가 Copy거나 Deref 주체가 Box일때만 가능함
까보면 이렇게 복잡하긴한데 정리하면 참조가 덕지덕지 발라진 타입들을 벗겨내기 쉽게 치는 설탕임
이게 없다면 &T조차 타입이 달라서 마음대로 못씀
다만 이 Deref 때문에 모호해질 위험이 있는데
그래서 Box Rc &등 참조 타입들은 자체 메소드를 만들지 않고 associated function으로 만드는게 국룰임
일련의 규칙을 Deref coercion 이라고 하는데
이 글은 그 일부를 좀 각색해서 나타낸것임
이쪽도 참고하면 좋음
댓글 0