콘텐츠로 이동

Rust 에러 E0027: pattern does not mention field X (패턴에서 빠진 필드)

E0027은 let Order { item, quantity } = order;처럼 패턴으로 구조체나 열거형 배리언트를 분해하는데, 모든 필드를 언급하지 않았다는 뜻이에요. Rust에서 구조체 패턴은 모든 필드를 처리해야 해요. 이름을 적거나, ..로 “나머지는 됐어”라고 말해야 하죠. 가장 친절한 에러 중 하나예요. rustc가 정확한 해결책을 보여 주는데, 거의 언제나 점 두 개면 돼요. 이 페이지는 Rust 컴파일러 에러 해설의 일부예요.

error[E0027]: pattern does not mention fields `id`, `paid`
--> src/main.rs:10:9
|
10 | let Order { item, quantity } = order; // ❌ `id`와 `paid`를 언급하지 않았어요
| ^^^^^^^^^^^^^^^^^^^^^^^^ missing fields `id`, `paid`
|
help: include the missing fields in the pattern
|
10 | let Order { item, quantity, id, paid } = order; // ❌ `id`와 `paid`를 언급하지 않았어요
| ++++++++++
help: if you don't care about these missing fields, you can explicitly ignore them
|
10 | let Order { item, quantity, id: _, paid: _ } = order; // ❌ `id`와 `paid`를 언급하지 않았어요
| ++++++++++++++++
help: or always ignore missing fields here
|
10 | let Order { item, quantity, .. } = order; // ❌ `id`와 `paid`를 언급하지 않았어요
| ++++

“pattern does not mention fields id, paid“는 “패턴이 id, paid 필드를 언급하지 않았다”는 뜻이에요. 세 개의 help:는 아래에서 하나씩 풀어 볼게요.

이 에러를 내는 프로그램은 다음과 같아요.

struct Order {
id: u32,
item: String,
quantity: u32,
paid: bool,
}
fn main() {
let order = Order { id: 1, item: String::from("keyboard"), quantity: 2, paid: true };
let Order { item, quantity } = order; // ❌ `id`와 `paid`를 언급하지 않았어요
println!("{} x {}", quantity, item);
}

첫 줄에는 패턴이 빠뜨린 필드(id와 paid)가 나와요. ^^^가 패턴 전체에 밑줄을 긋는 건, 문제가 틀린 단어 하나가 아니라 무언가가 빠졌다는 것이기 때문이에요.

그다음 rustc는 help: 제안을 세 개 보여 줘요. 셋 다 맞는 방법이지만 뜻이 서로 달라요.

  • include the missing fields(빠진 필드를 패턴에 넣어라): 이름을 적어요. 그러면 id와 paid 변수도 생겨요.
  • explicitly ignore them(명시적으로 무시해라): id: _, paid: _라고 써요. 변수는 생기지 않지만, 모든 필드를 이름으로 적은 셈이에요.
  • always ignore missing fields here(여기서는 빠진 필드를 늘 무시해라): ..를 써요. “그 밖의 필드는 상관없어”라는 뜻이에요.

입구에 놓인 체크리스트에 “모든 칸에 체크하거나, 기타: 건너뜀에 체크하세요”라고 적혀 있는 것과 같아요. 칸을 그냥 비워 둘 수는 없어요.

Rust의 구조체 패턴은 따로 말하지 않는 한 완전해야 해요. 그래야 다음에 코드를 읽는 사람에게 의도가 분명히 전달돼요. Order { item, quantity, .. }는 “이 두 개만 필요해”라는 뜻이고, Order { id, item, quantity, paid }는 “모든 필드를 생각해 봤어”라는 뜻이에요. _와 ..로 일부 무시하기를 참고하세요.

진짜 이득은 구조체가 바뀔 때 나타나요. 누군가 Order에 discount 필드를 추가하면, 모든 필드를 이름으로 적은 패턴은 E0027로 깨지고, 새 필드를 처리해야 할지도 모르는 코드를 짚어 줘요. ..가 있는 패턴은 계속 컴파일돼요. 어느 쪽을 원하는지는 내가 고를 수 있지만, Rust가 대신 짐작하지는 않아요.

방법 1: ..를 붙여서 나머지 무시하기

섹션 제목: “방법 1: ..를 붙여서 나머지 무시하기”

대부분은 이 방법을 고르세요. 일부 필드만 필요하다면 패턴 끝에 ..를 붙이세요. let, match, if let, 함수 매개변수에서 모두 쓸 수 있고, 반드시 맨 마지막에 와야 해요.

struct Order {
id: u32,
item: String,
quantity: u32,
paid: bool,
}
fn main() {
let order = Order { id: 1, item: String::from("키보드"), quantity: 2, paid: true };
let Order { item, quantity, .. } = order; // ✅ `..`가 `id`와 `paid`를 건너뛰어요
println!("{} x {}", quantity, item);
let orders = [
Order { id: 2, item: String::from("마우스"), quantity: 1, paid: false },
Order { id: 3, item: String::from("모니터"), quantity: 1, paid: true },
];
for order in &orders {
match order {
Order { paid: true, item, .. } => println!("{} 배송하기", item),
Order { id, .. } => println!("{}번 주문은 결제를 기다리고 있어요", id),
}
}
}

