콘텐츠로 이동

Rust 컴파일러 에러 해설

Rust 컴파일러가 빨간 에러를 띄웠는데 무슨 말인지 모르겠나요? 잘 찾아오셨어요. Rust 개발자라면 누구나 이런 에러를 봐요. 하루에도 몇 번씩요. 다행히 계속 마주치는 에러는 몇 개 되지 않고, 한 번 알아 두면 더는 무섭지 않아요.

아래의 각 페이지는 에러 코드 하나를 골라서, 실제 에러 메시지를 보여 주고, 쉬운 말로 설명하고, 브라우저에서 바로 실행해 볼 수 있는 해결 방법을 알려 줘요.

에러 컴파일러 메시지 쉽게 말하면
E0382 borrow of moved value 값을 넘겨준 다음에 또 쓰려고 했어요
E0502 cannot borrow as mutable because it is also borrowed as immutable 누군가 아직 읽고 있는 값을 바꾸려고 했어요
E0499 cannot borrow as mutable more than once at a time 두 곳에서 같은 값을 동시에 바꾸려고 해요
E0308 mismatched types 다른 타입이 와야 할 자리에 엉뚱한 타입을 넣었어요
E0277 the trait bound is not satisfied 그 타입은 요청한 일(출력, 비교, 더하기 등)을 할 수 없어요
E0106 missing lifetime specifier 반환한 참조자가 언제까지 유효한지 Rust가 알 수 없어요
E0425 cannot find value in this scope 이름에 오타가 있거나, 그 이름이 있는 블록 밖에서 썼어요
E0599 no method named … found 그 타입에 그런 메서드가 없거나, 트레이트를 가져오지(import) 않았어요
E0384 cannot assign twice to immutable variable mut로 선언하지 않은 변수를 바꿨어요
E0596 cannot borrow as mutable, as it is not declared as mutable mut가 아닌 변수나 참조자를 통해 값을 바꾸려고 했어요
E0597 borrowed value does not live long enough 가리키던 값이 사라진 뒤에도 참조자를 쓰고 있어요
E0515 cannot return reference to local variable 함수가 끝나면 해제되는 값의 참조자를 반환했어요
E0373 closure may outlive the current function, but it borrows … 클로저(주로 스레드)가 빌린 지역 변수가 클로저보다 먼저 사라질 수 있어요
E0369 binary operation == cannot be applied to type … 내가 만든 타입이 (아직) ==, <, + 같은 연산자를 지원하지 않아요
E0432 unresolved import use 줄이 가리키는 크레이트, 모듈, 항목을 찾을 수 없어요
E0433 cannot find type … in this scope (older: failed to resolve) HashMap::new() 같은 경로에 가져오지 않았거나 없는 이름이 있어요
E0424 self value is a keyword only available in methods with a self parameter self를 받지 않는 함수 안에서 self를 썼어요
E0061 this function takes N arguments but M arguments were supplied 인자를 너무 많이 또는 적게 넘겼어요 (Rust에는 선택적 인자가 없어요)
E0594 cannot assign to p.hp, as p is not declared as mutable mut 권한 없이 필드나 & 뒤의 값을 바꿨어요
E0004 non-exhaustive patterns: X not covered match가 가능한 값을 모두 처리하지 않아요
E0507 cannot move out of x which is behind a shared reference 빌리기만 한 값의 소유권을 가져가려고 했어요
E0603 function x is private pub이 아닌 함수, 구조체, 모듈을 썼어요
E0716 temporary value dropped while borrowed 그 줄이 끝나면 버려지는 값의 참조자를 계속 들고 있어요
E0463 can’t find crate for x 크레이트(또는 대상 플랫폼용 표준 라이브러리)가 설치되어 있지 않아요
E0368 binary assignment operation += cannot be applied to type … 내가 만든 타입이 +=, -= 같은 연산자를 지원하지 않아요
E0057 this function takes N arguments but M were supplied (note: closure defined here) 클로저를 호출할 때 인자를 너무 많이 또는 적게 넘겼어요
E0282 type annotations needed Rust가 타입을 스스로 알아낼 수 없어서 직접 적어 줘야 해요
E0609 no field x on type T 필드 이름에 오타가 있거나, 값이 (Option 같은 것에) 감싸져 있어요
E0593 closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments 튜플 하나(또는 다른 개수의 인자)를 받아야 할 자리에서 클로저가 인자를 따로따로 받아요
E0631 type mismatch in closure arguments 클로저 매개변수의 타입이 실제로 받는 값과 달라요 (주로 i32와 &i32)
E0005 refutable pattern in local binding let Some(x) = …는 실패할 수 있어서 그냥 let으로는 쓸 수 없어요
E0615 attempted to take value of method len on type String s.len() 대신 s.len이라고 썼어요
E0610 {integer} is a primitive type and therefore doesn’t have fields 숫자, bool, char에 .필드를 썼어요
E0560 struct User has no field named nmae 구조체를 만들 때 그 구조체에 없는 필드 이름을 썼어요
E0616 field balance of struct Account is private 모듈 밖에서 pub이 아닌 필드를 읽었어요
E0451 field x of struct Y is private 비공개 필드가 있는 구조체를 리터럴로 직접 만들었어요
E0624 method x is private pub이 아닌 메서드나 연관 함수를 호출했어요
E0283 type annotations needed (cannot infer type … multiple impls satisfy this bound) 여러 타입이 들어맞을 수 있어서(.collect(), .sum() 등) 하나를 골라 줘야 해요
E0284 type annotations needed: cannot satisfy <_ as FromStr>::Err == _ "42".parse()가 어떤 타입으로 바꿔야 할지 몰라요
E0790 cannot call associated function on trait without specifying the corresponding impl type 어떤 타입인지 말하지 않고 Default::default()나 Trait::new()를 썼어요
E0559 variant Shape::Circle has no field named r 열거형 배리언트를 만들 때 그 배리언트에 없는 필드 이름을 썼어요
E0063 missing field email in initializer of User 구조체를 만들면서 필드를 하나 이상 빠뜨렸어요
E0689 can’t call method pow on ambiguous numeric type {integer} 2.pow(10)이나 2.0.sqrt()에는 i32, f64 같은 구체적인 숫자 타입이 필요해요
E0034 multiple applicable items in scope 두 트레이트가 같은 이름의 메서드를 줘서 Rust가 하나를 고를 수 없어요
E0412 cannot find type X in this scope (Rust 1.93+ prints E0425) 타입 이름에 오타가 있거나, 가져오지(import) 않았거나, 선언하지 않았어요
E0428 the name area is defined multiple times 두 항목이 같은 이름을 써요. Rust에는 함수 오버로딩이 없어요
E0026 variant Shape::Circle does not have a field named r 패턴에 구조체나 배리언트에 없는 필드 이름을 썼어요
E0027 pattern does not mention fields id, paid 구조체 패턴에서 필드를 빠뜨렸어요. 필드를 추가하거나 ..로 끝내세요
E0533 expected unit struct, unit variant or constant, found struct variant Shape::Circle 이름만 와야 할 자리에 구조체 배리언트(또는 함수)를 썼어요. { .. }를 붙이세요
E0592 duplicate definitions with name reset 두 impl 블록이 같은 이름의 메서드를 정의해요
E0255 the name Error is defined multiple times use로 가져온 이름이 내가 만든 타입이나 함수와 같아요
E0252 the name Result is defined multiple times use 줄 두 개가 같은 이름을 가져와요. 하나를 as로 바꾸세요
E0411 cannot find type Self in this scope impl이나 트레이트 밖에서 Self를 썼어요
E0405 cannot find trait Display in this scope 트레이트 이름에 오타가 있거나 가져오지 않았어요(예: use std::fmt::Display;)
E0532 expected unit struct, unit variant or constant, found tuple variant Shape::Circle 패턴에서 튜플 배리언트(또는 구조체)의 ( )를 빠뜨렸거나, 필요 없는 곳에 ( )를 붙였어요
E0164 expected tuple struct or tuple variant, found struct variant Shape::Circle 구조체 배리언트나 연관 항목에 패턴으로 ( )를 썼어요. { }나 가드를 쓰세요
E0404 expected trait, found derive macro Debug impl X for나 T: X의 X가 구조체, 타입 별칭, 또는 가져오지 않은 derive 매크로예요
E0401 can’t use generic parameters from outer item 안쪽 fn이 바깥 함수의 T나 Self를 써요. 자기만의 제네릭을 주거나 클로저를 쓰세요
E0107 enum takes 2 generic arguments but 1 generic argument was supplied Result<u32>, HashMap<String> 같은 경우예요. < > 안의 인자가 너무 적거나 많아요
E0530 match bindings cannot shadow tuple variants use Shape::* 뒤에 쓴 Circle =>처럼, 괄호 없는 배리언트 이름은 새 변수가 될 수 없어요
E0434 can’t capture dynamic environment in a fn item 안쪽 fn은 바깥 함수의 지역 변수를 볼 수 없어요. 클로저를 쓰거나 값을 인자로 넘기세요
E0601 main function not found in crate main 바이너리에 fn main()이 없어요(빠졌거나, 철자가 틀렸거나, mod 안에 있거나, 사실 라이브러리예요)
E0658 use of unstable library feature iter_intersperse 안정판 Rust에서 nightly 전용 API를 썼어요. 안정판 대안을 쓰거나 업데이트하세요
E0614 type u32 cannot be dereferenced x가 참조자가 아니라 이미 평범한 값인데 *x라고 썼어요
E0435 attempt to use a non-constant value in a constant const, 배열 길이, static이 let 변수를 써요. const로 바꾸거나 Vec을 쓰세요
E0554 #![feature] may not be used on the stable release channel nightly 전용 코드를 복사했어요. 속성을 지우고 안정판 API를 쓰거나, 일부러 nightly를 쓰세요

