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

https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html

우리 러스트 팀은 새 버전 [1.63.0]을 발표하게 돼서 정말 기쁩니다!

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

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

rustup update stable

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

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

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




1.63.0 stable에는 무엇이 있나요?


Scoped threads

러스트는 1.0 부터 std:🧵:spawn으로 새 스레드를 시작할 수 있었는데요. 이 함수는 클로저를 'static'으로 제한합니다.

대략적으로, 이것은 스레드가 현재 클로저로 전달된 인자에 대한 소유권을 가지고 있어야 한다는 것을 의미합니다. borrow된 데이터를 스레드로 전달할 수도 없고요.
그런데 함수가 끝날 때면 스레드가 종료될 것으로 예상될 경우가 있을 수 있죠. .join()을 호출한다든지 하면요.
그럴때면 이게 꼭 필요하지 않은데, 그래도 데이터를 Arc로 구성하는 등의 방법을 써야 했죠.

이제 1.63부터는 표준 라이브러리에 scoped threads가 추가되었는데요. 이건 로컬 스택프레임에서 빌려오는 스레드를 생성하게 해줍니다.

std:🧵:scope API는 생성된 스레드가 return되기 전에 종료되도록 보장해주므로, 안전하게 데이터를 빌릴 수 있습니다.

다음은 예제 코드입니다.

**let mut a = vec![1, 2, 3]; **
**let mut x = 0; **


**std:🧵:scope(|s| { **
** s.spawn(|| { **
** println!("hello from the first scoped thread"); **
** ****// We can borrow a here. ******
** dbg!(&a); **
** }); **
** s.spawn(|| { **
** println!("hello from the second scoped thread"); **
** **** // We can even mutably borrow x here, **
** // because no other threads are using it. ******
** x += a[0] + a[2]; **
** }); **
** println!("hello from the main thread"); **
**}); **


**// After the scope, we can modify and access our variables again: ******
**a.push(4); **
**assert_eq!(x, a.len()); **




raw file descriptors/handles에 대한 소유권

이전에는 raw file descriptors(unix 스타일) 또는 핸들(Windows)을 사용하는 플랫폼 API로 작업하는 Rust 코드는 일반적으로 descriptor의 플랫폼별 표현(예: c_int 또는 alias RawFd)을 직접 사용했습니다.

이러한 네이티브 API에 대한 Rust 바인딩에서, 타입 시스템은 API가 descriptor의 소유권을 가질지(예: close) 아니면 단순히 빌려올 것인지(예: dup)를 제대로 결정하지 못했습니다.

이제 Rust는 #[repr(transparent)]로 표시된 BorrowedFd 및 OwnedFd와 같은 래퍼 타입을 제공합니다.
즉, extern 'C' 바인딩은 이러한 타입을 직접 사용하여 소유권 의미 체계를 적용할 수 있습니다.

1.63에서 안정화된 전체 래퍼 타입 목록은 안정화된 API 섹션을 참조하세요.
현재 cfg(unix) 플랫폼, Windows, WASI에서 사용할 수 있습니다.

새 API는 이전 타입 aliases(예: RawFd) 대신 이러한 타입을 사용하는 것을 추천합니다.





Mutex, RwLock, Condvar의 초기화 const 버전

함수는 이제 const 컨텍스트에서 호출할 수 있습니다.
이제는 Mutex, RwLock 또는 Condvar 값으로 전역 static을 생성하기 위해 lazy_static과 같은 크레잇을 사용하지 않아도 됩니다.

이는 Linux에서 더 얇고 빠른 뮤텍스를 활성화하기 위해 1.62의 작업을 기반으로 합니다.




impl Trait가 있는 함수의 제네릭 Turbofish

역주
turbofish: 제네릭 타입 명시 연산자 ::를 뜻함

fn foo(value: T, f: impl Copy)와 같은 함수 시그너처의 경우 Turbofish를 통해 T의 구체적인 유형을 지정하는 것은 오류였습니다.
foo::(3, 3)은 다음과 같이 실패합니다.

**error[E0632]: cannot provide explicit generic arguments when impl Trait is used in argument position **
**--> src/lib.rs:4:11 **
** | **
**4 | foo::(3, 3); **
** | ^^^ explicit generic argument not allowed **
** | **
** = note: see issue #83701 https://github.com/rust-lang/rust/issues/83701 for more information **

1.63에서는 이 제한이 완화되었으며, 제네릭의 타입을 명시적으로 지정할 수 있습니다.

그러나 impl Trait 매개변수는 제네릭으로 desugar하더라도 여전히 불투명(opaque)하며 터보피쉬로 지정할 수 없습니다.




Non-lexical lifetimes 마이그레이션 완료

포스트에 설명되어 있듯이, 우리는 모든 버전의 rustc에서 이전 lexical borrow checker를 완전히 제거하고 lexical이 아닌 새로운 borrow checker를 완전히 활성화했습니다.

borrow checker는 rustc의 출력에 영향을 주지 않으므로 프로그램의 동작을 바꾸지는 않지만, 장기 실행 마이그레이션(2018년판 NLL의 초기 안정화 단계부터 시작)을 완료하여 새로운 borrow checker의 이점을 모든 버전의 Rust에 제공합니다.

대부분의 사용자에게 이 변경은 일부 borrow checking 오류에 대해 약간 더 나은 진단을 제공하지만, 소스코드에는 영향을 미치지 않습니다.

2018년 에디션 발표의 이 섹션에서 non-lexical lifetimes에 대해 자세히 알아볼 수 있습니다.




Stable이 된 API

다음 메서드와 트레잇 구현은 이제 stable입니다.
array::from_fn
Box::into_pin
BinaryHeap::try_reserve
BinaryHeap::try_reserve_exact
OsString::try_reserve
OsString::try_reserve_exact
PathBuf::try_reserve
PathBuf::try_reserve_exact
Path::try_exists
Ref::filter_map
RefMut::filter_map
NonNull::<[T]>::len
ToOwned::clone_into
Ipv6Addr::to_ipv4_mapped
unix::io::AsFd
unix::io::BorrowedFd<'fd>
unix::io::OwnedFd
windows::io::AsHandle
windows::io::BorrowedHandle<'handle>
windows::io::OwnedHandle
windows::io::HandleOrInvalid
windows::io::HandleOrNull
windows::io::InvalidHandleError
windows::io::NullHandleError
windows::io::AsSocket
windows::io::BorrowedSocket<'handle>
windows::io::OwnedSocket
thread::scope
thread::Scope
thread::ScopedJoinHandle

이제 const 컨텍스트에서 사용 가능한 api입니다.
array::from_ref
slice::from_ref
intrinsics::copy
intrinsics::copy_nonoverlapping
<*const T>::copy_to
<*const T>::copy_to_nonoverlapping
<*mut T>::copy_to
<*mut T>::copy_to_nonoverlapping
<*mut T>::copy_from
<*mut T>::copy_from_nonoverlapping
str::from_utf8
Utf8Error::error_len
Utf8Error::valid_up_to
Condvar::new
Mutex::new
RwLock::new




기타 변경점

1.63 릴리즈에는 이외의 기타 변경점들도 있습니다. RustCargoClippy에서 무엇이 바뀌었는지 확인해보세요.




1.63.0의 컨트리뷰터들

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

고마워요!​