2017-12-21 10 views
1

조금 혼란 스럽네요. Option::map()입니다. documentationFnOnce을 허용한다고 말합니다.Option :: map (FnOnce)이 FnOnce를 수락하지 않는 것 같습니다 ...?

그렇다면 ab은 왜 컴파일 오류가 발생합니까?

let mut v = 3; 

let mut a: &FnOnce(u32) -> u32 = &|x: u32| { v = x; x }; 
let mut b: &FnMut(u32) -> u32 = &|x: u32| { x }; 
let mut c: &Fn(u32) -> u32 = &|x: u32| { x }; 

let o = Option::Some(3); 

o.map(a); // trait bound `std::ops::FnOnce(u32) -> u32: std::ops::Fn<(u32,)>` is not satisfied 
o.map(b); // trait bound `std::ops::FnMut(u32) -> u32: std::ops::Fn<(u32,)>` is not satisfied 
o.map(c); // works 

ab 등 그들 모두는 this post에 따라 FnOnce 구현하지 않나요?

답변

3

문제는 사용자가 직접 FnOnce을 사용하여 Option::map을 호출하지 않고 &FnOnce을 사용한다는 것입니다.

그러나 당신이 implementors for FnOnce 보면, 당신은 FnOnce&Fn 구현하는 동안, 그것은 &FnOnce 또는 &FnMut 구현되지 않는다는 것을 알 수 있습니다. 이유를 이해하려면 다음을 고려하십시오.

let a: &FnOnce(u32) -> u32 = &|x: u32| { v = x; x }; 
let b: &FnOnce(u32) -> u32 = a; 

a(42); // would be allowed if `&FnOnce: FnOnce`, moves `a` 
     // actually gives: 
     // error[E0507]: cannot move out of borrowed content 
a(6); // would not be allowed as `a` was moved 
b(7); // would be allowed if `&FnOnce: FnOnce` 
     // oh no! this calls the function again!