Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

코딩 규칙

이 장에서는 포맷팅, 정확성을 위한 코딩, crates.io의 크레이트 사용을 다루고, 리뷰하기 쉽도록 PR을 구성하는 방법에 대한 몇 가지 팁을 소개합니다.

포맷팅과 tidy 스크립트

rustc는 Rust 표준 코딩 스타일을 따르는 방향으로 나아가고 있습니다.

하지만 현재로서는 안정 버전의 rustfmt를 사용하지 않고 특별한 설정을 적용한 고정 버전을 사용하므로, 일반적인 rustfmt와는 다른 스타일이 나올 수 있습니다. 따라서 cargo fmt로 이 저장소를 포맷팅하는 것은 권장하지 않습니다.

대신 포맷팅은 ./x fmt로 해야 합니다. 커밋하기 전마다 ./x fmt를 실행하는 습관을 들이는 것이 좋습니다. 이렇게 하면 나중에 충돌이 줄어듭니다.

포맷팅은 tidy 스크립트가 검사합니다. 이 스크립트는 ./x test를 실행할 때 자동으로 실행되며, ./x fmt --check로 따로 실행할 수도 있습니다.

참고: 포맷팅과 테스트 스위트

tests/ 디렉터리 아래의 Rust 소스 파일 대부분은 공백 민감성, 스냅숏 테스트의 특성, 위치에 민감한 주석 등의 이유로 포맷팅되지 않습니다.

어떤 테스트 파일이 포맷팅되지 않는지는 https://github.com/rust-lang/rust/blob/main/rustfmt.toml의 ignore 항목을 참고하십시오.

편집기에서 저장 시 포맷팅 기능을 사용하려면, build/<target>/stage0/bin/rustfmt에 빌드되는 고정 버전의 rustfmt를 사용하십시오.

C++ 코드 포맷팅

컴파일러에는 안정적인 C API가 없는 LLVM 일부와 연동하기 위한 C++ 코드가 일부 포함되어 있습니다. 해당 코드를 수정할 때는 다음 명령으로 포맷팅하십시오:

./x test tidy --extra-checks cpp:fmt --bless

이 명령은 로컬 환경에 의존하지 않도록 고정 버전의 clang-format을 사용합니다.

Python 코드 포맷팅과 린트

Rust 저장소에는 상당히 많은 Python 코드가 포함되어 있습니다. 저희는 ruff 도구로 이 코드의 린트와 포맷팅을 모두 관리하려고 노력합니다.

Python 코드를 수정할 때는 다음 명령으로 포맷팅하십시오:

./x test tidy --extra-checks py:fmt --bless

그리고 린트를 실행하려면 다음 명령을 사용하십시오:

./x test tidy --extra-checks py:lint

이 명령들은 로컬 환경에 의존하지 않도록 고정 버전의 ruff를 사용합니다.

저작권 고지

예전에는 파일 첫머리에 저작권 및 라이선스 고지가 있었습니다. 표준 조건(MIT OR Apache-2.0)으로 라이선스되는 새 파일에서는 이 고지를 생략하십시오.

지금쯤이면 저작권 고지가 모두 제거되었어야 하지만, rust-lang/rust 저장소에서 남아 있는 고지를 발견하면 언제든 이를 제거하는 PR을 여십시오.

줄 길이

한 줄은 최대 100자여야 합니다. 80자 이내로 유지할 수 있다면 더욱 좋습니다.

때로는, 특히 테스트의 경우, 이 제한에서 예외를 두어야 할 때가 있습니다. 그런 경우에는 다음과 같이 파일 상단 부근에 주석을 추가할 수 있습니다:

#![allow(unused)]
fn main() {
// ignore-tidy-linelength
}

탭 대 공백

4칸 들여쓰기를 사용하십시오.

정확성을 위한 코딩

서식 외에도 따를 만한 몇 가지 다른 팁이 있습니다.

모든 경우를 다루는 매치를 사용하십시오

매치에서 _를 사용하면 편리하지만, 열거형에 새로운 배리언트가 추가될 때 해당 배리언트가 올바르게 처리되지 않을 수 있습니다. 스스로에게 물어보십시오. 이 열거형에 새로운 배리언트가 추가된다면, 그 배리언트가 다른 방식으로 처리되어야 하는 것이 아니라 _ 코드를 사용해야 할 가능성은 얼마나 됩니까? 답이 “낮음“이 아니라면 모든 경우를 다루는 매치를 사용하십시오.

if let과 while let에도 같은 조언이 적용됩니다. 이 둘은 사실상 단일 배리언트에 대한 테스트이기 때문입니다.

잊고 싶지 않은 것에는 “TODO” 주석을 사용하십시오

