Polonius에서 입력 프로그램의 요소를 식별하는 원자와 그 의미(변수, 경로, 노드, 대여, 기원)를 예제와 함께 설명합니다.
Polonius는 다음과 같은 원자(atom)를 정의합니다. Polonius에게 원자는 입력 프로그램 안의 특정한 것을 식별하는 불투명 식별자(실제로는 뉴타입으로 감싼 정수)입니다. 이들의 의미와 관계는 전적으로 입력 관계들에서 비롯됩니다.
존재할 수 있는 다양한 종류의 원자를 설명하기 위해 아래 러스트 코드 조각을 사용하겠습니다.
#![allow(unused)]
fn main() {
let x = (vec![22], vec![44]);
let y = &x.1;
let z = x.0;
drop(y);
}
변수(variable)는 러스트 소스 코드에서 정의된 사용자 변수를 나타냅니다. 위 코드 조각에서는 x, y, z가 변수입니다. 그 밖의 변수로는 매개변수 등이 있습니다.
경로(path)는 메모리의 한 위치에 도달하기 위한 메모리를 통한 경로를 나타냅니다. 이는 MIR의 place에 대략적으로 대응하지만, 전체 place의 부분집합만을 지원합니다(즉, 모든 MIR place는 하나의 경로로 매핑되지만, 때로는 하나의 경로가 여러 MIR place로 다시 매핑되기도 합니다).
각 경로는 변수(예: x)로 시작하지만, 필드(예: x.1), "인덱스"(예: x[]), 혹은 역참조 *x로 확장될 수 있습니다. 인덱스 경로(x[])는 차용 검사기가 모든 인덱스를 동일하게 다루기 때문에 실제로 접근된 인덱스 값을 추적하지 않는다는 점에 유의하세요.
경로의 문법은 대략 다음과 같습니다:
Path = Variable
| Path "." Field // 필드 접근
| Path "[" "]" // 인덱스
| "*" Path
각 경로에는 해당하는 별도의 원자(atom)가 연결됩니다. 따라서 경로 x에는 원자 P1이, 경로 x.0에는 또 다른 원자 P2가 있을 것입니다. 이 원자들은 path_parent 관계를 통해 서로 연관됩니다.
노드는 제어 흐름 그래프의 노드입니다. 이들은 cfg_edge 관계로 서로 연결됩니다.
MIR의 각 문(statement) S(또는 종료자 terminator)마다 실제로 두 개의 관련된 노드가 있습니다. 하나는 S가 실행되기 전의 "시작"을 나타내는 노드이고, 다른 하나는 S가 "효과를 발휘하는" 지점을 나타내는 이른바 "중간 노드(mid node)"입니다. 각 시작 노드는 정확히 하나의 후속 노드를 가지며, 그것이 중간 노드입니다.
대여(loan)는 소스에서 발생하는 어떤 빌림을 나타냅니다. 각 대여에는 빌려진 경로와 가변성(mutability)이 연결됩니다. 예제 코드에서는 &x.1 표현식에 해당하는 단일 대여가 있습니다.
기원(origin)은 러스트에서 일반적으로 수명(lifetime)이라고 부르는 것입니다. Polonius에서 기원은 참조가 생성되었을 가능성이 있는 대여들의 집합을 가리킵니다.