summaryrefslogtreecommitdiffstats
path: root/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
blob: b641f5941dcef64708f90cc6cdc2843bf40489cf (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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
pub trait Get<T> {
    fn get(self) -> T;
}

struct Foo {
    x: usize,
}

impl Get<usize> for Foo {
    fn get(self) -> usize {
        self.x
    }
}

fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
where
    G: Get<T>,
{
    move || {
        //~^ ERROR hidden type for `impl FnOnce()` captures lifetime
        *dest = g.get();
    }
}

// After applying suggestion for `foo`:
fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
where
    G: Get<T>,
{
    move || {
        //~^ ERROR the parameter type `G` may not live long enough
        *dest = g.get();
    }
}

// After applying suggestion for `bar`:
fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
//~^ ERROR undeclared lifetime name `'a`
where
    G: Get<T>,
{
    move || {
        *dest = g.get();
    }
}

// After applying suggestion for `baz`:
fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
where
    G: Get<T>,
{
    move || {
        //~^ ERROR the parameter type `G` may not live long enough
        *dest = g.get();
    }
}

// Same as above, but show that we pay attention to lifetime names from parent item
impl<'a> Foo {
    fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
        move || {
            //~^ ERROR the parameter type `G` may not live long enough
            *dest = g.get();
        }
    }
}

// After applying suggestion for `qux`:
fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
where
    G: Get<T>,
{
    move || {
        //~^ ERROR the parameter type `G` may not live long enough
        //~| ERROR explicit lifetime required
        *dest = g.get();
    }
}

// Potential incorrect attempt:
fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
where
    G: Get<T>,
{
    move || {
        //~^ ERROR the parameter type `G` may not live long enough
        *dest = g.get();
    }
}

// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure:
fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
where
    G: Get<T>,
{
    move || {
        *dest = g.get();
    }
}

// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions:
fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
where
    G: Get<T>,
{
    move || {
        *dest = g.get();
    }
}

fn main() {}