Rust 에러 E0026: struct or variant does not have a field named X (패턴 속 없는 필드)
E0026은 Shape::Circle { r }처럼 패턴으로 구조체나 열거형 배리언트를 분해하는데, 적은 필드 이름 중 하나가 존재하지 않는다는 뜻이에요. 값을 만들 때 같은 실수를 잡아 주는 E0560과 E0559의 패턴 버전이에요. rustc가 보통 help: 줄에서 맞는 이름을 알려 주니까, 단어 하나만 고치면 되는 경우가 많아요. 이 페이지는 Rust 컴파일러 에러 해설의 일부예요.
에러 메시지
섹션 제목: “에러 메시지”error[E0026]: variant `Shape::Circle` does not have a field named `r` --> src/main.rs:8:25 |8 | Shape::Circle { r } => 3.14 * r * r, // ❌ 필드 이름은 `radius`예요 | ^ | | | variant `Shape::Circle` does not have this field | help: `Shape::Circle` has a field named `radius`“variant Shape::Circle does not have a field named r“는 “Shape::Circle 배리언트에는 r이라는 필드가 없다”는 뜻이에요. help:는 “Shape::Circle에는 radius라는 필드가 있다”고 알려 줘요.
이 에러를 내는 프로그램은 다음과 같아요.
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { r } => 3.14 * r * r, // ❌ 필드 이름은 `radius`예요 Shape::Rectangle { width, height } => width * height, }}
fn main() { println!("{}", area(&Shape::Circle { radius: 1.0 }));}같은 줄에 두 번째 에러도 보일 거예요. E0027, “pattern does not mention field radius”(패턴이 radius 필드를 언급하지 않았다)예요. 같은 실수를 반대쪽에서 본 거예요. Rust는 내가 적었지만 존재하지 않는 필드(r)와, 존재하지만 내가 적지 않은 필드(radius)를 둘 다 찾아냈어요. 이름을 고치면 두 에러가 함께 사라져요.
무슨 뜻인가요
섹션 제목: “무슨 뜻인가요”첫 줄에는 매칭하는 구조체나 배리언트(Shape::Circle)와 내가 쓴 필드(r)가 나와요. ^는 패턴의 중괄호 안에 있는 그 이름을 가리켜요.
패턴에서 { } 안의 이름은 내가 마음대로 정하는 새 변수 이름이 아니라 필드 이름이에요. Shape::Circle { r }은 Shape::Circle { r: r }의 줄임말이에요. “r이라는 필드를 꺼내서 r이라는 변수에 넣어 줘”라는 뜻이죠. Circle에는 r이라는 필드가 없어서 Rust가 멈추는 거예요.
화살표 아래에서 rustc는 다음 힌트 중 하나를 보여 줘요.
help: `Shape::Circle` has a field named `radius`: 내가 언급하지 않은 필드가 딱 하나 있어서, rustc가 그걸 말하려던 거라고 추측해요.help: a field with a similar name exists: 비슷한 이름의 필드가 있다는 뜻이에요.name을nmae로 쓴 것 같은 오타예요. rustc가 고친 줄을 보여 줘요.- 힌트가 전혀 없음: rustc도 짐작하지 못했어요. 구조체나 열거형 정의를 보고 진짜 이름을 확인하세요.
도서관 사서에게 “소설 비슷한 서가에 있는 책”을 달라고 하는 것과 같아요. 사서는 내가 어떤 서가를 원한다는 건 알지만, 실제로 있는 서가에만 갈 수 있어요.
Rust가 이렇게 하는 이유
섹션 제목: “Rust가 이렇게 하는 이유”Shape::Circle { radius } 같은 패턴은 “값이 Circle이면 그 radius를 줘”라는 약속이에요. Rust는 컴파일할 때 이 약속을 정의와 대조해서, 패턴이 없는 데이터를 달라고 하는 일이 절대 없게 해요. 튜플과 구조체 구조 분해하기를 참고하세요.
이런 검사가 없는 언어에서는 없는 키를 읽으면 undefined나 null이 나오고, 버그는 오타에서 한참 떨어진 곳에서 훨씬 나중에 드러나요. Rust에서는 오타가 컴파일러를 통과할 수 없어요. 누군가 필드 이름을 바꿨을 때도 도움이 돼요. 예전 이름을 쓰는 패턴마다 E0026이 나니까, 아무도 모르게 빠뜨리는 곳이 없어요.
고치는 방법
섹션 제목: “고치는 방법”방법 1: 진짜 필드 이름 쓰기
섹션 제목: “방법 1: 진짜 필드 이름 쓰기”대부분은 이 방법을 고르세요. help: 줄에 나온 이름을 쓰거나, 정의를 보고 확인하세요. 필드 이름은 대소문자를 구분하고 snake_case로 써요.
오타라면 “비슷한 이름” 힌트와 고친 줄이 나와요.
error[E0026]: struct `User` does not have a field named `nmae` --> src/main.rs:8:16 |8 | let User { nmae, age } = user; // ❌ 오타: 필드 이름은 `name`이에요 | ^^^^ struct `User` does not have this field |help: a field with a similar name exists |8 - let User { nmae, age } = user; // ❌ 오타: 필드 이름은 `name`이에요8 + let User { name, age } = user; // ❌ 오타: 필드 이름은 `name`이에요 |이 에러를 내는 프로그램이에요.
struct User { name: String, age: u32,}
fn main() { let user = User { name: String::from("Ferris"), age: 7 }; let User { nmae, age } = user; // ❌ 오타: 필드 이름은 `name`이에요 println!("{} is {} years old", nmae, age);}필드 이름을 정의에 적힌 그대로 쓰세요. 그러면 축약형이 동작하고, 필드와 이름이 같은 변수를 얻어요.
struct User { name: String, age: u32,}
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ 진짜 필드 이름 Shape::Rectangle { width, height } => width * height, }}
fn main() { let shapes = [ Shape::Circle { radius: 2.0 }, Shape::Rectangle { width: 3.0, height: 4.0 }, ]; for shape in &shapes { println!("넓이: {:.2}", area(shape)); }
let user = User { name: String::from("Ferris"), age: 7 }; let User { name, age } = user; // ✅ `nmae`가 아니라 `name` println!("{}는 {}살이에요", name, age);}실행 결과:
넓이: 12.56넓이: 12.00Ferris는 7살이에요방법 2: field: name으로 원하는 변수 이름 쓰기
섹션 제목: “방법 2: field: name으로 원하는 변수 이름 쓰기”짧은 이름 r이 마음에 들어서 변수 이름만 그렇게 짓고 싶을 때 이 방법을 고르세요. 진짜 필드 이름, 콜론, 변수 이름 순서로 써요. Shape::Circle { radius: r }처럼요. “radius 필드를 꺼내서 r이라고 부를게”라고 읽으면 돼요.
enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius: r } => 3.14 * r * r, // ✅ 필드는 `radius`, 변수는 `r` Shape::Rectangle { width: w, height: h } => w * h, }}
fn main() { let small = Shape::Circle { radius: 1.0 }; let wide = Shape::Rectangle { width: 10.0, height: 2.5 }; println!("작은 원: {:.2}", area(&small)); println!("넓은 직사각형: {:.2}", area(&wide));}실행 결과:
작은 원: 3.14넓은 직사각형: 25.00필드 이름이 이미 있는 변수와 겹칠 때나, 필드 이름이 길 때도 편리해요.
방법 3: 맞는 배리언트를 매칭하는지 확인하기
섹션 제목: “방법 3: 맞는 배리언트를 매칭하는지 확인하기”내가 쓴 필드가 실제로 있긴 한데, 다른 배리언트에 있을 때 이 방법을 고르세요. 열거형의 배리언트마다 자기 필드가 따로 있어요. 여기서 x는 Click의 필드인데, 이 갈래는 KeyPress를 매칭해요.
error[E0026]: variant `Event::KeyPress` does not have a field named `x` --> src/main.rs:9:27 |9 | Event::KeyPress { x, .. } => format!("key at {}", x), // ❌ `x`는 `Click`의 필드예요 | ^ | | | variant `Event::KeyPress` does not have this field | help: `Event::KeyPress` has a field named `key`이 에러를 내는 프로그램이에요.
enum Event { Click { x: i32, y: i32 }, KeyPress { key: char },}
fn describe(event: &Event) -> String { match event { Event::Click { x, y } => format!("click at ({}, {})", x, y), Event::KeyPress { x, .. } => format!("key at {}", x), // ❌ `x`는 `Click`의 필드예요 }}
fn main() { println!("{}", describe(&Event::KeyPress { key: 'a' }));}rustc의 추측(key)은 그냥 “내가 언급하지 않은 유일한 필드”일 뿐이니, 무작정 따르지 마세요. 이 갈래가 무엇을 해야 하는지 스스로 물어보세요. 키 입력에는 위치가 없으니, 여기서는 KeyPress에 실제로 있는 필드를 쓰는 게 맞아요.
enum Event { Click { x: i32, y: i32 }, KeyPress { key: char },}
fn describe(event: &Event) -> String { match event { Event::Click { x, y } => format!("({}, {}) 위치 클릭", x, y), Event::KeyPress { key } => format!("'{}' 키 입력", key), // ✅ KeyPress에는 `key`가 있어요 }}
fn main() { let events = [Event::Click { x: 10, y: 20 }, Event::KeyPress { key: 'a' }]; for event in &events { println!("{}", describe(event)); }}실행 결과:
(10, 20) 위치 클릭'a' 키 입력키 입력에도 정말 위치가 있어야 한다면, 배리언트에 필드를 추가하세요. KeyPress { key: char, x: i32, y: i32 }처럼요. 그러면 KeyPress를 만드는 모든 곳에서 그 필드도 채워야 해요. rustc가 E0063으로 한 곳씩 알려 줘요.
자주 보게 되는 곳
섹션 제목: “자주 보게 되는 곳”필드 이름을 바꾼 뒤. 열거형에서 r을 radius로 바꿨더니, Shape::Circle { r } => ... 갈래마다 E0026이 나요. 프로젝트에서 예전 이름을 검색해서 패턴을 하나씩 고치거나, radius: r로 예전 변수 이름을 유지하세요.
if let과 let에서. if let Some(User { nmae, .. }) = find_user()도 같은 에러를 내요. 여기에 ..를 붙여도 소용없어요. ..는 내가 적지 않은 필드를 건너뛰는 것이고, 내가 적은 이름은 모두 존재해야 해요. 해결: User { name, .. }.
튜플 배리언트나 튜플 구조체에 중괄호 쓰기. struct Point(i32, i32);에 대해 Point { x, y } 패턴을 쓰면 매칭할 진짜 필드 이름이 없어요. rustc는 이걸 다른 코드인 E0769, “tuple variant Point written as struct variant”(튜플 배리언트 Point를 구조체 배리언트처럼 썼다)로 알려 주고 Point(x, y)를 제안해요. 데이터를 가진 열거형 구조 분해하기를 참고하세요.
관련 에러
섹션 제목: “관련 에러”- E0027: pattern does not mention field: E0026의 쌍둥이로, 패턴이 빠뜨린 진짜 필드예요. E0026과 함께 나오는 경우가 많아요.
- E0559: variant has no field named x: 열거형 배리언트를 만들 때 이름이 틀린 경우예요.
- E0560: struct has no field named x: 구조체를 만들 때 이름이 틀린 경우예요.
- E0609: no field on type:
user.nmae처럼 필드를 읽을 때 이름이 틀린 경우예요. - E0533: expected unit struct, unit variant or constant: 배리언트는 맞는데 패턴의 모양이 틀렸어요(
{ }가 없어요). - 전체 컴파일러 에러: 에러 페이지 전체 목록이에요.
이해도 점검
섹션 제목: “이해도 점검”이해도 점검
1. enum Shape { Circle { radius: f64 } }에서 Shape::Circle { r } 패턴은 무엇을 달라는 걸까요?
2. radius 필드를 r이라는 변수에 넣고 싶어요. 어떤 패턴이 동작할까요?
3. 필드 이름이 name인데 User { nmae, .. }라고 쓰면 컴파일될까요?
점수: 0 / 3
더 알아보기
섹션 제목: “더 알아보기”- E0026 — Rust error codes index (영어): 이 에러의 공식 설명이에요.
- 패턴 문법 — The Rust Programming Language 한국어판:
field: variable과..를 포함해서 구조체와 열거형을 분해하는 방법이에요. - Destructuring structs — Rust by Example (영어): 구조체 패턴을 실행해 볼 수 있는 짧은 예제예요.
- Patterns — The Rust Reference (영어): 구조체 패턴과 필드 축약형의 정확한 규칙이에요.