빌림 규칙을 조각조각 만났어. 깔끔하게 정리하고, 그걸 강제하는 컴파일러의 부분을 만나보자: borrow checker.
두 규칙
하나: 어느 순간이든 가변 참조 하나 OR 불변 참조 몇 개든 가질 수 있어. 둘: 참조는 항상 유효해야 해 — 가리키는 데이터보다 오래 살 수 없어. 그게 borrow checker 전부야, 두 문장으로. 나머지는 다 컴파일러가 네 코드가 이걸 지키는지 증명하는 거야.
참조는 스코프 끝이 아니라 마지막 사용까지 산다
현대 Rust 는 똑똑해: 참조의 borrow 는 닫는 중괄호가 아니라 마지막 사용 에서 끝나. 그래서 불변 borrow 를 만들고, 다 쓰고, 그다음 같은 스코프에서 가변 borrow 를 잡을 수 있어. 이걸 non-lexical lifetimes (NLL) 라 부르고, 실패할 것 같은 코드가 실제론 컴파일되는 이유야.
borrow checker 는 린터가 아니라 증명기야
추측하거나 경고하지 않아 — 모든 참조에 대해 데이터가 그보다 오래 살고 aliasing 규칙이 지켜진다는 걸 증명 해. 안전을 증명 못 하면 코드를 거부하고. 그게 컴파일되는 Rust 프로그램에 use-after-free 도 데이터 레이스도 없는 이유야: '아마' 가 아니라 증명됨.
맞서 싸우는 건 한 단계야
초반엔 borrow checker 랑 싸우는 기분이 들 거야. 나중엔 네가 못 보던 진짜 aliasing 위험을 잡아주던 거였다는 걸 깨달아. 규칙은 안 바뀌어; 네 직관이 거기 따라잡는 거야. 그 전환이 이 퀘스트가 컴파일러를 멘토로 그리는 이유 전부야.