summaryrefslogtreecommitdiffstats
path: root/tests/codegen/debuginfo-generic-closure-env-names.rs
blob: b29f8b4a029d08ff0cf75a4668584d3f05d1318b (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
// This test checks that we get proper type names for closure environments and
// async-fn environments in debuginfo, especially making sure that generic arguments
// of the enclosing functions don't get lost.
//
// Unfortunately, the order that debuginfo gets emitted into LLVM IR becomes a bit hard
// to predict once async fns are involved, so DAG allows any order.
//
// Note that the test does not check async-fns when targeting MSVC because debuginfo for
// those does not follow the enum-fallback encoding yet and thus is incomplete.

// ignore-tidy-linelength

// Use the v0 symbol mangling scheme to codegen order independent of rustc version.
// Unnamed items like shims are generated in lexicographical order of their symbol name and in the
// legacy mangling scheme rustc version and generic parameters are both hashed into a single part
// of the name, thus randomizing item order with respect to rustc version.

// compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0

// non_generic_closure()
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]],
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]],
// CHECK: ![[non_generic_closure_NAMESPACE]] = !DINamespace(name: "non_generic_closure"

// CHECK: ![[function_containing_closure_NAMESPACE:[0-9]+]] = !DINamespace(name: "function_containing_closure"
// CHECK: ![[generic_async_function_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_function"
// CHECK: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block"

// function_containing_closure<u32>()
// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: ![[function_containing_closure_NAMESPACE]]
// MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: ![[function_containing_closure_NAMESPACE]]

// generic_async_function<Foo>()
// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_function_NAMESPACE]]

// generic_async_function<u32>()
// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: ![[generic_async_function_NAMESPACE]]

// generic_async_block<Foo>()
// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_block_NAMESPACE]]

// generic_async_block<u32>()
// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: ![[generic_async_block_NAMESPACE]]

// function_containing_closure<Foo>()
// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
// MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]


#![crate_type = "lib"]
use std::future::Future;

pub struct Foo;

pub fn non_generic_closure(x: Foo) -> Box<dyn FnOnce() -> Foo> {
    return Box::new(move || x);
}

fn function_containing_closure<T: 'static>(x: T) -> impl FnOnce() -> T {
    // This static only exists to trigger generating the namespace debuginfo for
    // `function_containing_closure` at a predictable, early point, which makes
    // writing the FileCheck tests above simpler.
    static _X: u8 = 0;

    return move || x;
}

async fn generic_async_function<T: 'static>(x: T) -> T {
    static _X: u8 = 0; // Same as above
    x
}

fn generic_async_block<T: 'static>(x: T) -> impl Future<Output=T> {
    static _X: u8 = 0; // Same as above
    async move {
        x
    }
}

pub fn instantiate_generics() {
    let _closure_u32 = function_containing_closure(7u32);
    let _closure_foo = function_containing_closure(Foo);

    let _async_fn_u32 = generic_async_function(42u32);
    let _async_fn_foo = generic_async_function(Foo);

    let _async_block_u32 = generic_async_block(64u32);
    let _async_block_foo = generic_async_block(Foo);
}