사용법을 설명하기 위해 다음 두 가지 오류 유형 및 함수가 제공됩니다 ( Rust Playground 링크 ).
#[derive(std::fmt::Debug)]
struct MyError;
#[derive(std::fmt::Debug)]
struct OtherError;
impl std::error::Error for MyError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
impl std::fmt::Display for MyError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MyError")
}
}
impl std::fmt::Display for OtherError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "OtherError")
}
}
impl std::error::Error for OtherError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
impl From<OtherError> for MyError {
fn from(_: OtherError) -> Self {
MyError {}
}
}
fn my_error() -> Result<(), MyError> { Ok(()) }
fn other_error() -> Result<(), OtherError> { Ok(()) }
내가 함수에 나는 경우 반환 Result
에 MyError
그와 같은 Error
유형, 나는 두 함수 모두 반환 호출 할 수 있습니다 MyError
그리고 OtherError
거기에 있기 때문에 From
그들 사이에 변환.
그러나 단순히 Result
"기타"유형에 대해 를 반환 할 수는 없습니다 . 대신 ?
뒤에 와야 Ok(())
합니다. 이것은 나에게 일치하지 않는 것 같습니다.
예를 들어 다음은 잘 작동합니다.
fn main() -> Result<(), MyError> {
my_error()
}
이것은 또한 다음을 수행합니다.
fn main() -> Result<(), MyError> {
my_error()?;
other_error()?;
my_error()
}
그러나 이것은 실패합니다.
fn main() -> Result<(), MyError> {
my_error()?;
other_error()
}
오류:
error[E0308]: mismatched types
--> src/main.rs:43:5
|
41 | fn main() -> Result<(), MyError> {
| ------------------- expected `std::result::Result<(), MyError>` because of return type
42 | my_error()?;
43 | other_error()
| ^^^^^^^^^^^^^ expected struct `MyError`, found struct `OtherError`
|
= note: expected enum `std::result::Result<_, MyError>`
found enum `std::result::Result<_, OtherError>`
왜 그런 겁니까?
이 작업을 수행하려면이 작업을 수행해야한다는 것을 알게 되었기 때문에 코드의 일부가 더 장황 해집니다.
fn main() -> Result<(), MyError> {
my_error()?;
other_error()?;
Ok(())
}
이것이 유일한 해결책입니까? 나는 그것이 이런 식으로 작동하는 이유를 이해하는 데 더 관심이 있지만 어리석은 일을하고 있다면 더 잘 할 수있는 것을 지적하십시오.
?
오퍼레이터는 동일하다 try!
다음과 같이 단순화 된 버전은 매크로 :
macro_rules! r#try {
($expr:expr $(,)?) => {
match $expr {
Ok(val) => val,
Err(err) => {
return Err(From::from(err));
}
}
};
}
결과 가 포함 된 복구 가능한 오류 페이지의 A Shortcut for Propagating Errors : the? 운영자 섹션.
match
Listing 9-6 의 표현식 이하는 것과?
연산자 가하는 것 사이에는 차이 가 있습니다.?
연산자가 호출 한 오류 값from
From
은 표준 라이브러리 의 특성 에 정의 된 함수를 통과하여 오류를 변환하는 데 사용됩니다. 한 유형에서 다른 유형으로. 때?
조작자가 전화from
기능을, 수신 오류 유형은 현재 함수의 리턴 타입에서 정의 된 에러의 종류로 변환된다. 이는 함수가 여러 가지 이유로 인해 일부가 실패하더라도 함수가 실패 할 수있는 모든 방법을 나타내는 하나의 오류 유형을 반환 할 때 유용합니다. 각 오류 유형이from
자신을 반환 된 오류 유형으로 변환하는 방법을 정의하는 함수를 구현하는 한?
연산자는 변환을 자동으로 처리합니다.
(강조 내)
예외 유형 업 캐스팅 섹션 에서 정보를 찾을 수 있는 RFC 243 에서 이에 대한 참조를 찾을 수도 있습니다 .
따라서
?
연산자는 하위 유형에서 상위 유형으로 강제 변환의 특성에서 이러한 암시 적 변환을 수행해야합니다. 현재 RFC는std::convert::Into
이 목적을 위해 특성을 사용합니다 (에서 일괄impl
전달이 있음From
). [...]
또한보십시오:
Rust By Example 에서 페이지 의 다른 용도?
도 암시 적 변환 동작을 언급합니다. 또한 사용자 지정 오류 유형을 만드는 예도 제공합니다.
결론적으로 다음과 같습니다.
fn main() -> Result<(), MyError> {
my_error()?;
other_error()?;
Ok(())
}
본질적으로 다음과 같습니다.
fn main() -> Result<(), MyError> {
match my_error() {
Ok(_) => {}
Err(err) => return Err(From::from(err));
}
match other_error() {
Ok(_) => {}
Err(err) => return Err(From::from(err));
}
Ok(())
}
반환 other_error()
하고 암시 적으로 오류를 변환하는 경우 약간 무섭습니다. 예를 들어 반환 유형이 수정되고 return ...
암시 적으로 단지 Into
이면 즉시 명확하지 않은 문제가 발생할 수 있습니다.
추가를 피 Ok(())
하려면 map_err()
, 즉를 사용할 수 있습니다 .map_err(From::from)
. 그러나 즉시 반환되지 않으면 컴파일러가 올바른 유형을 추론 할 수없는 경우 쉽게 실행할 수 있습니다.
이러한 경우에 당신은 더 명시 적 형태, 즉 사용할 수 있습니다 .map_err::<MyError, _>(From::from)
, 또는 단지를 .map_err(MyError::from)
.
fn main() -> Result<(), MyError> {
my_error()?;
// other_error().map_err(From::from)
// other_error().map_err::<MyError, _>(From::from)?;
other_error().map_err(MyError::from)
}
당신이 경우 MyError
했다 enum
있던, MyError::OtherError
변형, 당신도 바로 할 수 .map_err(MyError::OtherError)
. 이것은 enum
함수 호출처럼 보이는 것을 구성 할뿐만 아니라 실제로 functions로 구현되기 때문입니다 .
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다