Rust 에러 E0559: variant has no field named X (배리언트에 없는 필드 이름)
E0559는 Enum::Variant { field: value }로 열거형 값을 만드는데, 적어 넣은 필드 중 하나가 그 배리언트에 없다는 뜻이에요. 구조체에서 같은 실수를 하면 나는 E0560의 열거형 버전이에요. 보통은 필드 이름을 줄여 썼거나 철자가 틀렸거나, 다른 배리언트의 필드를 썼거나, 괄호를 써야 하는 배리언트에 중괄호를 쓴 경우예요. 거의 언제나 단어 하나만 고치면 돼요. 이 페이지는 Rust 컴파일러 에러 해설의 일부예요.
에러 메시지
섹션 제목: “에러 메시지”error[E0559]: variant `Shape::Circle` has no field named `r` --> src/main.rs:8:33 |8 | let shape = Shape::Circle { r: 2.0 }; // ❌ 필드 이름은 `radius`예요 | ^ `Shape::Circle` does not have this field | = note: available fields are: `radius`“variant Shape::Circle has no field named r“는 “Shape::Circle 배리언트에는 r이라는 이름의 필드가 없다”는 뜻이에요. 라벨 `Shape::Circle` does not have this field는 “Shape::Circle에는 이 필드가 없다”, note는 “쓸 수 있는 필드는 radius“라는 뜻이에요.
이 에러를 내는 프로그램은 다음과 같아요.
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
fn main() { let shape = Shape::Circle { r: 2.0 }; // ❌ 필드 이름은 `radius`예요 println!("{:?}", shape);}무슨 뜻인가요
섹션 제목: “무슨 뜻인가요”첫 줄은 배리언트(Shape::Circle)와 내가 쓴 필드(r)를 알려 줘요. ^는 중괄호 안의 그 필드를 가리켜요. Rust가 정의 Circle { radius: f64 }를 살펴봤는데, r이라는 필드가 없었던 거예요.
열거형의 배리언트는 저마다 자기만의 필드 목록을 가져요. Shape::Circle에는 radius가 있고, Shape::Rectangle에는 width와 height가 있어요. 같은 열거형 안에 있어도 필드를 서로 나눠 쓰지 않아요.
화살표 아래에는 다음 힌트 중 하나가 나와요. 먼저 읽어 보세요. 보통 답이 들어 있어요.
note: available fields are: `radius`(쓸 수 있는 필드는radius): 비슷한 이름이 없어요. 이 배리언트에 있는 필드 중 아직 채우지 않은 것들이 나열돼요.help: a field with a similar name exists(비슷한 이름의 필드가 있다):key를kye라고 쓴 것 같은 오타예요. rustc가 고친 줄을 보여 줘요.help: `Message::Write` is a tuple variant, use the appropriate syntax(Message::Write는 튜플 배리언트이니 알맞은 문법을 쓰라): 배리언트의 필드에 이름이 없어서{ }가 아니라( )를 써야 해요.note: all struct fields are already assigned(모든 필드에 이미 값을 넣었다): 진짜 필드는 전부 채웠고, 이 필드는 남는 거예요.
피자를 주문하면서 “도우 크게”라고 적었는데, 주문서에는 “도우 크기” 칸만 있는 것과 비슷해요. 주방에서는 무슨 뜻인지 다 알지만, 주문서에 그런 이름의 칸이 없는 거죠.
Rust가 이렇게 하는 이유
섹션 제목: “Rust가 이렇게 하는 이유”Circle { radius: f64 }처럼 이름 있는 필드를 가진 배리언트는 열거형 안의 작은 구조체처럼 동작해요. 그런 배리언트를 만들 때 Rust는 정확히 그 필드들을 넣었는지 검사해요. 빠진 것도, 남는 것도, 철자가 틀린 것도 없어야 해요. 열거형은 데이터를 담을 수 있어요를 참고하세요.
이 검사가 가장 빛나는 때는 나중에 그 열거형을 match할 때예요. Shape::Circle { radius } => ... 같은 갈래는 모든 Circle에 정말로 radius가 있을 때만 제대로 동작해요. Rust가 Shape::Circle { r: 2.0 }을 통과시킨다면 그 보장이 사라지겠죠. 컴파일할 때 오타를 잡아 주니까, 프로그램 안의 모든 Circle은 언제나 빠짐없이 완전해요.
고치는 방법
섹션 제목: “고치는 방법”방법 1: 배리언트의 진짜 필드 이름 쓰기
섹션 제목: “방법 1: 배리언트의 진짜 필드 이름 쓰기”rustc가 available fields are나 a field with a similar name exists를 보여 줄 때 이 방법을 고르세요. 힌트에 나온 이름을 쓰면 돼요. 필드 이름은 대소문자를 구별하고 snake_case로 쓰니까, Radius와 radius는 서로 다른 이름이에요.
오타라면 “비슷한 이름” 힌트가 나와요.
error[E0559]: variant `Event::KeyPress` has no field named `kye` --> src/main.rs:8:31 |8 | let e = Event::KeyPress { kye: 'a' }; | ^^^ unknown field |help: a field with a similar name exists |8 - let e = Event::KeyPress { kye: 'a' };8 + let e = Event::KeyPress { key: 'a' }; |라벨 unknown field는 “알 수 없는 필드”라는 뜻이고, help는 kye를 key로 바꾼 줄을 보여 줘요.
r처럼 짧은 이름은 radius와 너무 달라서 제안이 나오지 않고, 대신 필드 목록이 나와요. 어느 쪽이든 배리언트에 정의된 필드를 쓰세요.
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 },}
#[derive(Debug)]enum Event { Click { x: i32, y: i32 }, KeyPress { key: char },}
fn main() { let shapes = [ Shape::Circle { radius: 2.0 }, // ✅ 진짜 필드 이름이에요 Shape::Rectangle { width: 3.0, height: 4.0 }, ]; for shape in &shapes { println!("{:?}", shape); }
let events = [Event::KeyPress { key: 'a' }, Event::Click { x: 10, y: 20 }]; println!("{:?}", events);}실행 결과:
Circle { radius: 2.0 }Rectangle { width: 3.0, height: 4.0 }[KeyPress { key: 'a' }, Click { x: 10, y: 20 }]필드 초기화 축약법(field init shorthand)도 조심하세요. Shape::Circle { r }은 Shape::Circle { r: r }이라는 뜻이라서 똑같이 E0559가 나요. 변수 이름이 r이라면 필드를 풀어서 쓰세요. Shape::Circle { radius: r }처럼요. 아니면 변수 이름을 radius로 바꾸고 Shape::Circle { radius }라고 쓰면 돼요.
방법 2: 튜플 배리언트에는 괄호 쓰기
섹션 제목: “방법 2: 튜플 배리언트에는 괄호 쓰기”rustc가 is a tuple variant, use the appropriate syntax라고 할 때 이 방법을 고르세요. Write(String) 같은 배리언트에는 필드가 있지만, 그 필드에 이름이 없어요. 그래서 중괄호 안에 어떤 이름을 써도 틀려요.
error[E0559]: variant `Message::Write` has no field named `text` --> src/main.rs:8:30 |4 | Write(String), | ----- `Message::Write` defined here...8 | let m = Message::Write { text: String::from("hi") }; | ^^^^ field does not exist |help: `Message::Write` is a tuple variant, use the appropriate syntax |8 - let m = Message::Write { text: String::from("hi") };8 + let m = Message::Write(/* String */); |라벨 `Message::Write` defined here는 “Message::Write는 여기서 정의됐다”, field does not exist는 “그런 필드는 없다”는 뜻이에요.
제안에 있는 /* String */은 자리 표시자예요. 그 자리에 내 값을 넣으세요. 튜플 배리언트는 정의된 순서대로 괄호 안에 값을 넣어서 만들어요.
#[derive(Debug)]enum Message { Move { x: i32, y: i32 }, // 이름 있는 필드: { }를 써요 Write(String), // 이름 없는 필드: ( )를 써요 Color(u8, u8, u8),}
fn main() { let messages = vec![ Message::Move { x: 1, y: 2 }, Message::Write(String::from("안녕")), // ✅ 괄호 Message::Color(255, 128, 0), ]; for m in &messages { match m { Message::Move { x, y } => println!("이동: ({}, {})", x, y), Message::Write(text) => println!("쓰기: {}", text), Message::Color(r, g, b) => println!("색: {} {} {}", r, g, b), } }}실행 결과:
이동: (1, 2)쓰기: 안녕색: 255 128 0필드에 이름을 붙이고 싶다면 정의를 Write { text: String }으로 바꾸세요. 그러면 Message::Write { text: ... }가 동작해요. 반대로 헷갈린 경우, 즉 Shape::Circle(2.0)처럼 이름 있는 필드를 가진 배리언트에 괄호를 쓰면 다른 에러가 나요. E0533, “expected value, found struct variant”(값이 와야 하는데 구조체 배리언트가 왔다)예요.
방법 3: 맞는 배리언트 고르기, 또는 배리언트 고치기
섹션 제목: “방법 3: 맞는 배리언트 고르기, 또는 배리언트 고치기”내가 쓴 필드가 있긴 한데 다른 배리언트에 있을 때 이 방법을 고르세요. 아래에서 radius는 Square가 아니라 Circle의 필드예요.
error[E0559]: variant `Shape::Square` has no field named `radius` --> src/main.rs:8:29 |8 | let s = Shape::Square { radius: 2.0 }; | ^^^^^^ `Shape::Square` does not have this field | = note: available fields are: `side`“Shape::Square 배리언트에는 radius 필드가 없고, 쓸 수 있는 필드는 side“라는 뜻이에요.
원래 무엇을 만들려고 했는지 생각해 보세요. 원을 원했다면 Shape::Circle { radius: 2.0 }을 쓰세요. 정사각형을 원했다면 그 필드를 쓰세요. Shape::Square { side: 2.0 }처럼요.
note: all struct fields are already assigned가 보인다면, 배리언트의 필드는 다 채웠고 내가 쓴 필드가 남는 거예요. 그 필드를 지우거나, 코드에 정말 필요하다면 배리언트 정의에 추가하세요.
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
#[derive(Debug)]enum Message { Move { x: i32, y: i32, z: i32 }, // 코드에 필요해서 `z`를 추가했어요}
fn main() { let a = Shape::Circle { radius: 2.0 }; // 원에는 반지름이 있어요 let b = Shape::Square { side: 2.0 }; // 정사각형에는 한 변의 길이가 있어요 println!("{:?}, {:?}", a, b);
let m = Message::Move { x: 1, y: 2, z: 3 }; println!("{:?}", m);}실행 결과:
Circle { radius: 2.0 }, Square { side: 2.0 }Move { x: 1, y: 2, z: 3 }배리언트에 필드를 추가하면, 그 배리언트를 만드는 모든 곳에서 그 필드도 채워야 해요. rustc가 그런 곳마다 E0063, “missing field”(필드 누락)로 짚어 줄 거예요.
자주 보게 되는 곳
섹션 제목: “자주 보게 되는 곳”Self::를 쓰는 생성자 메서드. impl Shape 안에서 fn circle(r: f64) -> Shape { Self::Circle { r } }이라고 쓰면, 축약법 때문에 r에서 E0559가 나요. 해결: Self::Circle { radius: r }. 열거형도 메서드를 가질 수 있어요를 참고하세요.
필드 이름을 바꾼 뒤. 열거형에서 Circle { r }을 Circle { radius }로 바꿨더니, 예전의 Shape::Circle { r: ... }마다 available fields are: `radius`와 함께 E0559가 나요. 프로젝트 전체에서 옛 이름을 검색해서 하나씩 고치세요.
match 패턴 안에서. Shape::Circle { r } => ...처럼 패턴에 틀린 필드 이름을 쓰는 것도 같은 실수지만, rustc는 다른 코드를 써요. E0026, “variant Shape::Circle does not have a field named r”(Shape::Circle 배리언트에는 r이라는 필드가 없다)와 help: `Shape::Circle` has a field named `radius`(radius라는 필드는 있다)가 나오고, E0027 “pattern does not mention field radius”(패턴이 radius 필드를 언급하지 않는다)도 함께 나와요. 해결: Shape::Circle { radius } => ..., 또는 짧은 이름을 그대로 쓰고 싶다면 Shape::Circle { radius: r } => .... 패턴 매칭을 참고하세요.
관련 에러
섹션 제목: “관련 에러”- E0560: struct has no field named x: 같은 실수를 구조체 리터럴에서 한 경우예요.
User { nmae: ... }처럼요. - E0063: missing field in initializer: 반대 경우예요. 배리언트에 있는 필드인데 채우지 않았어요.
- E0599: no method named x found:
Shape::Circel { ... }처럼 배리언트 이름이 틀렸을 때도 rustc는 이 코드를 써요. 메시지는 “no variant namedCircelfound for enumShape”(Shape열거형에Circel이라는 배리언트가 없다)예요. - E0609: no field on type: 필드를 읽을 때 이름이 틀린 경우예요.
E0026: variant does not have a field named x: 같은 실수를match패턴 안에서 한 경우예요(위 참고).E0533: expected value, found struct variant:Shape::Circle(2.0)처럼 이름 있는 필드를 가진 배리언트에 괄호를 쓴 경우예요.- 전체 컴파일러 에러: 에러 페이지 전체 목록이에요.
이해도 점검
섹션 제목: “이해도 점검”이해도 점검
1. enum Message { Write(String) }에서 Message::Write { text: s }는 어떻게 바꿔야 할까요?
2. let r = 2.0;이 있는데 Shape::Circle { r }이라고 썼어요. 필드 이름은 radius예요. 어떻게 고칠까요?
3. Shape::Square { radius: 2.0 }에서 E0559가 났고, note에는 side만 나와요. 무슨 일일까요?
점수: 0 / 3
더 알아보기
섹션 제목: “더 알아보기”- E0559 — Rust error codes index (영어): 이 에러의 공식 설명이에요.
- 열거형 정의하기 — The Rust Programming Language 한국어판: 이름 있는 필드를 가진 배리언트, 튜플 배리언트, 유닛 배리언트를
Message예제로 설명해요. - Enums — Rust by Example (영어): 모든 종류의 배리언트를 실행해 볼 수 있는 예제예요.
- Struct expressions — The Rust Reference (영어): 축약법을 포함해서
Enum::Variant { field: value }의 정확한 규칙이에요. - E0026 — Rust error codes index (영어): 같은 실수를 패턴 안에서 했을 때의 공식 페이지예요.