PR을 병합하기 전에 다시 살펴보고 싶은 부분이 있다면, 스스로를 위한 유용한 도구로서 // TODO 주석을 삽입할 수 있습니다:

fn do_something() {
    if something_else {
        unimplemented!(); // TODO write this
    }
}

tidy 스크립트는 // TODO 주석에 대해 오류를 보고하므로, 이 코드는 TODO가 수정(또는 제거)될 때까지 병합될 수 없습니다.

이는 PR 안에서 어떤 커밋이 이후 커밋에서 수정할 버그를 남겨 두고 있음을 알리는 방법으로도 유용할 수 있습니다:

if foo {
    return true; // TODO wrong, but will be fixed in a later commit
}

코드베이스에 메모를 남기고 싶다면 대신 // FIXME를 사용하십시오.

주변 코드의 스타일을 따르십시오

기존 헬퍼를 사용하고 로직이나 검증을 중복하지 마십시오.

진실 공급원을 중복하지 마십시오

서로 다른 두 곳의 데이터를 동기화된 상태로 유지하려는 것은 코드 스멜입니다.

타입을 사용하여 불변 조건을 강제하십시오

가능하다면 생성 시점에 검사하는 데 그치지 말고 잘못된 상태를 아예 표현할 수 없게 만드십시오.

유용한 주석을 작성하십시오

무엇을 했는지가 아니라 왜 그렇게 했는지를 설명하는 주석을 작성하십시오. 명확하지 않은 버그에 대해서는 자세히 설명해도 괜찮습니다.

기존 동작을 유지하십시오

플랫폼 간 차이와 오류 상황을 고려하십시오. 엣지 케이스를 검증하는 관련 테스트를 찾아보십시오.

작은 단계로 나누어 작업하십시오

작고 독립적으로 테스트할 수 있는 단계로 나누어 작업하십시오. 의미 있는 변경을 할 때마다 관련 테스트를 실행하십시오. 그래야 처음 잘못된 지점이 어디인지 알 수 있습니다.

crates.io의 크레이트 사용하기

crates.io 의존성 절을 참고하십시오.

PR 구성 방법

PR의 커밋을 어떻게 준비하느냐에 따라 리뷰어의 부담이 크게 달라질 수 있습니다. 몇 가지 팁을 소개합니다.

“순수 리팩터링“은 별도의 커밋으로 분리하십시오. 예를 들어 메서드 이름을 바꾸는 경우, 그 이름 변경을 모든 사용처의 이름 변경과 함께 별도의 커밋에 넣으십시오.

일반적으로 커밋은 많을수록 좋습니다. 큰 변경을 하는 경우, 이를 독립적으로 이해할 수 있는 더 작은 단계로 나누는 것이 거의 항상 더 좋습니다. 한 가지 주의할 점은, 어떤 전략에 따라 코드를 도입한 다음 이후 커밋에서 그 코드를 (덧붙이는 것이 아니라) 크게 바꾸면 그러한 ’오락가락’이 혼란을 줄 수 있다는 것입니다.

포맷팅을 자주 하십시오. PR의 마지막 커밋만 올바르게 포맷팅되어 있으면 되지만, ./x fmt를 사용하여 각 커밋을 개별적으로 포맷팅하면 리뷰하기도 쉽고 불필요한 변경도 줄어듭니다.

병합하지 마십시오. bors가 만든 것 외에는 히스토리에 병합 커밋을 허용하지 않습니다. 병합 충돌이 발생하면 병합 대신 git rebase --interactive rust-lang/main과 같은 명령으로 리베이스하십시오(원격 저장소 이름으로 rust-lang을 사용한다고 가정합니다).

개별 커밋이 빌드될 필요는 없습니다(하지만 빌드되면 좋습니다). 모든 중간 커밋이 성공적으로 빌드되어야 한다고 요구하지는 않으며, PR 단위로 bisect할 수 있기만 하면 됩니다. 하지만 개별 커밋이 빌드되도록 할 수 있다면 언제나 도움이 됩니다.

명명 규칙

일반적인 Rust 스타일 및 명명 규칙 외에도, 컴파일러에만 해당하는 규칙이 몇 가지 있습니다.

  • cx는 대개 “context“의 약어이며, 접미사로 자주 사용됩니다. 예를 들어 tcx는 타이핑 컨텍스트(Typing Context)를 가리키는 일반적인 이름입니다.

  • 'tcx는 타이핑 컨텍스트의 라이프타임 이름으로 사용됩니다.

  • crate는 키워드이므로, 크레이트와 관련된 무언가를 나타내는 변수가 필요하면 철자를 krate로 바꾸는 경우가 많습니다.