1/*
2 * Copyright (c) 2023-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
26class A { }
27class B { }
28class C { }
29class X<T> { }
30
31function erase<T>(x: Object | null | undefined): T { return x as T; }
32
33function test_substitution() {
34    assert_ccexc(() => { erase<Object>(null); })
35    assert_ccexc(() => { erase<Object>(undefined); })
36    assert_ccexc(() => { erase<A>(null); })
37    assert_ccexc(() => { erase<A>(undefined); })
38
39    assert_ccexc(() => { erase<Object | undefined>(null); })
40    assert_ccexc(() => { erase<Object | null>(undefined); })
41    assert_ccexc(() => { erase<A | undefined>(null); })
42    assert_ccexc(() => { erase<A | null>(undefined); })
43
44    assert_ccexc(() => { erase<A>(undefined); })
45    assert_ccexc(() => { erase<A>(new Object()); })
46    assert_ccexc(() => { erase<A>(new B()); })
47
48    assert_ccexc(() => { erase<A | B>(undefined); })
49    assert_ccexc(() => { erase<A | B>(new Object()); })
50    assert_ccexc(() => { erase<A | B>(new C()); })
51
52    assert_ccexc(() => { erase<A[]>(new B[0]); })
53}
54
55class Erased<T> {
56    constructor(x: Object | null | undefined) { this.t = x as T; }
57    t: T;
58}
59
60function test_substitution_memberexpr() {
61    assert_ccexc(() => { new Erased<Object>(null).t; })
62    assert_ccexc(() => { new Erased<Object>(undefined).t; })
63    assert_ccexc(() => { new Erased<A>(null).t; })
64    assert_ccexc(() => { new Erased<A>(undefined).t; })
65
66    assert_ccexc(() => { new Erased<Object | undefined>(null).t; })
67    assert_ccexc(() => { new Erased<Object | null>(undefined).t; })
68    assert_ccexc(() => { new Erased<A | undefined>(null).t; })
69    assert_ccexc(() => { new Erased<A | null>(undefined).t; })
70
71    assert_ccexc(() => { new Erased<A>(undefined).t; })
72    assert_ccexc(() => { new Erased<A>(new Object()).t; })
73    assert_ccexc(() => { new Erased<A>(new B()).t; })
74
75    assert_ccexc(() => { new Erased<A | B>(undefined).t; })
76    assert_ccexc(() => { new Erased<A | B>(new Object()).t; })
77    assert_ccexc(() => { new Erased<A | B>(new C()).t; })
78
79    assert_ccexc(() => { new Erased<A[]>(new B[0]).t; })
80}
81
82function cast_to_tparam<T extends A | B | null>(x: Object | null | undefined) { x as T; }
83
84function test_constraint() {
85    assert_ccexc(() => { cast_to_tparam<A>(undefined); })
86    assert_ccexc(() => { cast_to_tparam<A>(new Object()); })
87    assert_ccexc(() => { cast_to_tparam<A>(new C()); })
88}
89
90function to_basetype<T>(x: Object | null | undefined) { return x as X<T>; }
91
92function test_basetype() {
93    assert_ccexc(() => { to_basetype<A>(null); })
94    assert_ccexc(() => { to_basetype<A>(undefined); })
95    assert_ccexc(() => { to_basetype<A>(new Object()); })
96    assert_ccexc(() => { to_basetype<A>(new C()); })
97}
98
99function main() {
100    test_substitution();
101    test_substitution_memberexpr();
102    test_constraint();
103    test_basetype();
104}
105