[Rust] 1.79.0 업데이트 발표 (번역)

https://blog.rust-lang.org/2024/06/13/Rust-1.79.0.html

러스트는 누구든 믿음직하고 효과적인 소프트웨어를 만들 수 있게 도와주는 끝내주는 언어입니다.

만약 rustup을 통해서 Rust의 이전버전을 설치해놓은 상대라면, 업데이트는 아주 쉽습니다. 그냥 이렇게 치면 돼요.

rustup update stable

rustup을 설치한 적이 없다면, 우리 웹사이트의 설치 페이지에서 받을 수 있습니다. 그리고 깃허브에서 이번 버전에 대한 릴리즈 노트를 참조해보세요.

미래의 릴리즈를 테스트해서 러스트 팀을 돕고 싶다면, 로컬에서 베타 채널(rustup default beta) 또는 nightly 채널(rustup default nightly)로 업데이트하는 것을 고려할 수 있습니다.

버그를 발견했다면 리포트해주세요!



1.79.0 stable에는 무엇이 있나요?


inline const expressions

표현식 위치에서의 const {... } 블록은 이제 stable하게 사용할 수 있습니다.

이걸 사용하면 추가적인 선언. 그러니까, trait에 대한 const item 정의나 associated constants 정의 같은 것 없이 명시적으로 const 컨텍스트에 입력할 수 있어요.

const item을 (const ITEM: ... = ...)처럼 하나하나 선언했던 과거와 달리, 인라인 const는 in-scope 제네릭을 사용할 수 있으며, 명시적으로 작성하지 않아도 타입을 추론할 수 있습니다.
특히 인라인 코드 스니펫에 유용하죠.

한번 예제를 보죠.

const EMPTY: Option<Vec> = None;
let foo = [EMPTY; 100];

상수를 선언한 다음에 그걸 다른 변수 할당에 사용했습니다.
하지만 이건 이제 이렇게도 쓰일 수 있습니다.

let foo = [const { None }; 100];

상수 할당 없이 바로 넣어버린거죠.

특히 이건 이전에 상수가 연관되어 장황한 trait 선언을 사용했던 일반적인 컨텍스트들에도 다 적용됩니다.
이젠 다 아래처럼 걸어버릴 수 있어요.

fn create_none_array<T, const N: usize>() -> [Option; N] {
** [const { None:: }; N]**
}

더 자세한 내용은 관련 문서를 참조해주세요.




associated type 위치에서의 Bound

Rust 1.79에서는 associated item bounds 신택스를 안정화하여 다른 Bound 내에서도 associated type 위치에 Bound를 둘 수 있습니다.
T: Trait<Assoc: Bounds...>. 이런 식으로 말이죠

이건 단지 associated type을 제한하기 위해 추가로 명시적인 일반 타입을 제공할 필요를 줄여줍니다.

이 기능을 사용하면 이전에는 불가능했거나 사용에 대해 불필요한 제약이 붙었던 몇 곳에서 Bound를 좀더 적극적으로 지정할 수 있습니다.

where 절
where bound를 두 개 이상의 bound로 분해할 수도 있고, 하나로 쓰는 것도 가능합니다.
예를 들어, T: Trait<Assoc: Bound>는 T: Trait, :Assoc: Bound로도 표현할 수 있습니다.

Supertraits
Supertrait어 대한 새로운 Bound 신택스는 where 절과는 다르게 trait을 사용할 때 암시됩니다.
아래는 예시 코드입니다.
trait CopyIterator: Iterator<Item: Copy> {}.

**Associated type item bounds **
이젠 trait의 associated types과 관련된 nested rigid projections을 제한할 수 있습니다.
trait Trait { type Assoc: Trait2<Assoc2: Copy>; }.

**opaque type bounds (RPIT, TAIT) **
이는 opaque type을 명명할 필요 없이 opaque type 연관된 associated types을 제약할 수 있게 합니다.
예를 들어, impl Iterator<Item: Copy>는 실제로 해당 항목의 바인딩 이름을 지정할 필요 없이 항목이 Copy인 iterator를 정의합니다.

더 자세한 내용을 원한다면 관련 리포트를 참조해주세요.




temporary lifetime의 자동 연장

구성(construction)을 거쳐서 즉시 참조되는 임시 참조는 이제 match나 if 구성의 경우에도 자동으로 lifetime이 연장됩니다.
이건 블록 구성에서 임시 참조에 대한 lifetime 연장과 동일한 동작을 갖습니다.

아개는 그에 대한 예시입니다.

let a = if true {
** ..;**
** &temp()**** // 예전엔 오류가 발생했지만 이제는 수명이 연장됩니다.******
} else {
** ..;**
** &temp() // 예전엔 오류가 발생했지만 이제는 수명이 연장됩니다.**
};
그리고

let a = match () {
** _ => {**
** ..;**
** &temp() // 예전엔 오류가 발생했지만 이제는 수명이 연장됩니다.**
** }**
};

예전에는 이것만 됐었죠

let a = {
** ..;**
** &temp() // lifetime이 연장됨**
};

컴파일에 실패하는 데 사용되었던 동작이기 때문에 이 동작은 역호환(backwards compatible)됩니다.




표준 라이브러리 빌드에서 Frame pointers 활성화

러스트 프로젝트에서 배포한 표준 라이브러리는 이제 -Cforce-frame-pointers=yes로 컴파일되어 downstream 사용자가 프로그램을 보다 쉽게 프로파일링할 수 있습니다.

표준 라이브러리는 Cargo의 release 프로필에서 기본적으로 stripped되지만, line level 디버그 정보(예: DWARF)는 계속 제공합니다.




Stable이 된 API

{integer}::unchecked_add
{integer}::unchecked_mul
{integer}::unchecked_sub
<[T]>::split_at_unchecked
<[T]>::split_at_mut_unchecked
<[u8]>::utf8_chunks
str::Utf8Chunks
str::Utf8Chunk
<*const T>::is_aligned
<*mut T>::is_aligned
NonNull::is_aligned
<*const [T]>::len
<*mut [T]>::len
<*const [T]>::is_empty
<*mut [T]>::is_empty
NonNull::<[T]>::is_empty
CStr::count_bytes
io::Error::downcast
num::NonZero
path::absolute
proc_macro::Literal::byte_character
proc_macro::Literal::c_string

이 API들은 이제 const 버전도 stable이 됩니다.

Atomic*::into_inner
io::Cursor::new
io::Cursor::get_ref
io::Cursor::position
io::empty
io::repeat
io::sink
panic::Location::caller
panic::Location::file
panic::Location::line
panic::Location::column




기타 변경점

이외의 모든 변경사항은 각각 Rust, Cargo, Clippy에서 확인하세요.




1.79.0의 컨트리뷰터들에게

1.79.0의 완성엔 수많은 사람들이 함께했습니다. 전부 여러분이 없었다면 불가능했을 거에요.

고마워요!