[Rust] 1.89.0 업데이트 발표 (번역)
https://blog.rust-lang.org/2025/08/07/Rust-1.89.0/
러스트는 누구든 믿음직하고 효과적인 소프트웨어를 만들 수 있게 도와주는 끝내주는 언어입니다.
만약 rustup을 통해서 Rust의 이전버전을 설치해놓은 상대라면, 업데이트는 아주 쉽습니다. 그냥 이렇게 치면 돼요.
rustup update stable
rustup을 설치한 적이 없다면, 우리 웹사이트의 설치 페이지에서 받을 수 있습니다. 그리고 깃허브에서 이번 버전에 대한 릴리즈 노트를 참조해보세요.
미래의 릴리즈를 테스트해서 러스트 팀을 돕고 싶다면, 로컬에서 베타 채널(rustup default beta) 또는 nightly 채널(rustup default nightly)로 업데이트하는 것을 고려할 수 있습니다.
버그를 발견했다면 리포트해주세요!
1.89.0 stable에는 무엇이 있나요?
const generic에 대한 인자 추론
Rust는 이제 const generic parameters에 대한 인자로 _를 지원합니다. 이건 주변 컨텍스트에서 값을 추론해요.
pub fn all_false
** [false; _]**
}
_는 시그너처에 있을 때는 const generics에 대한 인자로 허용되지 않습니다.
_가 타입으로 허용되는 경우에 대한 규칙과 유사하죠.
// 안됨****
pub const fn all_false
** [false; LEN]**
}
// 이것도 안됨****
pub const ALL_FALSE: [bool; _] = all_false::<10>();
Mismatched lifetime syntax lint
함수 시그너처에서의 라이프타임 생략은 러스트의 인체공학적 부분이지만, 초보자와 전문가 모두에게 걸림돌이 될 수도 있습니다.
이건 특히 문법적으로 라이프타임이 존재한다는 것이 확실하지 않은 타입에서 라이프타임이 추론될 때 그렇죠.
**// 반환타입 std::slice::Iter은 라이프타임을 가지나, 저기서는 시각적인 표시가 없음 **
// 라이프타임 생략은 반환타입의 라이프타임을 scores와 같은 것으로 추론함 ******
fn items(scores: &[u8]) -> std::slice::Iter
** scores.iter()
}
이 코드는 이제 기본적으로 다음과 같은 warning을 던질 겁니다.
warning: hiding a lifetime that's elided elsewhere is confusing
** --> src/lib.rs:1:18**
** |**
1 | fn items(scores: &[u8]) -> std::slice::Iter
** | ^^^^^ -------------------- the same lifetime is hidden here**
** | |**
** | the lifetime is elided here**
** |**
** = help: the same lifetime is referred to in inconsistent ways, making the signature confusing**
** = note: #[warn(mismatched_lifetime_syntaxes)] on by default**
help: use '_ for type paths
** |**
1 | fn items(scores: &[u8]) -> std::slice::Iter<'_, u8> {
** | +++**
우리는 2018년에 rust_2018_idioms lint 그룹의 일부로 이 상황을 개선하려고 처음 시도했었죠. 하지만 elided_lifetimes_in_paths lint에 대한 강한 피드백이 있었고, 함수를 이해하는 데 있어 중요하지 않은 라이프타임에 대해서도 경고하기 때문에 너무 과하다고(blunt of a hammer) 판단했습니다.
use std::fmt;
struct Greeting;
impl fmt::Display for Greeting {
** fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {**
** **** // -----^^^^^^^^^ expected lifetime parameter**
** // Knowing that Formatter has a lifetime does not help the programmer******
** "howdy".fmt(f)**
** }**
}
그 후, 우리는 제거하고자 했던 혼란이 다음 두가지와 함께 발생한다는 것을 깨달았습니다.
- 라이프타임 생략시 추론 규칙은 입력 라이프타임을 출력 라이프타임으로 연결합니다.
- 라이프타임이 존재한다는 것이 문법적으로 명백하지 않습니다.
Rust 문법에는 라이프타임이 존재한다는 것을 나타내는 2가지 조각이 있습니다. &와 '죠.
이 중에서도 '는 다시 추론되는 라이프타임 '_와 이름붙은 라이프타임('a)로 세분화됩니다.
타입이 이름붙은 라이프타임을 쓴다면 라이프타임 생략은 그 타입에서 라이프타임을 추론하지 않습니다.
이 조건대로면 우리는 3가지 그룹을 구성해볼 수 있죠.

mismatched_lifetime_syntaxes lint는 함수의 입력과 출력이 같은 그룹에 속하는지를 검사합니다.
위의 initial motivating 예시에서 &[u8]은 두 번째 그룹에 속하는 반면 std::slice::Iter
입력과 출력의 라이프타임이 다른 그룹에 속하기 때문에, lint는 이 함수를 경고해서 값이 시각적으로 명확하지 않은 라이프타임을 가질 때에 대한 혼란을 줄입니다.
그래서 mismatched_lifetime_syntaxes lint가 elided_named_lifetimes lint를 대체합니다.
이건 named lifetimes에 대해 유사한 동작을 했습니다.
elided_lifetimes_in_paths lint에 대한 향후 작업은 더 세분화되고 구체적인 sub-lints들로 분리하는 겁니다.
더 많은 x86 target feature
target_feature attribute는 이제 x86에서 sha512, sm3, sm4, kl, widekl target feature를 지원합니다.
또한 여러 AVX512 intrinsics 및 target feature들이 X86에서 지원됩니다.
#[target_feature(enable = "avx512bw")]
pub fn cool_simd_code(/ .. /) -> / ... / {
** /* ... /*
}
크로스 컴파일되는 doctests
Doctests는 이제 cargo test --doc --target other_target를 실행할 때 테스트될 겁니다.
이건 현재 테스트되고 있는 would-be-failing doctests 때문에 파손될 여지가 있습니다.
실패하는 테스트는 ignore-
/// ignore-x86_64** **/// panic!("something")** **///
pub fn my_function() { }
extern "C" 함수에서의 i128과 u128
i128와 u128은 더 이상 improper_ctypes_definitions lint를 트리거하지 않으며, 이는 이러한 타입이 경고 없이 extern "C" 함수에 사용될 수 있음을 의미합니다.
여기에는 몇 가지 주의사항이 있습니다.
Rust의 타입은 C의 (unsigned) __int128와도 ABI 및 layout이 호환됩니다.
문제는 플랫폼에서 __int128가 사용 가능하지 않다면 i128과 u128도 C 타입과 align이 되지 않을 수 있다는 겁니다.
i128는 모든 플랫폼에서 _BitInt(128)과 완전히 호환되지는 않습니다.
_BitInt(128)와 __int128는 같은 ABI를 갖지 않을 수도 있기 때문이죠.
이건 작년의 다은 레이아웃 변경에 대한 마지막 후속 조치이기도 합니다. https://blog.rust-lang.org/2024/03/30/i128-layout-update
x86_64-apple-darwin를 Tier 2로 강등
깃허브는 곧 public repository를 위한 무료 macOS x86_64 runner 제공을 중단하려고 합니다.
애플은 또한 x86_64 아키텍처에 대한 지원을 중단할 계획을 발표했습니다.
이러한 변화에 따라 Rust 프로젝트는 x86_64-apple-darwin을 티어 1에서 티어 2로 강등하는 과정에 있습니다.
이건 해당 타겟에서, rustc와 cargo 같은 도구의 빌드는 보장되지만 자동화된 테스트 슈트를 통과하는 것은 보장되지 않는다는 것을 의미합니다.
Tier 2로 강등하기 위한 RFC가 Rust 1.89와 1.90 사이에 허용될 것으로 예상하며, 이는 Rust 1.89가 x86_64-apple-darwin이 Tier 1 타겟인 Rust의 마지막 출시가 될 것임을 의미합니다.
사용자들에게 이러한 변경은 즉시 영향을 미치지는 않습니다.
표준 라이브러리와 컴파일러의 빌드는 여전히 러스트 프로젝트에 의해 배포되어 rustup 또는 기타 설치 방법을 통해 사용할 수 있을 겁니다.
하지만 타겟은 티어 2로 남습니다.
시간이 지남에 따라 이 타겟에 대한 테스트 커버리지가 줄어들면 점차 호환성이 깨지거나 떨어질 가능성이 큽니다.
wasm32-unknown-unknown target에 대한 Standards Compliant C ABI
wasm32-unknown-unknown 타겟에 대한 extern "C" 함수는 이제 표준 호환성 ABI를 가집니다.
자세한 것은 아래 블로그 포스트를 참조하세요. https://blog.rust-lang.org/2025/04/04/c-abi-changes-for-wasm32-unknown-unknown
Platform 지원
x86_64-apple-darwin은 티어 2로 강등되는 과정에 있습니다.
**새로운 Tier-3 타겟 **
loongarch32-unknown-none and loongarch32-unknown-none-softfloat
러스트의 tiered platform support에 대한 자세한 내용은 해당 페이지를 참조하세요.
Stable이 된 API
NonZero
x86 전용 intrinsics 추가
- AVX512 intrinsics
- SHA512, SM3 and SM4 intrinsics
File::lock
File::lock_shared
File::try_lock
File::try_lock_shared
File::unlock
NonNull::from_ref
NonNull::from_mut
NonNull::without_provenance
NonNull::with_exposed_provenance
NonNull::expose_provenance
OsString::leak
PathBuf::leak
Result::flatten
std::os::linux::net::TcpStreamExt::quickack
std::os::linux::net::TcpStreamExt::set_quickack
다음의 기존 stable API들은 이제 const context에서도 사용 가능합니다.
<[T; N]>::as_mut_slice
<[u8]>::eq_ignore_ascii_case
str::eq_ignore_ascii_case
기타 변경점
이외의 모든 변경사항은 각 Rust, Cargo, Clippy 페이지를 확인하세요
1.89.0의 컨트리뷰터들에게
1.89.0의 완성엔 수많은 사람들이 함께했습니다. 전부 여러분이 없었다면 불가능했을 거에요.