시그니처가 어긋난 memcmp 정의가 이제 컴파일 오류입니다 — Rust 1.98
한 줄 요지 —
#[no_mangle]로memcmp같은 런타임 심벌을 정의하는 자리가 있다면, 올리기 전에 시그니처가 C 명세와 맞는지 확인해 볼 만합니다.
무슨 일인가
Rust 1.98.0 이 2026년 8월 20일 나왔습니다. 언어 쪽 변경 하나가 베어메탈 코드에 직접 닿습니다.
deny-by-default 린트 invalid_runtime_symbol_definitions 가 생겼습니다.
- 릴리스 노트는 대상을
memcmp·memset·strlen같은core런타임 심벌로 적고, “앞으로 몇 릴리스에 걸쳐 확대할 계획” 이라고 덧붙입니다. - 무엇을 잡는지는 린트를 넣은 PR이 적습니다 — 심벌 이름이
core가 기대하는 런타임 심벌인 항목의 시그니처가 기대와 크게 다를 때입니다(ABI 불일치, C 가변인자 불일치, 인자 수 불일치, 반환형 누락 등). - 진단은 기대값과 실제값을 나란히 보여 주고
either fix the signature or remove any attributes를 권합니다. - 문서는 위험을 이렇게 적습니다 — C 명세를 따라야 하고 표준 라이브러리 기능을 쓰면 안 되며, 그러지 않으면 정의되지 않은 동작이 일어날 수 있다.
같은 릴리스에서 베어메탈 ARM 타깃이 올라갔습니다.
thumbv7a-none-eabi·thumbv7a-none-eabihf·thumbv7r-none-eabi·thumbv7r-none-eabihf·thumbv8r-none-eabihf5개가 Tier 2(공식 빌드가 제공되고 CI가 빌드를 보장하는 등급)로 승격됐습니다.
호환성 주의도 몇 가지 있습니다.
repr(transparent)가 더 엄격해져repr(C)타입·비공개 필드가 있는 타입·#[non_exhaustive]타입을 더 이상 “trivial”로 보지 않습니다.std::env::Vars·VarsOs에서 Send/Sync 구현이 빠졌습니다.derive(PartialOrd)의 빠른 경로가 들어오면서, 릴리스 노트가 “타입의 PartialOrd와 Ord 구현이 서로 어긋나 있던 크레이트를 실제로 깨뜨릴 수 있다” 고 적습니다.
태리의 판단
새로 생긴 제약이 아니라, 이미 있던 위험을 컴파일 시점으로 당긴 것입니다. 시그니처가 어긋난 memcmp 정의는 지금까지도 잘못된 것이었지만 조용히 컴파일됐고 결과는 실행 시점에 나타났습니다. 1.98은 그 자리를 오류로 바꿨을 뿐입니다.
그래서 이 린트를 #[allow] 로 넘기는 것은 경고를 끄는 것이 아니라 정의되지 않은 동작으로 가는 경로를 그대로 두는 것입니다. 그 차이는 릴리스 노트 한 줄만 봐서는 보이지 않고 린트 PR의 설명을 열어야 보입니다 — 노트는 대상 심벌만 적지 판정 기준을 적지 않습니다.
베어메탈 ARM 5개가 같은 릴리스에서 Tier 2로 올라간 것과 함께 읽으면 방향이 잡힙니다. 지원 등급을 올리면서, 그 환경이 특히 노출돼 있던 결함 부류를 컴파일러가 잡기 시작했습니다. 그리고 확대 계획이 명시돼 있으니 이번이 첫 걸음입니다.
올릴 버전은 1.98.0이 아닙니다. 저장소의 RELEASES.md 에 1.98.1(2026-09-03)이 vtable 생성 오컴파일(컴파일러가 잘못된 기계어를 내는 결함)을 고친다고 적혀 있습니다 — 이 줄은 1.98.0 릴리스 페이지에는 없습니다.
이번 주 할 일
- 팀 —
#[unsafe(no_mangle)]이나export_name으로core런타임 심벌을 정의하는 자리가 있다면 시그니처를 C 명세와 대조해 보시길 권합니다. 린트가 잡는 것은 정의 자체가 아니라 어긋난 시그니처이므로, 관례대로 쓴 코드는 그대로 통과합니다. 단, 걸린 자리를 억제로 넘기는 선택은 경고를 끄는 것이 아니라 그 UB를 남겨 두는 것입니다. - 개인 기여자 — 올릴 때
1.98.1을 지정하시고,cargo build로그에서repr(transparent)와derive(Ord)관련 새 오류가 나오는지 훑어보시면 호환성 주의 세 줄이 자기 코드에 걸리는지 바로 보입니다.