1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 #![feature(core, fn_traits, unboxed_closures)]
13 use std
::marker
::PhantomData
;
15 // An erroneous variant of `run-pass/unboxed_closures-infer-recursive-fn.rs`
16 // where we attempt to perform mutation in the recursive function. This fails to compile
17 // because it winds up requiring `FnMut` which enforces linearity.
19 struct YCombinator
<F
,A
,R
> {
21 marker
: PhantomData
<(A
,R
)>,
24 impl<F
,A
,R
> YCombinator
<F
,A
,R
> {
25 fn new(f
: F
) -> YCombinator
<F
,A
,R
> {
26 YCombinator { func: f, marker: PhantomData }
30 impl<A
,R
,F
: FnMut(&mut FnMut(A
) -> R
, A
) -> R
> FnMut
<(A
,)> for YCombinator
<F
,A
,R
> {
31 extern "rust-call" fn call_mut(&mut self, (arg
,): (A
,)) -> R
{
32 (self.func
)(self, arg
)
33 //~^ ERROR cannot borrow `*self` as mutable more than once at a time
37 impl<A
,R
,F
: FnMut(&mut FnMut(A
) -> R
, A
) -> R
> FnOnce
<(A
,)> for YCombinator
<F
,A
,R
> {
39 extern "rust-call" fn call_once(mut self, args
: (A
,)) -> R
{
46 let factorial
= |recur
: &mut FnMut(u32) -> u32, arg
: u32| -> u32 {
48 if arg
== 0 {1}
else {arg * recur(arg-1)}
50 let mut factorial
: YCombinator
<_
,u32,u32> = YCombinator
::new(factorial
);
51 let mut r
= factorial(10);
52 assert_eq
!(3628800, r
);