Rust 코딩
워크플로우
-
오리엔테이션. 코드를 작성하기 전에 프로젝트의 신뢰할 수 있는 출처를 읽으세요:
rust-toolchain.toml,Cargo.toml(edition,rust-version,[lints],[workspace]),clippy.toml,rustfmt.toml,.cargo/config.toml, CI 설정,justfile,Makefile또는 표준 점검 명령어를 위한xtask. 변경 중인 모듈과 그 주변 모듈을 읽고, 그들의 헬퍼, 오류 타입, 패턴을 재사용하세요. 완료 조건: 에디션, MSRV, 린트 정책, 모든disallowed-methods/disallowed-types항목, 프로젝트의 점검 명령어를 말할 수 있어야 합니다. -
타입 모델링. 타입에 따라 제어 흐름보다 데이터를 먼저 설계하세요. 라이브러리의 공개 API 변경 시:
references/api.md를 읽으세요. 완료 조건: 변경 사항이 의존하는 모든 불변 조건이 타입으로 인코딩되거나, 그 이름을 명시하는expect에 의해 유지되어야 합니다. -
빠른 루프로 구현. 작은 단계로 작업하고 각 단계 후에
cargo check를 실행하세요. 전체 진단 메시지를 읽으세요:help:줄은 일반적으로 수정 방법을 알려주며,rustc --explain E0502는 오류 코드를 설명합니다. 종속성의 API를 위해,$CARGO_HOME/registry/src/아래 잠긴 버전(Cargo.lock)의 소스를 읽으세요. 대규모 이름 변경은 rust-analyzer rename 또는ast-grep을 통해 처리하세요;cargo clippy --fix는 기계 적용 가능한 제안을 적용합니다. 버그 수정: 회귀 테스트를 먼저 작성하고 빨간색으로 표시되는지 확인하세요. 완료 조건: 변경 사항이 변경한 줄에 경고 없이 컴파일되고, 회귀 테스트가 수정 전에 빨간색, 수정 후에 초록색이어야 합니다. -
검증. 1단계의 프로젝트 명령어를 실행하세요; 그렇지 않으면:
cargo fmt --all cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test --workspace --all-features[lints]정책이 없는 프로젝트:cargo clippy --all-targets -- -W clippy::pedantic도 실행하고 변경한 줄의 hits를 수정하세요.- 상호 배타적 기능:
--all-features를 CI가 테스트하는 각 기능 세트로 대체하세요. cargo nextest는 doctest를 건너뜁니다:cargo test --doc를 추가하세요.- 공개 문서 변경:
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features. unsafe를 건드린 경우:references/unsafe.md를 읽으세요.- 린트는 원인을 수정하세요. 억제가 올바른 경우,
#[expect(clippy::lint_name, reason = "...")]를 가장 작은 항목에 범위를 지정하세요. 완료 조건: 모든 명령어가 0으로 종료되고, 변경한 줄에 경고가 없으며, 모든 새로운 억제에reason이 있어야 합니다.
-
diff 자체 검토. diff가 닿는 각 참조 파일의 분기와 규칙에 대해 전체
git diff를 기억이 아닌 다시 읽으세요. 완료 조건: 모든 헝크가 작업에 필수적이고, 프로토타입 코드와dbg!/todo!가 없으며, doc 주석이 동작과 일치하고, 모든 적용 가능한 규칙이 모든 헝크에 대해 유지되어야 합니다.
코드 검토: 다른 사람의 코드: 1단계를 실행하고, 가능하면 4단계 명령어를 실행한 후, 5단계를 그들의 diff에 적용하세요. 각 발견 사항을 path:line, 규칙, 수정 방법과 함께 보고하세요.
규칙
소유권
- 매개변수에서 빌림:
&str,&[T],&Path,&T. 함수가 저장하거나 소비할 때만String,Vec<T>,T를 값으로 가져옵니다. - 모든
.clone()은 그 자리를 정당화합니다: 호출자가 소유권이 필요하거나, 값이 저렴한 핸들(Arc::clone(&handle))인 경우. - 빌림 검사기가 문제를 제기하면 먼저 구조를 재구성하세요: 빌림을 짧게, 필드를 분리하여 빌림,
std::mem::take/replace,Vec에 대한 인덱스. 공유 가변 소유권(Rc<RefCell<_>>,Arc<Mutex<_>>)은 최후의 수단입니다. - 호출자가 반복만 하는 경우
impl Iterator<Item = T>를 반환하세요.
타입
- 불법 상태를 표현 불가능하게 만드세요:
bool플래그와Option필드 대신 상태별 데이터를 담은enum; ID, 단위, 검증된 값에 대한 뉴타입 (struct Port(NonZeroU16)). - 검증 대신 파싱하세요: 한 번에 경계에서 신뢰할 수 없는 입력을 변환하고 (
TryFrom,FromStr,#[serde(try_from = "Raw")]), 파싱된 타입을 안쪽으로 전달하세요. - 소유한 열거형에 대해 철저히 매칭하세요.
_arm은 미래의 변형이 해당 분기도 취해야 하는 경우에만 올바릅니다. - 정수는
From/TryFrom으로 변환하세요;as는 조용히 자르고 부호를 반전시킵니다.
오류와 패닉
- 라이브러리: 실패 도메인당
thiserror열거형. 바이너리:anyhow::Result와.context(...). - 패닉은 버그를 의미합니다.
unwrap()은 테스트에만 존재합니다; 프로덕션 코드는?또는 실패를 불가능하게 만드는 불변 조건을 명시하는expect("...")를 사용하세요.
현재 관용구
훈련 데이터에는 오래된 패턴이 지배적입니다. rust-version이 허용할 때 현재 형태를 선호하세요; 새 크레이트는 edition = "2024"를 사용합니다. clippy::incompatible_msrv는 새로운 std API만 잡아냅니다; 언어 및 Cargo 기능은 cargo +<msrv> check가 필요합니다.
| 선호 | 대신 | 도입 버전 |
|---|---|---|
std::sync::LazyLock, OnceLock | lazy_static!, once_cell | 1.80, 1.70 |
let Some(x) = opt else { return ... }; | match + 조기 반환 | 1.65 |
if let Some(x) = a && x > 0 | 중첩 if let | 1.88, edition 2024 |
트레이트의 기본 async fn | #[async_trait], dyn Trait에는 여전히 필요 | 1.75 |
| `async | {}클로저,AsyncFn` 바운드 | |
#[expect(lint, reason = "...")] | #[allow(lint)] | 1.81 |
&raw const x, &raw mut x | ptr::addr_of! | 1.82 |
opt.is_some_and(f), opt.is_none_or(f) | map_or(false, f), map_or(true, f) | 1.70, 1.82 |
std::hint::black_box | criterion::black_box | 1.66 |
공유 정책을 위한 Cargo.toml의 [lints] | 모든 크레이트 루트의 #![warn(...)] | 1.74 |
cargo:: 빌드 스크립트 지시문 | cargo: | 1.77 |
문서와 주석
- 공개 항목은
///문서를 가집니다: 실패 가능 함수의# Errors, 패닉 함수의# Panics,?를 사용하는 doctest 예제. - 주석은 이유를 설명합니다; 코드는 무엇을 보여줍니다.
종속성
- 워크스페이스가 이미 의존하는 것을 재사용하세요 (
[workspace.dependencies],cargo tree -i <crate>), 필요를 충족할 때 std를 선호하세요. cargo add(MSRV 인식)로 추가하고, 사용하는 기능만 활성화하세요.
참조
사용 중인 분기에 맞는 것을 로드하세요:
references/api.md: 라이브러리의 공개 API 설계 또는 변경, 명명, 트레이트 구현, semver.references/errors.md: 오류 타입 정의, 전파, 패닉 대Result.references/async.md: 비동기, tokio, 스레드, 채널, 락, 아토믹.references/unsafe.md:unsafe, FFI, 원시 포인터, 수동Send/Sync.references/cargo.md:Cargo.toml, 워크스페이스, 기능, 프로파일, 빌드 스크립트, 크레이트 선택.references/lints.md: 크레이트 또는 워크스페이스에 대한 린트 구성 설정.references/testing.md: 테스트 작성, 속성 및 스냅샷 테스트, 벤치마크.references/perf.md: 측정된 핫 경로 최적화.