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

원문
https://blog.rust-lang.org/2020/03/12/Rust-1.42.html

우리 러스트 팀은 새 버전 [1.42.0]을 발표하게 돼서 정말 기쁩니다!
러스트는 누구든 믿음직하고 효과적인 소프트웨어를 만들 수 있게 도와주는 끝내주는 언어입니다.

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

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



1.42.0 stable엔 무엇이 있나요?

1.42.0의 하이라이트는 unwrap 시의 더 유용한 패닉 메세지, Error::description의 사용중단(deprecate) 등이 있습니다.

이 포스트에서 다루지 않은 변경 내역들을 확인하고 싶다면, 릴리즈 노트를 참조하세요.



유용해진 Option과 Result의 패닉 메세지 라인 넘

Rust 1.41.1에서는, Option::None 값에 대해 unwrap()을 호출하면 대충 이렇게 오류 메세지를 뿜어냅니다.

**thread 'main' panicked at 'called Option::unwrap() on a None value', /.../src/libcore/macros/mod.rs:15:40 **

비슷하게, unwrap_err와 expect_err에 의해 생성되는 패닉 메세지의 라인넘버와, Result 타입에 있는 대응 메서드들도 기본 라이브러리의 코어 내부를 참조합니다.

1.42.0에서, 이 8개의 모든 함수들은 호출된 위치의 라인넘버를 제공하는 패닉 메세지를 산출합니다.

새로운 에러 메세지는 이렇게 보일 겁니다.

**thread 'main' panicked at 'called Option::unwrap() on a None value', src/main.rs:2:5 **

이건 unwrap의 유효하지 않은 호출이 src/main.rs의 라인 2에 있었다는 뜻이죠.

이러한 행동은 #[track_caller]이란 어노테이션 덕분에 가능한 겁니다.
이 어노테이션은 아직 stable에서는 사용이 불가능한데요. 만약 이걸 쓰는 것에 관심이 있다면, 이 tracking issue를 보면서 진행 상황을 확인하면 됩니다.



서브슬라이스(Subslice) 패턴

1.26에서 슬라이스 패턴(slice patterns)이란 걸 stable로 넣었었죠. 이건 슬라이스를 매칭할 수 있게 해줬어요.

이런 식으로.

**fn foo(words: &[&str]) { **
**    match words { **
**        [] => println!("empty slice!"), **
**        [one] => println!("one element: {:?}", one), **
**        [one, two] => println!("two elements: {:?} {:?}", one, two), **
**        _ => println!("I'm not sure how many elements!"), **
**    } **
**} **

이건 슬라이스에 match를 할 수 있게 해주지만, 꽤 한계점이 있었습니다.
지원하길 원하는 정확한 사이즈를 선택해야만 했고. 원하지 않는 사이즈에 대해선 catch-all arm을 가져야만 했죠.

1.42에선 슬라이스의 일부분 매칭에 대한 지원이 확장됐습니다.

**fn foo(words: &[&str]) { **
**    match words { **
**        ["Hello", "World", "!", ..] => println!("Hello World!"), **
**        ["Foo", "Bar", ..] => println!("Baz"), **
**        rest => println!("{:?}", rest), **
**    } **
**} **

..는 "나머지(rest) 패턴"이라고 부릅니다. 슬라이스의 나머지를 매칭시켜주거든요.
위의 예제에선 슬라이스의 끝에서 나머지 패턴을 사용했는데요. 다른 방법을 사용할 수도 있습니다.

fn foo(words: &[&str]) { **
**    match words { **
**        **// 모든 걸 무시하지만 마지막 요소는 반드시 "!"
**       "[.., "!"] => println!("!!!"), **
**        ****// start는 모든 것의 슬라이스. 하지만 마지막은 반드시 "z"
.
**        [start @ .., "z"] => println!("starts with: {:?}", start), **
**      ****  // end는 모든 것의 슬라이스. 하지만 첫번째 요소는 반드시 "a"**
**        "a". ["a", end @ ..] => println!("ends with: {:?}", end), **
**        rest => println!("{:?}", rest), **
**    } **
**} **

더 많은 것을 배우고 싶나요? 그렇다면 우리가  Rust 블로그에 게시한 글을 봐보세요. 이 변경점뿐만 아니라 미래에 stable이 될 더 많은 패턴매칭의 개선안들을 논의했습니다.

슬라이스 패턴에 대해 더 많은 것을 알고싶다면 Thomas Hartmann의 포스트를 읽어보세요.



matches!

이번 stable 릴리즈엔 새로운 매크로, matches!가 추가되었습니다.
이 매크로는 표현식과 패턴을 허용합니다. 패턴이 표현식과 매칭된다면 true를 반환하죠.

