Unnamed repository; edit this file 'description' to name the repository.
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use expect_test::{expect, Expect};
use span::Edition;
use syntax::ast::{self, make};
use test_fixture::WithFixture;

use crate::{
    lower::LowerCtx,
    path::{
        lower::{hir_segment_to_ast_segment, SEGMENT_LOWERING_MAP},
        Path,
    },
    pretty,
    test_db::TestDB,
    type_ref::{TypesMap, TypesSourceMap},
};

fn lower_path(path: ast::Path) -> (TestDB, TypesMap, Option<Path>) {
    let (db, file_id) = TestDB::with_single_file("");
    let mut types_map = TypesMap::default();
    let mut types_source_map = TypesSourceMap::default();
    let mut ctx = LowerCtx::new(&db, file_id.into(), &mut types_map, &mut types_source_map);
    let lowered_path = ctx.lower_path(path);
    (db, types_map, lowered_path)
}

#[track_caller]
fn check_hir_to_ast(path: &str, ignore_segments: &[&str]) {
    let path = make::path_from_text(path);
    SEGMENT_LOWERING_MAP.with_borrow_mut(|map| map.clear());
    let _ = lower_path(path.clone()).2.expect("failed to lower path");
    SEGMENT_LOWERING_MAP.with_borrow(|map| {
        for (segment, segment_idx) in map {
            if ignore_segments.contains(&&*segment.to_string()) {
                continue;
            }

            let restored_segment = hir_segment_to_ast_segment(&path, *segment_idx as u32)
                .unwrap_or_else(|| {
                    panic!(
                        "failed to map back segment `{segment}` \
                        numbered {segment_idx} in HIR from path `{path}`"
                    )
                });
            assert_eq!(
                segment, &restored_segment,
                "mapping back `{segment}` numbered {segment_idx} in HIR \
                from path `{path}` produced incorrect segment `{restored_segment}`"
            );
        }
    });
}

#[test]
fn hir_to_ast_trait_ref() {
    check_hir_to_ast("<A as B::C::D>::E::F", &["A"]);
}

#[test]
fn hir_to_ast_plain_path() {
    check_hir_to_ast("A::B::C::D::E::F", &[]);
}

#[test]
fn hir_to_ast_crate_path() {
    check_hir_to_ast("crate::A::B::C", &[]);
    check_hir_to_ast("crate::super::super::A::B::C", &[]);
}

#[test]
fn hir_to_ast_self_path() {
    check_hir_to_ast("self::A::B::C", &[]);
    check_hir_to_ast("self::super::super::A::B::C", &[]);
}

#[test]
fn hir_to_ast_super_path() {
    check_hir_to_ast("super::A::B::C", &[]);
    check_hir_to_ast("super::super::super::A::B::C", &[]);
}

#[test]
fn hir_to_ast_type_anchor_path() {
    check_hir_to_ast("<A::B>::C::D", &["A", "B"]);
}

#[test]
fn hir_to_ast_path_super_in_middle() {
    check_hir_to_ast("A::super::B::super::super::C::D", &[]);
}

#[track_caller]
fn check_fail_lowering(path: &str) {
    let (_, _, lowered_path) = lower_path(make::path_from_text(path));
    assert!(lowered_path.is_none(), "path `{path}` should fail lowering");
}

#[test]
fn keywords_in_middle_fail_lowering1() {
    check_fail_lowering("self::A::self::B::super::C::crate::D");
}

#[test]
fn keywords_in_middle_fail_lowering2() {
    check_fail_lowering("A::super::self::C::D");
}

#[test]
fn keywords_in_middle_fail_lowering3() {
    check_fail_lowering("A::crate::B::C::D");
}

#[track_caller]
fn check_path_lowering(path: &str, expected: Expect) {
    let (db, types_map, lowered_path) = lower_path(make::path_from_text(path));
    let lowered_path = lowered_path.expect("failed to lower path");
    let mut buf = String::new();
    pretty::print_path(&db, &lowered_path, &types_map, &mut buf, Edition::CURRENT)
        .expect("failed to pretty-print path");
    expected.assert_eq(&buf);
}

#[test]
fn fn_like_path_with_coloncolon() {
    check_path_lowering("Fn::(A, B) -> C", expect![[r#"Fn::<(A, B), Output = C>"#]]);
    check_path_lowering("Fn::(A, B)", expect![[r#"Fn::<(A, B), Output = ()>"#]]);
}