[Rust] 1.64.0 업데이트 발표 (번역)
https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html
우리 러스트 팀은 새 버전 [1.64.0]을 발표하게 돼서 정말 기쁩니다!
러스트는 누구든 믿음직하고 효과적인 소프트웨어를 만들 수 있게 도와주는 끝내주는 언어입니다.
만약 rustup을 통해서 Rust의 이전버전을 설치해놓은 상대라면, 업데이트는 아주 쉽습니다. 그냥 이렇게 치면 돼요.
rustup update stable
rustup을 설치한 적이 없다면, 우리 웹사이트의 설치 페이지에서 받을 수 있습니다. 그리고 깃허브에서 이번 버전에 대한 릴리즈 노트를 참조해보세요.
미래의 릴리즈를 테스트해서 러스트 팀을 돕고 싶다면, 로컬에서 베타 채널(rustup default beta) 또는 nightly 채널(rustup default nightly)로 업데이트하는 것을 고려할 수 있습니다.
버그를 발견했다면 리포트해주세요!
1.64.0 stable에는 무엇이 있나요?
IntoFuture를 통한 .await 강화
Rust 1.64는 IntoFuture trait을 안정화했습니다.
IntoFuture는 IntoIterator와 비슷한 트레잇인데요. IntoIterator가 for ... in ... 루프를 제공하는 것과 다르게 .await의 동작에 영향을 줍니다.
IntoFuture를 사용하면 .await 키워드는 단순한 future 이외에도 await을 걸 수 있습니다. IntoFuture를 통해 Future로 변환할 수 있는 모든 것을 await할 수 있는 거죠.
이는 API를 더욱 사용자 친화적으로 만드는 데 도움이 될 수 있습니다.
네트워크를 통해 일부 스토리지 provider에 대한 요청을 구성하는 빌더를 예로 들어보겠습니다.
**pub struct Error { ... } **
**pub struct StorageResponse { ... }: **
**pub struct StorageRequest(bool); **
**impl StorageRequest { **
** ****/// Create a new instance of StorageRequest. ******
** pub fn new() -> Self { ... } **
** **/// Decide whether debug mode should be enabled. ******
** pub fn set_debug(self, b: bool) -> Self { ... } **
** /// Send the request and receive a response.
** pub async fn send(self) -> Result<StorageResponse, Error> { ... } **
**} **
일반적인 사용법은 다음과 같습니다.
**let response = StorageRequest::new() ****// 1. create a new instance ******
** .set_debug(true) ****// 2. set some option ******
** .send() ****// 3. construct the future ******
** .await?; ****// 4. run the future + propagate errors **
나쁘지는 않지만 더 잘할 수도 있을 거에요. IntoFuture를 사용하여 'future 구성'(3행)과 'future 실행'(4행)을 단일 단계로 결합할 수 있습니다.
**let response = StorageRequest::new() ****// 1. create a new instance ******
** .set_debug(true) ****// 2. set some option ******
** .await?; ****// 3. construct + run the future + propagate errors **
StorageRequest에 대해 IntoFuture를 구현하면 이를 수행할 수 있습니다.
IntoFuture를 사용하려면 반환할 수 있는 명명된 future가 있어야 하며, "boxed future"를 생성하고 이에 대한 타입 alias을 정의하여 수행할 수 있어야 합니다.
**// First we must import some new types into the scope. ******
**use std::pin::Pin; **
**use std::future::{Future, IntoFuture}; **
**pub struct Error { ... } **
**pub struct StorageResponse { ... } **
**pub struct StorageRequest(bool); **
**impl StorageRequest { **
** **** /// Create a new instance of StorageRequest. ******
** pub fn new() -> Self { ... } **
** ****/// Decide whether debug mode should be enabled. ******
** pub fn set_debug(self, b: bool) -> Self { ... } **
** /// Send the request and receive a response. **
** pub async fn send(self) -> Result<StorageResponse, Error> { ... } **
**} **
**// The new implementations: **
**// 1. create a new named future type **
**// 2. implement IntoFuture for StorageRequest ******
**pub type StorageRequestFuture = Pin<Box<dyn Future<Output = Result<StorageResponse, Error> + Send + 'static>> **
**impl IntoFuture for StorageRequest { **
** type IntoFuture = StorageRequestFuture; **
** type Output =
** fn into_future(self) -> Self::IntoFuture { **
** Box::pin(self.send()) **
** } **
}
구현에는 코드가 조금 더 필요하지만 사용자에게는 더 간단한 API를 제공합니다.
미래에 Rust Async WG는 타입 별칭(Type Alias Imp Trait or TAIT)에서 impl Trait을 지원하여 명명된 future 생성을 단순화하기를 바랍니다.
그렇게 하면 타입 별칭의 시그너처를 단순화해서 IntoFuture를 더 쉽게 구현할 수 있고 타입 별칭에서 Box를 제거하여 성능을 높일 수 있습니다.
core와 alloc에 대한 C-호환 FFI 타입
C ABI에서 호출하거나 호출될 때 Rust 코드는 c_uint 또는 c_ulong과 같은 타입 별칭을 사용하면 타겟별 코드나 조건문 없이도 모든 타겟에서 C의 타입을 사용할 수 있습니다.
이전에는 이러한 타입 별칭이 std에서만 사용할 수 있었고, core나 alloc만 사용할 수 있는 임베디드 타겟 및 기타 시나리오용으로 작성된 코드에서는 이러한 타입을 사용할 수 없었습니다.
이제 Rust 1.64는 core::ffi의 모든 c_* 타입 별칭과 C 문자열 작업을 위한 core::ffi::CStr을 제공합니다.
또한 전체 std 라이브러리 없이 alloc 크레이트만 사용하여 소유 C 문자열로 작업할 수 있도록 alloc::ffi::CString을 제공합니다.
rust-analyzer는 이제 rustup으로 사용가능.
Rust-analyzer는 이제 Rust의 도구 모음여 포함됩니다.
이제 Rust-analyzer를 더 쉽게 다운로드하고 액세스할 수 있으며, 더 많은 플랫폼에서 사용할 수 있습니다.
다음과 같이 rustup의 구성요소로서 설치해 사용할 수 있습니다.
**rustup component add rust-analyzer **
이때 Rustup이 설치된 버전을 실행하려면 다음과 같이 호출해야 합니다.
**rustup run stable rust-analyzer **
Rustup의 다음 릴리즈는 빌트인 프록시를 제공하여 executable rust-analyzer를 실행하면 적절한 버전을 시작할 것입니다.
대부분의 사용자는 더 자주 게시되는 rust-analyzer 팀에서 제공하는 릴리스(rust-analyzer 릴리스 페이지에서 사용 가능)를 계속 사용해야 합니다.
공식 VSCode 확장 사용자는 백그라운드에서 릴리스를 자동으로 다운로드하고 업데이트하므로 영향을 받지 않습니다.
Cargo 개선: workspace inheritance and multi-target builds
하나의 Cargo workspace에서 관련 라이브러리 또는 바이너리 크레이트 컬렉션으로 작업할 때.
이제는 크레이트 간에도 공통 버전 번호, 저장소 URL 또는 rust-version과 같은 공통 필드 값이 중복되는 것을 방지할 수 있습니다.
이건 업데이트할 때 이러한 값을 크레이트 간에 동기화된 상태로 유지하는 데에도 도움이 됩니다.
자세한 내용은 workspace.package, workspace.dependencies 및 "workspace에서 종속성 상속"을 참조하세요.
그리고 여러 타겟을 빌드할 때, 이제 여러개의 --target 옵션을 cargo build에 전달하여 한 번에 모든 target을 빌드할 수 있습니다.
또한 build.target을 .cargo/config.toml의 타겟 배열로 설정해서 기본적으로 여러 타겟을 빌드하도록 할 수도 있고요.
Stable이 된 API
다음 메서드와 트레잇 정의들은 이제 stable입니다.
future::IntoFuture
num::NonZero*::checked_mul
num::NonZero*::checked_pow
num::NonZero*::saturating_mul
num::NonZero*::saturating_pow
num::NonZeroI*::abs
num::NonZeroI*::checked_abs
num::NonZeroI*::overflowing_abs
num::NonZeroI*::saturating_abs
num::NonZeroI*::unsigned_abs
num::NonZeroI*::wrapping_abs
num::NonZeroU*::checked_add
num::NonZeroU*::checked_next_power_of_two
num::NonZeroU*::saturating_add
os::unix::process::CommandExt::process_group
os::windows::fs::FileTypeExt::is_symlink_dir
os::windows::fs::FileTypeExt::is_symlink_file
이 타입들은 이전에 std::ffi에서만 stable이었지만, 이제 core, alloc에서도 사용할 수 있습니다.
core::ffi::CStr
core::ffi::FromBytesWithNulError
alloc::ffi::CString
alloc::ffi::FromVecWithNulError
alloc::ffi::IntoStringError
alloc::ffi::NulError
이 타입들은 이전에 std::os::raw에서만 stable이었지만 이제는 core::ffi 및 std::ffi에서도 사용할 수 있습니다.
ffi::c_char
ffi::c_double
ffi::c_float
ffi::c_int
ffi::c_long
ffi::c_longlong
ffi::c_schar
ffi::c_short
ffi::c_uchar
ffi::c_uint
ffi::c_ulong
ffi::c_ulonglong
ffi::c_ushort
futures 기반의 저수준 구현인 Poll과 함께 사용할 일부 헬퍼를 안정화했습니다.
future::poll_fn
task::ready!
앞으로는 Poll 및 Pin과 같은 저수준의 세부정보를 덜 사용하는 더 간단한 API를 제공할 수 있기를 희망합니다. 하지만 일단은 이러한 헬퍼를 통해 이러한 코드를 더 쉽게 작성할 수 있습니다.
이 api는 이제 const 컨텍스트에서 사용가능합니다.
slice::from_raw_parts
호환성 노트
이전에 발표된 대로 linux 타겟에는 이제 최소 Linux 커널 3.2가 필요하고(이미 최신 커널이 필요한 타겟 제외) linux-gnu 타겟에는 glibc 2.17이 필요합니다(이미 최신 glibc가 필요한 타겟 제외).
Rust 1.64.0은 Ipv4Addr, Ipv6Addr, SocketAddrV4 및 SocketAddrV6의 메모리 레이아웃을 더 작고 메모리 효율적으로 변경합니다.
이 내부 표현은 노출된 적이 없지만 일부 크레이트는 std::mem::transmute를 사용하고 이에 의존하여 잘못된 메모리 액세스가 발생할 것입니다.
이러한 표준 라이브러리의 내부 구현 세부정보는 결코 안정적인 인터페이스로 간주되지 않습니다.
피해를 최소화하기 위해 우리는 1년 이상 되었으며 여전히 유지 관리되는 모든 크레이트의 작성자와 협력했습니다.
영향을 받는 대다수의 사용자는 크레이트 업데이트를 통해 완화할 수 있을 겁니다.
RLS 지원 중단(deprecation)의 일환으로, RLS 사본이 포함된 마지막 릴리즈이기도 합니다.
Rust 1.65.0부터 RLS는 사용 중단 경고를 표시하는 작은 LSP 서버로 대체됩니다.
기타 변경점
Rust 1.64 릴리스에는 다음과 같은 기타 변경 사항이 있습니다.
Rust 컴파일러의 Windows 빌드는 이제 프로필 기반(profile-guided) 최적화를 사용하여 코드를 컴파일할 때 10-20%의 성능 향상을 제공합니다.
사용되지 않는 필드가 포함된 구조체를 정의하면 rustc는 사용되지 않는 필드를 경고합니다.
이제 Rust 1.64에서 unused_tuple_struct_fields 린트를 활성화하여 튜플 구조체의 사용되지 않은 필드에 대해 동일한 경고를 받을 수 있습니다.
미래의 버전에서는 이 린트를 디폴트로 경고하도록 할 계획입니다. 단위("()") 타입의 필드는 이 경고를 생성하지 않으므로 튜플 인덱스를 변경하지 않고도 기존 코드를 쉽게 마이그레이션할 수 있습니다.
Rust, Cargo, Clippy에서 변경된 모든 사항을 확인하세요.
1.64.0의 컨트리뷰터들
1.64.0의 완성엔 수많은 사람들이 함께했습니다. 전부 여러분이 없었다면 불가능했을 거에요.