Rust의 에러 메시지는 친절하기로 유명하지만, 담긴 정보가 많아요. 실제 예를 하나 볼게요.

fn main() {
let name = String::from("Ferris");
let greeting = name;
println!("{name}");
}
error[E0382]: borrow of moved value: `name`
--> src/main.rs:4:16
|
2 | let name = String::from("Ferris");
| ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait
3 | let greeting = name;
| ---- value moved here
4 | println!("{name}");
| ^^^^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
3 | let greeting = name.clone();
| ++++++++

“이동된 값 name을 빌렸다”는 에러예요. 이렇게 읽어 보세요.

  1. 첫 줄은 요약이에요. 에러 코드(E0382)와 한 줄 설명이 있어요.
  2. 화살표 줄(--> src/main.rs:4:16)은 문제가 생긴 파일, 줄, 칸을 알려 줘요.
  3. ^^^^ 표시는 에러가 난 정확한 위치를 가리켜요. ---- 표시는 거기까지 이어진 사연이에요. 여기서는 값이 2번째 줄에서 만들어지고, 3번째 줄에서 이동(move)되고, 4번째 줄에서 사용됐다고 말하고 있어요.
  4. help: 줄은 컴파일러가 제안하는 해결책이에요. 추가할 코드를 정확히 보여 줄 때가 많아요(++++ 표시가 새로 넣을 글자예요). 항상 가장 좋은 방법은 아니지만, 출발점으로는 아주 좋아요.

