1 // Copyright 2021 The Tint Authors.
2 //
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 #include "src/ast/struct_block_decoration.h"
16 #include "src/resolver/resolver.h"
17 #include "src/resolver/resolver_test_helper.h"
18
19 #include "gmock/gmock.h"
20
21 namespace tint {
22 namespace resolver {
23 namespace {
24
25 // Helpers and typedefs
26 template <typename T>
27 using DataType = builder::DataType<T>;
28 template <typename T>
29 using vec2 = builder::vec2<T>;
30 template <typename T>
31 using vec3 = builder::vec3<T>;
32 template <typename T>
33 using vec4 = builder::vec4<T>;
34 template <typename T>
35 using mat2x2 = builder::mat2x2<T>;
36 template <typename T>
37 using mat3x3 = builder::mat3x3<T>;
38 template <typename T>
39 using mat4x4 = builder::mat4x4<T>;
40 template <typename T>
41 using alias = builder::alias<T>;
42 using f32 = builder::f32;
43 using i32 = builder::i32;
44 using u32 = builder::u32;
45
46 struct ResolverInferredTypeTest : public resolver::TestHelper,
47 public testing::Test {};
48
49 struct Params {
50 builder::ast_expr_func_ptr create_value;
51 builder::sem_type_func_ptr create_expected_type;
52 };
53
54 template <typename T>
ParamsFor()55 constexpr Params ParamsFor() {
56 return Params{DataType<T>::Expr, DataType<T>::Sem};
57 }
58
59 Params all_cases[] = {
60 ParamsFor<bool>(), //
61 ParamsFor<u32>(), //
62 ParamsFor<i32>(), //
63 ParamsFor<f32>(), //
64 ParamsFor<vec3<bool>>(), //
65 ParamsFor<vec3<i32>>(), //
66 ParamsFor<vec3<u32>>(), //
67 ParamsFor<vec3<f32>>(), //
68 ParamsFor<mat3x3<f32>>(), //
69 ParamsFor<alias<bool>>(), //
70 ParamsFor<alias<u32>>(), //
71 ParamsFor<alias<i32>>(), //
72 ParamsFor<alias<f32>>(), //
73 ParamsFor<alias<vec3<bool>>>(), //
74 ParamsFor<alias<vec3<i32>>>(), //
75 ParamsFor<alias<vec3<u32>>>(), //
76 ParamsFor<alias<vec3<f32>>>(), //
77 ParamsFor<alias<mat3x3<f32>>>(), //
78 };
79
80 using ResolverInferredTypeParamTest = ResolverTestWithParam<Params>;
81
TEST_P(ResolverInferredTypeParamTest,GlobalLet_Pass)82 TEST_P(ResolverInferredTypeParamTest, GlobalLet_Pass) {
83 auto& params = GetParam();
84
85 auto* expected_type = params.create_expected_type(*this);
86
87 // let a = <type constructor>;
88 auto* ctor_expr = params.create_value(*this, 0);
89 auto* var = GlobalConst("a", nullptr, ctor_expr);
90 WrapInFunction();
91
92 EXPECT_TRUE(r()->Resolve()) << r()->error();
93 EXPECT_EQ(TypeOf(var), expected_type);
94 }
95
TEST_P(ResolverInferredTypeParamTest,GlobalVar_Fail)96 TEST_P(ResolverInferredTypeParamTest, GlobalVar_Fail) {
97 auto& params = GetParam();
98
99 // var a = <type constructor>;
100 auto* ctor_expr = params.create_value(*this, 0);
101 Global(Source{{12, 34}}, "a", nullptr, ast::StorageClass::kPrivate,
102 ctor_expr);
103 WrapInFunction();
104
105 EXPECT_FALSE(r()->Resolve());
106 EXPECT_EQ(r()->error(),
107 "12:34 error: global var declaration must specify a type");
108 }
109
TEST_P(ResolverInferredTypeParamTest,LocalLet_Pass)110 TEST_P(ResolverInferredTypeParamTest, LocalLet_Pass) {
111 auto& params = GetParam();
112
113 auto* expected_type = params.create_expected_type(*this);
114
115 // let a = <type constructor>;
116 auto* ctor_expr = params.create_value(*this, 0);
117 auto* var = Const("a", nullptr, ctor_expr);
118 WrapInFunction(var);
119
120 EXPECT_TRUE(r()->Resolve()) << r()->error();
121 EXPECT_EQ(TypeOf(var), expected_type);
122 }
123
TEST_P(ResolverInferredTypeParamTest,LocalVar_Pass)124 TEST_P(ResolverInferredTypeParamTest, LocalVar_Pass) {
125 auto& params = GetParam();
126
127 auto* expected_type = params.create_expected_type(*this);
128
129 // var a = <type constructor>;
130 auto* ctor_expr = params.create_value(*this, 0);
131 auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
132 WrapInFunction(var);
133
134 EXPECT_TRUE(r()->Resolve()) << r()->error();
135 EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type);
136 }
137
138 INSTANTIATE_TEST_SUITE_P(ResolverTest,
139 ResolverInferredTypeParamTest,
140 testing::ValuesIn(all_cases));
141
TEST_F(ResolverInferredTypeTest,InferArray_Pass)142 TEST_F(ResolverInferredTypeTest, InferArray_Pass) {
143 auto* type = ty.array(ty.u32(), 10);
144 auto* expected_type =
145 create<sem::Array>(create<sem::U32>(), 10, 4, 4 * 10, 4, 4);
146
147 auto* ctor_expr = Construct(type);
148 auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
149 WrapInFunction(var);
150
151 EXPECT_TRUE(r()->Resolve()) << r()->error();
152 EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type);
153 }
154
TEST_F(ResolverInferredTypeTest,InferStruct_Pass)155 TEST_F(ResolverInferredTypeTest, InferStruct_Pass) {
156 auto* member = Member("x", ty.i32());
157 auto* str = Structure("S", {member}, {create<ast::StructBlockDecoration>()});
158
159 auto* expected_type = create<sem::Struct>(
160 str, str->name,
161 sem::StructMemberList{create<sem::StructMember>(
162 member, member->symbol, create<sem::I32>(), 0, 0, 0, 4)},
163 0, 4, 4);
164
165 auto* ctor_expr = Construct(ty.Of(str));
166
167 auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
168 WrapInFunction(var);
169
170 EXPECT_TRUE(r()->Resolve()) << r()->error();
171 EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type);
172 }
173
174 } // namespace
175 } // namespace resolver
176 } // namespace tint
177