summaryrefslogtreecommitdiffstats
path: root/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs
blob: f1ea6627aab86f569c4f5c9d95c4812f7185208d (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
#![feature(unboxed_closures)]

// Test for projection cache. We should be able to project distinct
// lifetimes from `foo` as we reinstantiate it multiple times, but not
// if we do it just once. In this variant, the region `'a` is used in
// an contravariant position, which affects the results.

// revisions: ok oneuse transmute krisskross
//[ok] check-pass
//[oneuse] check-pass

#![allow(dead_code, unused_variables)]

fn foo<'a>() -> &'a u32 { loop { } }

fn bar<T>(t: T, x: T::Output) -> T::Output
    where T: FnOnce<()>
{
    t()
}

#[cfg(ok)] // two instantiations: OK
fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
    let a = bar(foo, x);
    let b = bar(foo, y);
    (a, b)
}

#[cfg(oneuse)] // one instantiation: OK (surprisingly)
fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
    let f /* : fn() -> &'static u32 */ = foo; // <-- inferred type annotated
    let a = bar(f, x); // this is considered ok because fn args are contravariant...
    let b = bar(f, y); // ...and hence we infer T to distinct values in each call.
    (a, b)
}

#[cfg(transmute)] // one instantiations: BAD
fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
   bar(foo, x) //[transmute]~ ERROR lifetime may not live long enough
}

#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
   let a = bar(foo, y);
   let b = bar(foo, x);
   (a, b) //[krisskross]~ ERROR lifetime may not live long enough
   //[krisskross]~^ ERROR lifetime may not live long enough
}

fn main() { }