Pin은 자기참조(self-referential) 구조체를 나타내기 위해서 만들어진 래퍼 타입이다
일단 Pin없이 자기참조 구조체를 만들어보자
잘 보면 a의 참조를 리턴하는게 아니라 저장해준 참조를 리턴한다 이건 수명으로 나타낼수가 없어서 b는 참조가 될수없고 그냥 포인터를 써야한다
이것만보면 잘 돌아가는거 같지만 만약 SelfRef가 이동하면 어떻게 될까?
SelfRef를 리턴해서 이동시켜봤다 이때 b는 foo 함수의 스택을 가르키고 있고 당연히 main에서 읽고 쓰기를 시도하는것은 UB다
miri를 돌려보면 자세한 설명이 나온다
이미 freed된곳을 역참조 즉 이미 끝난 함수의 스택을 읽으려 했다는것이다
이처럼 참조가 가르키는 대상이 소멸될일은 없지만 대상을 가르키는 주소는 이동할때 변할수가 있다
Rust에서 이동은 아무런 제약이 없기에 이걸 방지하려면 이동해도 변하지 않는 주소일때만 참조를 저장해야한다
그걸 위해서 존재하는 타입이 바로 Pin이다
이제 이 함수들이 safe하게된 이유를 찾아보자
일단 Pin을 safe하게 만드는 방법은 Pin::new인데 이건 Unpin을 요구한다
이때 필드에 PhantomPinned를 박아놨기 때문에 SelfRef는 !Unpin이다
그러므로 단순히 스택에 있는 값으로 만들려고 하면 컴파일 에러가 발생한다
그래서 위 코드에선 Box::pin을 사용했는데 Box는 항상 Unpin이기에 Box<SelfRef> 또한 Unpin이라서 Pin<Box<SelfRef>>를 만들수있다
그리고 이렇게 만든 Pin<Box<SelfRef>>를 Pin<&mut SelfRef>로 만드는건 safe하다 왜냐면 이미 고정된 주소를 가지고 있기 때문이다
디시 맨날 스샷 이상해져 십 다시 올렸음
설명 개잘해놨네... 주딱이는 레전드다... - dc App
내가 궁금한 부분을 순서대로 설명해놨음 ㄷㄷ - dc App
주딱 그 는 신인가?