필드 접근 표현식

필드 접근 표현식 (Field access expressions)

필드 접근 표현식은 struct나 union의 필드 위치로 평가되는 place 표현식(place expression) 이에요. 피연산자가 가변(mutable)이면 필드 표현식도 가변이 돼요.

문법은 표현식(이걸 컨테이너 피연산자(container operand) 라고 불러요) 하나, 그 다음 ., 마지막에 식별자 하나로 이뤄져 있어요.

출처: Rust Reference

본문

필드 표현식 뒤에는 괄호로 묶인 쉼표 구분 표현식 목록이 올 수 없는데, 그건 메서드 호출 표현식(method call expression) 으로 파싱되기 때문이에요. 즉, 필드 표현식은 호출 표현식의 함수 피연산자가 될 수 없어요.

참고 필드 표현식을 호출 표현식에서 사용하려면 괄호로 감싸면 돼요.

#![allow(unused)]
fn main() {
struct HoldsCallable<F: Fn()> {
    callable: F,
}

let holds_callable = HoldsCallable { callable: || () };

// Invalid: Parsed as calling the method "callable"
// holds_callable.callable();

// Valid
(holds_callable.callable)();
}

필드 접근의 예시예요.

mystruct.myfield;
foo().x;
(Struct {a: 10, b: 20}).a;
(mystruct.function_field)() // Call expression containing a field expression

자동 역참조 (Automatic dereferencing)

컨테이너 피연산자의 타입이 Deref 또는(피연산자가 가변인지에 따라) DerefMut를 구현하면, 필드 접근이 가능해질 때까지 필요한 만큼 자동으로 역참조돼요. 이 과정을 줄여서 autoderef 라고도 불러요.

빌림 (Borrowing)

struct의 필드나 struct에 대한 참조의 필드는 빌림할 때 서로 분리된 개체로 취급돼요. struct가 Drop을 구현하지 않고 지역 변수에 저장되어 있으면, 그 각 필드를 밖으로 이동(move out)하는 경우에도 이 원칙이 적용돼요. Box 이외의 사용자 정의 타입을 통해 자동 역참조를 수행하는 경우에는 이 원칙이 적용되지 않아요.

#![allow(unused)]
fn main() {
struct A { f1: String, f2: String, f3: String }

let mut x: A;
x = A {
    f1: "f1".to_string(),
    f2: "f2".to_string(),
    f3: "f3".to_string()
};
let a: &mut String = &mut x.f1; // x.f1 borrowed mutably
let b: &String = &x.f2;         // x.f2 borrowed immutably
let c: &String = &x.f2;         // Can borrow again
let d: String = x.f3;           // Move out of x.f3
}

위 코드를 보면 같은 struct x의 필드들을 각각 가변 빌림, 불변 빌림, 다시 불변 빌림, 마지막으로 이동까지 섞어서 써도 문제가 없어요. 모든 필드가 하나의 값으로 묶여 있는 것처럼 보여도, 빌림 규칙은 필드 단위로 따로 적용되거든요.

더 알아보기