Announcing Rust 1.99.1
Rust 1.99.1 출시
Rust 팀이 1.99.1을 배포했습니다. 이번 업데이트는 일부 대상에서 발생한 wcslen 링크 오류, x86_64에서 FFI bool 반환값이 잘못 전달되는 컴파일 오류, macOS에서 rust-lld가 libLLVM를 찾지 못하는 문제를 수정합니다.
- 주제
에디터 노트
이번 릴리스에서 실제 영향이 가장 구체적으로 드러난 문제는 x86_64의 FFI bool 반환 오류입니다. 댓글 작성자는 Mercury가 0이나 1 대신 16을 받아 런타임 충돌을 일으켰다고 설명했고, 다른 개발자도 JIT 타입 가드에서 비슷한 문제를 겪었다고 전합니다. 어셈블리 차이와 재현 코드까지 제시돼 ABI 위반이 사용자 코드의 오류로 보일 수 있었던 경로가 분명합니다. 나머지 두 수정은 UEFI의 `wcslen` 링크 실패와 macOS에서 `rust-lld`가 `libLLVM`을 찾지 못하는 문제를 각각 대상으로 합니다. 댓글에서는 별도의 nightly 컴파일 오류와 혼동한 사례도 나왔지만, 해당 문제는 이 릴리스의 수정 사항과 같은 버그라고 확인되지 않았습니다. 각 수정의 적용 범위나 영향받은 버전은 릴리스 안내에 구체적으로 적혀 있지 않습니다.
AI 요약
Rust 팀이 Rust 1.99.1을 배포했습니다. 기존 버전을 rustup으로 설치했다면 rustup update stable 명령으로 업데이트하면 됩니다. 이번 포인트 릴리스는 이전 버전에서 발생한 세 가지 회귀를 수정합니다.
수정 사항
일부 Rust 대상에서 wcslen 심볼을 찾지 못해 링크 오류가 발생했습니다. LLVM의 loop-idiom-wcslen 최적화가 wcslen 호출을 넣을 수 있지만 대상 환경의 libc 등에 함수가 없을 때 문제가 생겼습니다. 특히 UEFI 대상에서는 미리 빌드된 표준 라이브러리에 해당 호출이 들어가 std를 사용하는 프로젝트가 영향을 받았습니다. Rust는 compiler-builtins 라이브러리에 대체 구현을 추가했습니다.
x86_64에서 FFI를 통해 bool을 반환할 때 반환 레지스터의 1~7번 비트가 지정되지 않는 문제가 있었습니다. 호출 측에서 0이나 1이 아닌 원시 값을 받을 수 있었습니다. 이번 수정에서는 ABI 요구에 맞춰 반환값에 다시 zero-extension을 적용합니다.
macOS에서는 rustup 프록시를 거치지 않고 컴파일러를 실행하면 rust-lld가 libLLVM을 불러오지 못할 수 있었습니다. rust-lld에 libLLVM.dylib이 있는 디렉터리를 가리키는 rpath 항목을 추가했습니다.
Lobsters 반응
- @BD103 — 버그 수정 릴리스가 이 사이트의 주제에 맞는지 확신은 없지만, 이번에 수정한 잘못된 컴파일과 오류는 꽤 흥미롭습니다.
- @wezm — bool FFI 컴파일 오류를 발견하고 신고한 사람입니다. 당시 동작이 매우 혼란스러웠고 컴파일러 탓으로 돌리는 데는 원래 무척 신중합니다. 결국 팀에 문제를 알리면서 "이상한 동작을 겪고 있는데 컴파일러 버그 같은 냄새가 납니다"라고 말했습니다. 이번에는 의심이 맞았다는 점이 조금 안심됩니다.
- @BD103 — 흥미롭네요. 어떤 동작을 보고 컴파일러 버그를 의심하기 시작했나요?
- @wezm — 처음에는 테스트 모음에서 테스트가 실패했습니다. 원인을 추적하다가 Mercury 코드에 bool을 반환하는 Rust 함수가 있다는 점을 발견했습니다. Rust 쪽에서 값을 기록하면 정상이었지만 Mercury 쪽에서 같은 값을 기록하려 하자 Mercury 런타임이 충돌했습니다. 이후 Mercury의 C foreign_proc에서 값을 기록해 보니 0이나 1이 아니라 16을 받고 있었습니다. 그때 컴파일러 버그를 의심했습니다. 함수 어셈블리도 수상했습니다. 1.99에서는
movzbl 0x19f(%rdi), %eax다음에retq가 나왔지만, 1.83에서는 그 사이에andb $0x1, %al이 있었습니다. 작은 재현 코드를 만든 뒤 Rust 저장소에 이슈를 열었습니다. - @pervognsen — bool 관련 문제라는 말을 보고 예전에 nightly에서 겪은 컴파일 오류와 관련 있는 줄 알았습니다. MIR 패스
SimplifyComparisonIntegral에서 비롯된 문제였습니다. https://github.com/rust-lang/rust/issues/158231 버그를 확인하고 nightly 툴체인을 최신 버전으로 업데이트했을 때는 이미 수정된 뒤였습니다. - @chc4 — 몇 주 전에 저도 이 문제를 겪었습니다. 신고해 주셔서 감사합니다. 제 경우 JIT 컴파일러의 타입 가드가 잘못된 경로로 넘어갔습니다. ABI 요구와 달리 bool을 반환하는 런타임 타입 가드의 결과에서 다른 비트가 설정된 바이트가 돌아왔기 때문입니다. https://github.com/chc4/lunacy/commit/1b94b976fd00869148fb0db3d639f65e9bda5a64
- @ralfj — 다음에 비슷한 문제가 보이면 버그를 신고해 주세요. 그래야 더 빨리 수정할 수 있습니다. :)
원문: Rust Blog / 번역·요약: Trawling