Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

안전하지 않은 코드 검사

Rust의 특정 표현식은 메모리 안전성을 위반할 수 있으므로 unsafe 블록이나 함수 안에 있어야 합니다. 또한 컴파일러는 대응하는 안전하지 않은 연산이 없는데 unsafe 블록이 사용되면 경고합니다.

개요

안전하지 않은 코드 검사는 check_unsafety 모듈에 있습니다. 이 검사는 함수와 그 함수의 모든 클로저 및 인라인 상수의 THIR를 순회합니다. 이 검사는 unsafe 컨텍스트, 즉 unsafe 블록에 진입했는지 여부를 추적합니다. 안전하지 않은 연산이 unsafe 블록 밖에서 사용되면 오류가 보고됩니다. 안전하지 않은 연산이 unsafe 블록 안에서 사용되면, 해당 블록은 unused_unsafe 린트를 위해 사용된 것으로 표시됩니다.

안전하지 않은 코드 검사에는 타입 정보가 필요하므로, typeck 결과를 활용하는 HIR, THIR 또는 MIR에서 수행될 수 있습니다. THIR를 선택한 이유는 HIR보다 고려해야 할 경우가 적기 때문입니다. 예를 들어 THIR에서는 안전하지 않은 함수 호출과 안전하지 않은 메서드 호출이 동일한 표현을 가집니다. 안전성 검사는 제어 흐름에 의존하지 않아 MIR을 사용할 필요가 없으므로, 이 검사는 MIR에서 수행되지 않습니다. 또한 MIR은 일부 표현식에 대해 충분히 정확한 스팬을 가지고 있지 않습니다.

대부분의 안전하지 않은 연산은 THIR의 ExprKind를 확인하고 인자의 타입을 확인하여 식별할 수 있습니다. 예를 들어 원시 포인터의 역참조는 원시 포인터 타입의 인자를 가진 ExprKind::Deref에 해당합니다.

공용체(union)의 필드에 쓰는 것은 안전하기 때문에, 안전하지 않은 Union 필드 접근을 찾는 일은 조금 더 복잡합니다. 검사기는 대입 표현식의 좌변을 방문하고 있는 시점을 추적하여 그곳에는 공용체 필드가 직접 나타나는 것을 허용하고, 그 외의 모든 경우에는 오류를 발생시킵니다. 공용체 필드 접근은 패턴에서도 발생할 수 있으므로 패턴도 순회해야 합니다.

unused_unsafe 린트

unused_unsafe 린트는 제거할 수 있는 unsafe 블록을 보고합니다. 안전하지 않은 코드 검사기는 unsafe가 필요한 연산을 발견할 때마다 이를 기록합니다. 그런 다음 다음 중 하나에 해당하면 린트가 보고됩니다.

  • unsafe 블록에 안전하지 않은 연산이 전혀 없는 경우
  • unsafe 블록이 다른 unsafe 블록 안에 있고, 바깥 블록이 사용되지 않은 것으로 간주되지 않는 경우
#![allow(unused)]
#![deny(unused_unsafe)]
fn main() {
let y = 0;
let x: *const u8 = core::ptr::addr_of!(y);
unsafe { // lint reported for this block
    unsafe {
        let z = *x;
    }
    let safe_expr = 123;
}
unsafe {
    unsafe { // lint reported for this block
        let z = *x;
    }
    let unsafe_expr = *x;
}
}

unsafe와 관련된 기타 검사

안전하지 않은 트레이트를 구현하려면 unsafe impl이 필요하며, 이에 대한 검사는 일관성(coherence) 검사의 일부로 수행됩니다. unsafe_code 린트는 AST에 대한 린트 패스로 실행되며, unsafe 블록, 함수, 구현뿐만 아니라 특정 unsafe 속성도 찾아냅니다.