1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16function assert_ccexc(f: () => void) {
17    try {
18        f();
19    } catch (e) {
20        assert(e instanceof ClassCastError);
21        return;
22    }
23    assert false : "exception expected";
24}
25
26function assert_nothrow(f: () => void) {
27    try {
28        f();
29    } catch (e) {
30        assert false : "unexpected exception";
31    }
32}
33
34class A { }
35class B { }
36class C { }
37
38function foo(x: Object | null | undefined) { return x as Object }
39
40function test_nullsafety() {
41    // Handling of Object may be a bit different, so test it separately
42    // let f = ... until inference in form ((p)=>expr)(a) is broken
43    assert_ccexc(() => { let f = ((x: Object | null | undefined) => x as Object); f(null); });
44    assert_ccexc(() => { let f = ((x: Object | null | undefined) => x as Object); f(undefined); });
45    assert_ccexc(() => { let f = ((x: Object | null) => x as Object); f(null); });
46    assert_ccexc(() => { let f = ((x: Object | undefined) => x as Object); f(undefined); });
47
48    assert_ccexc(() => { let f = ((x: Object | null | undefined) => x as Object | undefined); f(null); });
49    assert_ccexc(() => { let f = ((x: Object | null | undefined) => x as Object | null); f(undefined); });
50    assert_ccexc(() => { let f = ((x: Object | null) => x as Object | undefined); f(null); });
51    assert_ccexc(() => { let f = ((x: Object | undefined) => x as Object | null); f(undefined); });
52
53    assert_ccexc(() => { let f = ((x: A | null | undefined) => x as A); f(null); });
54    assert_ccexc(() => { let f = ((x: A | null | undefined) => x as A); f(undefined); });
55    assert_ccexc(() => { let f = ((x: A | null) => x as A); f(null); });
56    assert_ccexc(() => { let f = ((x: A | undefined) => x as A); f(undefined); });
57
58    assert_ccexc(() => { let f = ((x: A | null | undefined) => x as A | undefined); f(null); });
59    assert_ccexc(() => { let f = ((x: A | null | undefined) => x as A | null); f(undefined); });
60    assert_ccexc(() => { let f = ((x: A | null) => x as A | undefined); f(null); });
61    assert_ccexc(() => { let f = ((x: A | undefined) => x as A | null); f(undefined); });
62
63
64    assert_nothrow(() => { let f = ((x: Object | null | undefined) => x as Object); f(new Object()); });
65    assert_nothrow(() => { let f = ((x: Object | null | undefined) => x as Object); f(new Object); });
66    assert_nothrow(() => { let f = ((x: Object | null) => x as Object); f(new Object()); });
67    assert_nothrow(() => { let f = ((x: Object | undefined) => x as Object); f(new Object()); });
68
69    assert_nothrow(() => { let f = ((x: Object | null | undefined) => x as Object | undefined); f(new Object()); });
70    assert_nothrow(() => { let f = ((x: Object | null | undefined) => x as Object | null); f(new Object()); });
71    assert_nothrow(() => { let f = ((x: Object | null) => x as Object | undefined); f(new Object()); });
72    assert_nothrow(() => { let f = ((x: Object | undefined) => x as Object | null); f(new Object()); });
73
74    assert_nothrow(() => { let f = ((x: A | null | undefined) => x as A); f(new A()); });
75    assert_nothrow(() => { let f = ((x: A | null | undefined) => x as A); f(new A()); });
76    assert_nothrow(() => { let f = ((x: A | null) => x as A); f(new A()); });
77    assert_nothrow(() => { let f = ((x: A | undefined) => x as A); f(new A()); });
78
79    assert_nothrow(() => { let f = ((x: A | null | undefined) => x as A | undefined); f(new A()); });
80    assert_nothrow(() => { let f = ((x: A | null | undefined) => x as A | null); f(new A()); });
81    assert_nothrow(() => { let f = ((x: A | null) => x as A | undefined); f(new A()); });
82    assert_nothrow(() => { let f = ((x: A | undefined) => x as A | null); f(new A()); });
83}
84
85function test_unions() {
86    assert_ccexc(() => { let f = ((x: A | B | C) => x as A); f(new C()); });
87    assert_ccexc(() => { let f = ((x: A | B | C) => x as A | B); f(new C()); });
88    assert_ccexc(() => { let f = ((x: A | B | C | null) => x as A | B); f(null); });
89    assert_ccexc(() => { let f = ((x: A | B | C | undefined) => x as A | B); f(undefined); });
90
91    assert_ccexc(() => { let f = ((x: A | null | undefined) => x as A | undefined); f(null); });
92    assert_ccexc(() => { let f = ((x: A | null | undefined) => x as A | null); f(undefined); });
93    assert_ccexc(() => { let f = ((x: A | null) => x as A | undefined); f(null); });
94    assert_ccexc(() => { let f = ((x: A | undefined) => x as A | null); f(undefined); });
95
96    assert_ccexc(() => { let f = ((x: A | B | C) => x as A); f(new C()); });
97    assert_ccexc(() => { let f = ((x: A | B | C) => x as A | B); f(new C()); });
98    assert_ccexc(() => { let f = ((x: A | B | C | null) => x as A | B); f(null); });
99    assert_ccexc(() => { let f = ((x: A | B | C | undefined) => x as A | B); f(undefined); });
100
101    assert_ccexc(() => { let f = ((x: A | null | undefined) => x as A | undefined); f(null); });
102    assert_ccexc(() => { let f = ((x: A | null | undefined) => x as A | null); f(undefined); });
103    assert_ccexc(() => { let f = ((x: A | null) => x as A | undefined); f(null); });
104    assert_ccexc(() => { let f = ((x: A | undefined) => x as A | null); f(undefined); });
105}
106
107function main() {
108    test_nullsafety();
109    test_unions();
110}
111