실행 결과:

2 x 키보드
2번 주문은 결제를 기다리고 있어요
모니터 배송하기
▶ 직접 실행해 보기

첫 번째 갈래의 paid: true를 눈여겨보세요. 패턴 안의 필드를 값과 비교할 수도 있고, 그때도 나머지는 ..가 처리해 줘요.

방법 2: 빠진 필드를 적거나, _로 이름을 적고 무시하기

섹션 제목: “방법 2: 빠진 필드를 적거나, _로 이름을 적고 무시하기”

그 필드가 실제로 필요할 때, 또는 나중에 필드가 추가되면 패턴이 깨지기를 원할 때 이 방법을 고르세요. 이름 있는 필드를 가진 열거형 배리언트를 match할 때도 같은 에러가 나요.

error[E0027]: pattern does not mention field `y`
--> src/main.rs:9:9
|
9 | Message::Move { x } => println!("move to x = {}", x), // ❌ `y`를 언급하지 않았어요
| ^^^^^^^^^^^^^^^^^^^ missing field `y`

이 에러를 내는 프로그램이에요.

enum Message {
Move { x: i32, y: i32 },
Quit,
}
fn main() {
let m = Message::Move { x: 1, y: 2 };
match m {
Message::Move { x } => println!("move to x = {}", x), // ❌ `y`를 언급하지 않았어요
Message::Quit => println!("quit"),
}
}

이동에는 좌표가 두 개 있고, 코드는 사실 둘 다 써야 해요. 그러니 y를 적으세요. 정말로 상관없는 필드라면 y: _가 그 사실을 분명히 말해 주면서도 이름은 적어 둬요.

enum Message {
Move { x: i32, y: i32 },
Quit,
}
fn main() {
let messages = [Message::Move { x: 1, y: 2 }, Message::Move { x: 5, y: 0 }, Message::Quit];
for m in &messages {
match m {
Message::Move { x, y: 0 } => println!("바닥을 따라 x = {}까지 미끄러지기", x),
Message::Move { x, y } => println!("({}, {})(으)로 이동", x, y), // ✅ 두 필드 모두
Message::Quit => println!("종료"),
}
}
// 모든 필드를 이름으로 적었어요. `Move`에 필드를 추가하면 일부러 여기가 깨져요
if let Message::Move { x, y: _ } = &messages[0] {
println!("첫 번째 x = {}", x);
}
}

실행 결과:

(1, 2)(으)로 이동
바닥을 따라 x = 5까지 미끄러지기
종료
첫 번째 x = 1
▶ 직접 실행해 보기

무시하려고 필드 이름을 적는다면 그냥 y가 아니라 y: _라고 쓰세요. 쓰지 않는 y만 적으면 “unused variable”(사용하지 않는 변수) 경고가 나요.

방법 3: 철자가 틀린 필드 이름 고치기

섹션 제목: “방법 3: 철자가 틀린 필드 이름 고치기”

E0027이 같은 줄의 E0026과 함께 나올 때 이 방법을 고르세요. 예를 들어 필드가 radius인 배리언트에 Shape::Circle { r }이라고 쓰면 둘 다 나와요. r에 대해서는 E0026(그런 필드가 없음), radius에 대해서는 E0027(언급하지 않음)이에요. rustc의 E0027 help는 r 옆에 radius를 추가하라고 제안하지만, 그건 원하는 게 아니에요. 진짜 해결책은 틀린 이름을 바꾸는 거예요. Shape::Circle { radius }라고 쓰거나, 짧은 변수 이름을 유지하려면 Shape::Circle { radius: r }라고 쓰세요. 그러면 두 에러가 한꺼번에 사라져요. 예제는 E0026 페이지에서 볼 수 있어요.

구조체에 필드를 추가한 뒤. Order에 created_at을 추가했더니, 모든 필드를 적은 패턴마다 E0027이 나요. 검사가 제 할 일을 하고 있는 거예요. 패턴마다 정하세요. 이 코드에 created_at이 필요한가요? 필요하면 적고, 아니면 ..를 붙이세요.

함수 매개변수. fn print_order(&Order { item, quantity }: &Order)도 E0027을 내요. 해결: &Order { item, quantity, .. }. let과 함수 매개변수에서의 패턴을 참고하세요.

튜플 구조체와 튜플 배리언트. struct Color(u8, u8, u8);에 대한 Color(r) 패턴도 불완전하지만, rustc는 이걸 E0023, “this pattern has 1 field, but the corresponding tuple struct has 3 fields”(이 패턴에는 필드가 1개인데 대응하는 튜플 구조체에는 3개 있다)로 알려 줘요. 해결 방법은 같은 생각이에요. Color(r, ..)이나 Color(r, _, _)라고 쓰세요.

이해도 점검

1. struct Point { x: i32, y: i32, z: i32 }가 있어요. 컴파일되면서 x만 꺼내는 패턴은 무엇일까요?

2. Order { item, .. }와 Order { item, id: _, quantity: _, paid: _ }의 차이는 무엇일까요?

3. 같은 줄에서 r에 대해 E0026이, radius에 대해 E0027이 나요. 가장 좋은 해결책은 무엇일까요?

점수: 0 / 3