[Rust] 1.41.0 업데이트 발표 (번역)
원본
https://blog.rust-lang.org/2020/01/30/Rust-1.41.0.html
이틀전에 업뎃됐길래 번역도 함 해봤다.
...
우리 러스트 팀은 새 버전 [1.41.0]을 발표하게 돼서 정말 기쁩니다!
러스트는 누구든 믿음직하고 효과적인 소프트웨어를 만들 수 있게 도와주는 끝내주는 언어입니다.
만약 rustup을 통해서 Rust의 이전버전을 설치해놓은 상대라면, 업데이트는 아주 쉽습니다. 그냥 이렇게 치면 돼요.
**rustup update stable **
rustup을 설치한 적이 없다면, 우리 웹사이트의 설치 페이지에서 받을 수 있습니다. 그리고 깃허브에서 이번 버전에 대한 릴리즈 노트를 참조해보세요.
1.41.0 stable****엔 무엇이 있나요?
Rust 1.41의 하이라이트는 trait 구현의 완화된 제약, cargo install 개선, 더 git에 친숙한 Cargo.lock, 그리고 Box
이 포스트에서 다루지 않은 다른 변경 내역들을 확인하고 싶다면 릴리즈노트를 참조하세요.
트레잇 구현 시의 완화된 제약
의존성에 새로운 trait impl을 추가할 경우 에코시스템에서의 파손를 예방하기 위해. 러스트는 orphan rule을 강제했습니다.
요지는, 해당 트레잇이나 구현된 타입이 외부(foreign) 크레이트와는 반대로, 현재 크레이트에 대해 지역적(local)인 경우에만 trait impl이 허용된다는 겁니다.
근데 이건 제너릭이 연관되면 의미가 굉장히 복잡해집니다.
1.41 전에는 orphan rule이 지나치게 빡빡해서, 구성(composition)에 걸림돌이 되곤 했습니다.
예를 들어 BetterVec
그럼 코드는 이런식으로 쓸 수 있겠죠
impl
**{ **
** **** // ... **
**} **
...은 이 패턴의 인스턴스입니다.
**impl
{ **
ㅤ// ... **
**} **
1.40에서 이 impl은 orphan rule에 의해 금지됐습니다.(forbidden)
그리고 From과 Vec은 표준 라이브러리에 정의된 거고, 현재 크레이트와는 별개(foreign)죠.
newtypepattern과 같은 제약 회피법이 있긴 했지만, 번거로운 데다 어떤 경우에선 적용이 불가능했습니다.
From과 Vec가 외부 크레이트인건 그대로지만, 해당 트레잇(이 경우엔 From)은 로컬 타입에 의해 파라미터화될 수 있습니다.
따라서, 1.41은 이러한 impl을 허용합니다.
더 자세한 내용을 원한다면, the stabilization report와 the RFC proposing the change를 읽으시는걸 추천합니다.
만료시 cargo install 패키지 갱신
cargo install를 사용하면, 각자의 시스템에 바이너리 크레이트를 설치할 수 있습니다.
이 명령은 종종 Rust로 작성된 CLI 도구를 설치할 때 사용되기도 해요.
1.41에서부터, cargo install은 설치해놨던 것에 새 릴리즈가 뜬다면, 기존 설치를 업데이트할거에요.
이 릴리즈 전에는 옵션으로 --force 플래그를 줘서 확인도 없이 재설치하게 해야했죠.
충돌 가능성 낮춘 Cargo.lock 형식
일관적인 빌드 보장하기 위해, cargo는 Cargo.lock라는 파일을 사용합니다. 이건 의존성 버전과 체크섬(checksum)들을 포함해요.
근데 안타깝게도. 나열된 데이터는 별개 브랜치에서 의존성이 변경됐을 때, 불필요한 병합 충돌을 발생시켰습니다.
1.41은 해당 파일에 대한 새 형식을 만들어, 명시적으로 이러한 충돌을 피하게끔 했습니다.
이 새 형식은 모든 lockfiles에 사용될겁니다. 그리고 기존 lockfiles은 이전 형식에 종속될거고요... 별개란 말이죠.
여기 PR adding it에서 새 형식을 이끄는 선택들에 대해 배울 수 있습니다.
FFI에서 Box
1.41부터 Box
그래서 만약 C에서 호출된 extern "C" 러스트 함수를 가지고 있다면, 러스트 함수는 이제 특정 T에 대해 Box
C에선 대응되는 함수에 T*를 사용할 수 있게 되고요.
예제를 봅시다. C 측 코드에요.
**// C 헤더 **
// 호출자에게 소유권 반환함
*struct Foo foo_new(void); **
**// 호출자에게 소유권 받음. **
// null로 호출되면 no-op
*void foo_delete(struct Foo); **
그리고... 러스트 측에선 이렇게 할수 있을겁니다.
**#[repr(C)] pub struct Foo; **
**#[no_mangle] **
**pub extern "C" fn foo_new() -> Box
**{ **
** Box::new(Foo) **
} **
// NULL 가능성은 Option<_>로 표현됨. **
**#[no_mangle] **
**pub extern "C" **
**fn foo_delete(_: Option<Box
**{} **
여기서 알아둘건.
Box
이걸 보장하기 위해선, 전역할당자에서 시작된 Box만 사용하는게 베스트입니다.
중요: 최소한 현재는. C에서 정의됐지만 Rust에서 호출될 함수들에 Box
만약 그래야할 경우엔, C 타입들을 가능한 한 비슷하게 미러링해야합니다.
C의 정의에서 T*를 쓴 Box
더 많은 정보를 원한다면, 여기로 가보세요.
consult the documentation for Box
라이브러리 변경사항
1.41에선, 표준 라이브러리에 다음과 같은 추가사항이 있습니다.
Result::map_or과 Result::map_or_else 메서드가 stable이 되었습니다.
Option::map_or과 Option::map_or_else는 .map(|val| process(val)).unwrap_or(default) 패턴의 축약 표현에 가까워요.
NonZero* numerics은 정수 너비가 더 작다면 From<NonZero*>을 구현합니다.
예를 들면. NonZeroU16는 지금 From
Weak 포인터에 대한 weak_count와 strong_count 메서드들이 stable이 되었습니다.
std::rc::Weak::weak_count
std::rc::Weak::strong_count
std::sync::Weak::weak_count
std::sync::Weak::strong_count
이 메서드들은 각 할당에 대한 weak(rc::Weak, sync::Weak)나 strong(Rc, Arc) 포인터의 개수를 반환합니다.
MaybeUninit
32비트 애플 타겟에 대한 지원 감소
1.41은 i686-apple-darwin 타겟을 포함해서, 32비트 애플 타겟에 대한 컴파일러 지원을 가지는 마지막 릴리즈입니다.
러스트 1.42부터, 저 타겟들은 가장 낮은 지원 수준을 가지게 될 겁니다.
이 포스트에서 해당 변경에 대한 더 많은 정보를 얻을 수 있어요..
다른 변경사항들
1.41 릴리즈엔 이외에도 다른 변경사항들이 었습니다.
Rust, Cargo, Clippy 등...
그리고 우리는 컴파일타임을 개선하기 위해 MIR 최적화륵 시작했습니다.
이에 대한 정보를 얻고자 한다면 "Inside Rust" blog post를 참조하세요.
1.41.0의 컨트리뷰터들
1.41의 완성엔 수많은 사람들이 함께했습니다. 전부 여러분이 없었다면 불가능했을 거에요.
고마워요!