summaryrefslogtreecommitdiffstats
path: root/tests/ui/regions/region-borrow-params-issue-29793-big.rs
blob: 83b1a6eab57b457032bbf647b010152faa9958e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Issue #29793, big regression test: do not let borrows of
// parameters to ever be returned (expanded with exploration of
// variations).
//
// This is the version of the test that actually exposed unsound
// behavior (because the improperly accepted closure was actually
// able to be invoked).

struct WrapA<F>(Option<F>);

impl<F> WrapA<F> {
    fn new() -> WrapA<F> {
        WrapA(None)
    }
    fn set(mut self, f: F) -> Self {
        self.0 = Some(f);
        self
    }
}

struct WrapB<F>(Option<F>);

impl<F> WrapB<F> {
    fn new() -> WrapB<F> {
        WrapB(None)
    }
    fn set(mut self, f: F) -> Self {
        self.0 = Some(f);
        self
    }
}

trait DoStuff : Sized {
    fn handle(self);
}

impl<F, T> DoStuff for WrapA<F>
    where F: FnMut(usize, usize) -> T, T: DoStuff {
        fn handle(mut self) {
            if let Some(ref mut f) = self.0 {
                let x = f(1, 2);
                let _foo = [0usize; 16];
                x.handle();
            }
        }
    }

impl<F> DoStuff for WrapB<F> where F: FnMut(bool) -> usize {
    fn handle(mut self) {
        if let Some(ref mut f) = self.0 {
            println!("{}", f(true));
        }
    }
}

impl<F, T> WrapA<F>
    where F: FnMut(usize, usize) -> T, T: DoStuff {
        fn handle_ref(&mut self) {
            if let Some(ref mut f) = self.0 {
                let x = f(1, 2);
            }
        }
    }

fn main() {
    let mut w = WrapA::new().set(|x: usize, y: usize| {
        WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
            //~^ ERROR closure may outlive the current function
            //~| ERROR closure may outlive the current function
    });

    w.handle(); // This works
    // w.handle_ref(); // This doesn't
}