에러가 여러 개라면 첫 번째 에러부터 읽으세요. 실수 하나가 줄줄이 다른 에러를 만들 수 있어서, 첫 번째를 고치면 나머지가 사라지는 경우가 많아요.

  • 컴파일러에게 더 물어보세요. 모든 에러 코드에는 더 긴 설명이 들어 있어요. 터미널에서 이렇게 실행해 보세요.

    Terminal window
    rustc --explain E0382

    짧은 설명과 함께, 에러가 나는 예제와 고친 예제를 보여 줘요(설명은 영어예요).

  • 자주 검사하세요. cargo check는 프로그램 전체를 빌드하지 않고 에러만 찾아 주기 때문에 cargo build보다 훨씬 빨라요. 몇 줄 쓸 때마다 실행하면 에러를 스무 개씩이 아니라 하나씩 만나게 돼요. Cargo와 크레이트를 참고하세요.

  • 에디터가 입력하는 동안 에러를 보여 주게 하세요. rust-analyzer 확장을 쓰면 코드 바로 위에 같은 도움말과 함께 에러가 표시돼요. Rust 도구와 개발 환경 설정을 참고하세요.

이 에러들은 대부분, 다른 언어에서는 실행 중에야 (혹은 영영) 발견되는 문제를 Rust가 프로그램을 실행하기 전에 검사하기 때문에 생겨요. 해제된 메모리 사용, 두 스레드가 같은 데이터를 동시에 바꾸기, null 검사 빠뜨리기 같은 것들이요. 에러 하나를 고칠 때마다, 사용자에게 절대 닿지 않을 버그 하나를 없애는 셈이에요.

그래서 많은 사람이 이렇게 말해요. Rust에서는 싸움이 컴파일할 때 일어나고, 그다음엔 프로그램이 그냥 잘 돌아간다고요. 가장 흔한 에러들 뒤에 있는 규칙은 소유권, 대여, 라이프타임 페이지에서 설명해요.

이해도 점검

1. Rust 에러 메시지에 문제가 여러 개 나왔어요. 어떤 것부터 고쳐야 할까요?

2. rustc --explain E0382는 무엇을 하나요?

3. 에러 메시지에서 ^^^^ 표시는 무엇을 가리키나요?

점수: 0 / 3