이렇게요.

// match 표현식 사용
**match self.partial_cmp(other) { **
**    Some(Less) => true, _ => false, **
**} **

// matches! 매크로 사용
matches!(
**    self.partial_cmp(other), **
**    Some(Less)**
**) **


여기엔 | 패턴이나 if 가드 문법도 사용할 수가 있습니다.

let foo = 'f'; **
assert!(
**    matches!(foo, 'A'..='Z' | 'a'..='z')

**); **

let bar = Some(4); **
assert!(
**    matches!(bar, Some(x) if x > 2)

**); **


**use proc_macro::TokenStream;**가 이제 작동합니다.

Rust 2018에서, 우리는 마침내 extern crate에 대한 의존성을 제거했습니다.

원래 procedural 매크로는 좀 특별했죠. 그래서 procedural 매크로를 쓰려면  **extern crate proc_macro;**를 써야만 했습니다.

이번 릴리즈에서는.
만약 cargo를 사용할 경우, 2018 에디션에서 작업한 이 라인이 더이상 필요하지 않을 겁니다. 다른 어떤 크레이트에서도 use를 사용할 수 있을 거고요.

대부분의 프로젝트에선 이미 **use proc_macro::TokenStream;**을 사용하는 라인이 있는데요. 이 변경사항은 extern crate proc_macro; 라인을 지일 수 있게 해줄 겁니다.

이 변경사항은 대단한건 아니지만, procedural 매크로를 더 일반적인 코드에 가깝게 해줄 겁니다.



라이브러리들

iter::Empty 는 이제 어떤 T에 대해서도 Send와 Sync를 구현합니다.

Pin::{map_unchecked, map_unchecked_mut}는 더 이상 반환 타입이 Sized를 구현할 필요가 없습니다.

io::Cursor는 이제 PartialEq와 Eq를 구현합니다..

Layout::new는 이제 const입니다.



Stable화된 API

CondVar::wait_while & CondVar::wait_timeout_while

DebugMap::key & DebugMap::value

ManuallyDrop::take

ptr::slice_from_raw_parts_mut & ptr::slice_from_raw_parts



다른 변경점들

이것들 외에도 여러가지 변경점이 있는데요.
RustCargo에서 무엇이 바뀌었는지 확인해보세요.



호환성 노트

이 릴리즈엔 적어둘만한 2가지의 호환성 이슈가 있습니다.

  1. 표준 라이브러리에서의 사용중단(deprecate).
  2. 32비트 애플 타겟을 3티어로 강등한 것이죠.


Error::Description의 사용중단(deprecated)

누구나 가끔은, 실수를 할 때가 있죠.
Error::description 메서드는 이제 이러한 실수들 중 하나인 것으로 밝혀졌습니다.

이건 타입 시그너처에 문제가 있습니다.

**fn description(&self) -> &str **

description은 &str을 반환하기 때문에, 우리가 기대했던것만큼 유용하진 않았습니다.
이건 기본적으로 Error의 내용을 반환해야만 한다는 것을 의미하죠.
뭔가 말을 하고 싶어서 더 멋진 description을 산출하는 formatting을 사용할 수도 있는데. 무조건 String을 반환하라고 하니 문제죠.

그럼 그 대신, error 타입들은 Display/Debug 트레잇을 구현해서 오류의 desciptiom을 제공하면 되는 겁니다.

이 API는 Rust 1.0부터 존재했습니다.
우리는 오랫동안 이 목표를 위해 달려왔습니다. 1.27 때로 돌아가보면, 이 메서드는 soft한 사용중단(deprecated) 제안을 받았었거든요.

이게 무얼 의미하냐면. 이 함수에 디폴트 구현을 줬다는 겁니다.
그래서 이제는 사용자들이 더 이상 Error 트레잇을 구현할 때 이 메서드를 구현할 필요가 없습니다.

이번 릴리즈에서, 우리는 이걸 실제로 사용중단으로 표시했고, Error 문서에서 강조를 줄이는 등의 몇가지 단계를 거쳤습니다.

우리의 stable 정책에 따라. description은 절대 삭제되지 않을 겁니다. 그래서 우리가 할 수 있는건 여기까지에요.



32비트 애플 타겟 다운그레이드

애플은 더이상 32비트 타겟을 지원하지 않습니다. 우리도 그럴 거고요.
32비트 타겟은 이제 우리 프로젝트에서 3티어 지원 대상으로 다운그레이드됐습니다.

이 사항에 대해서 더 자세한 정보를 원하신다면, 1월에 작성된 이 포스트를 확인하세요.



1.42.0의 컨트리뷰터들

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