]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/typecheck/rust-tyty-call.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / typecheck / rust-tyty-call.cc
CommitLineData
a945c346 1// Copyright (C) 2020-2024 Free Software Foundation, Inc.
06688fe4
PH
2
3// This file is part of GCC.
4
5// GCC is free software; you can redistribute it and/or modify it under
6// the terms of the GNU General Public License as published by the Free
7// Software Foundation; either version 3, or (at your option) any later
8// version.
9
10// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13// for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with GCC; see the file COPYING3. If not see
17// <http://www.gnu.org/licenses/>.
18
19#include "rust-tyty-call.h"
20#include "rust-hir-type-check-expr.h"
21
22namespace Rust {
23namespace TyTy {
24
25void
26TypeCheckCallExpr::visit (ADTType &type)
27{
28 rust_assert (!variant.is_error ());
29 if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
30 {
31 rust_error_at (
32 call.get_locus (),
33 "expected function, tuple struct or tuple variant, found struct %<%s%>",
34 type.get_name ().c_str ());
35 return;
36 }
37
38 if (call.num_params () != variant.num_fields ())
39 {
40 rust_error_at (call.get_locus (),
41 "unexpected number of arguments %lu expected %lu",
42 (unsigned long) call.num_params (),
43 (unsigned long) variant.num_fields ());
44 return;
45 }
46
47 size_t i = 0;
48 for (auto &argument : call.get_arguments ())
49 {
50 StructFieldType *field = variant.get_field_at_index (i);
51 BaseType *field_tyty = field->get_field_type ();
af22b54a 52 Location arg_locus = argument->get_locus ();
06688fe4
PH
53
54 BaseType *arg = Resolver::TypeCheckExpr::Resolve (argument.get ());
55 if (arg->get_kind () == TyTy::TypeKind::ERROR)
56 {
57 rust_error_at (argument->get_locus (),
58 "failed to resolve argument type");
59 return;
60 }
61
af22b54a 62 HirId coercion_side_id = argument->get_mappings ().get_hirid ();
06688fe4 63 auto res = Resolver::TypeCheckBase::coercion_site (
af22b54a
PH
64 coercion_side_id, TyWithLocation (field_tyty),
65 TyWithLocation (arg, arg_locus), argument->get_locus ());
06688fe4
PH
66 if (res->get_kind () == TyTy::TypeKind::ERROR)
67 {
68 return;
69 }
70
06688fe4
PH
71 i++;
72 }
73
74 if (i != call.num_params ())
75 {
76 rust_error_at (call.get_locus (),
77 "unexpected number of arguments %lu expected %lu",
78 (unsigned long) i, (unsigned long) call.num_params ());
79 return;
80 }
81
82 resolved = type.clone ();
83}
84
85void
86TypeCheckCallExpr::visit (FnType &type)
87{
06688fe4
PH
88 if (call.num_params () != type.num_params ())
89 {
90 if (type.is_varadic ())
91 {
92 if (call.num_params () < type.num_params ())
93 {
94 rust_error_at (call.get_locus (),
95 "unexpected number of arguments %lu expected %lu",
96 (unsigned long) call.num_params (),
97 (unsigned long) type.num_params ());
98 return;
99 }
100 }
101 else
102 {
103 rust_error_at (call.get_locus (),
104 "unexpected number of arguments %lu expected %lu",
105 (unsigned long) call.num_params (),
106 (unsigned long) type.num_params ());
107 return;
108 }
109 }
110
111 size_t i = 0;
112 for (auto &argument : call.get_arguments ())
113 {
af22b54a 114 Location arg_locus = argument->get_locus ();
06688fe4
PH
115 auto argument_expr_tyty
116 = Resolver::TypeCheckExpr::Resolve (argument.get ());
117 if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
118 {
119 rust_error_at (
120 argument->get_locus (),
121 "failed to resolve type for argument expr in CallExpr");
122 return;
123 }
124
a9d72ef2 125 // it might be a variadic function
06688fe4
PH
126 if (i < type.num_params ())
127 {
128 auto fnparam = type.param_at (i);
af22b54a
PH
129 HIR::Pattern *fn_param_pattern = fnparam.first;
130 BaseType *param_ty = fnparam.second;
131 Location param_locus
132 = fn_param_pattern == nullptr
133 ? mappings->lookup_location (param_ty->get_ref ())
134 : fn_param_pattern->get_locus ();
135
136 HirId coercion_side_id = argument->get_mappings ().get_hirid ();
06688fe4 137 auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site (
af22b54a
PH
138 coercion_side_id, TyWithLocation (param_ty, param_locus),
139 TyWithLocation (argument_expr_tyty, arg_locus),
140 argument->get_locus ());
06688fe4
PH
141 if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
142 {
06688fe4
PH
143 return;
144 }
145 }
a9d72ef2
OA
146 else
147 {
148 switch (argument_expr_tyty->get_kind ())
149 {
150 case TyTy::TypeKind::ERROR:
151 return;
152 case TyTy::TypeKind::INT: {
153 auto &int_ty
154 = static_cast<TyTy::IntType &> (*argument_expr_tyty);
155 if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8)
156 || (int_ty.get_int_kind () == TyTy::IntType::IntKind::I16))
157 {
158 rust_error_at (arg_locus,
159 "expected %<c_int%> variadic argument");
160 return;
161 }
162 break;
163 }
164 case TyTy::TypeKind::UINT: {
165 auto &uint_ty
166 = static_cast<TyTy::UintType &> (*argument_expr_tyty);
167 if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8)
168 || (uint_ty.get_uint_kind ()
169 == TyTy::UintType::UintKind::U16))
170 {
171 rust_error_at (arg_locus,
172 "expected %<c_uint%> variadic argument");
173 return;
174 }
175 break;
176 }
177 case TyTy::TypeKind::FLOAT: {
178 if (static_cast<TyTy::FloatType &> (*argument_expr_tyty)
179 .get_float_kind ()
180 == TyTy::FloatType::FloatKind::F32)
181 {
182 rust_error_at (arg_locus,
183 "expected %<c_double%> variadic argument");
184 return;
185 }
186 break;
187 }
188 case TyTy::TypeKind::BOOL:
189 rust_error_at (arg_locus, "expected %<c_int%> variadic argument");
190 return;
191 case TyTy::TypeKind::FNDEF:
192 rust_error_at (arg_locus,
193 "unexpected function definition type as variadic "
194 "argument - cast to function pointer");
195 return;
196 default:
197 break;
198 }
199 }
06688fe4
PH
200
201 i++;
202 }
203
204 if (i < call.num_params ())
205 {
206 rust_error_at (call.get_locus (),
207 "unexpected number of arguments %lu expected %lu",
208 (unsigned long) i, (unsigned long) call.num_params ());
209 return;
210 }
211
212 type.monomorphize ();
213 resolved = type.get_return_type ()->clone ();
214}
215
216void
217TypeCheckCallExpr::visit (FnPtr &type)
218{
219 if (call.num_params () != type.num_params ())
220 {
221 rust_error_at (call.get_locus (),
222 "unexpected number of arguments %lu expected %lu",
223 (unsigned long) call.num_params (),
224 (unsigned long) type.num_params ());
225 return;
226 }
227
228 size_t i = 0;
229 for (auto &argument : call.get_arguments ())
230 {
af22b54a
PH
231 Location arg_locus = argument->get_locus ();
232 BaseType *fnparam = type.param_at (i);
06688fe4
PH
233 auto argument_expr_tyty
234 = Resolver::TypeCheckExpr::Resolve (argument.get ());
235 if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
236 {
237 rust_error_at (
238 argument->get_locus (),
239 "failed to resolve type for argument expr in CallExpr");
240 return;
241 }
242
243 auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site (
af22b54a
PH
244 argument->get_mappings ().get_hirid (), TyWithLocation (fnparam),
245 TyWithLocation (argument_expr_tyty, arg_locus), argument->get_locus ());
06688fe4
PH
246 if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
247 {
06688fe4
PH
248 return;
249 }
250
251 i++;
252 }
253
254 if (i != call.num_params ())
255 {
256 rust_error_at (call.get_locus (),
257 "unexpected number of arguments %lu expected %lu",
258 (unsigned long) i, (unsigned long) call.num_params ());
259 return;
260 }
261
262 resolved = type.get_return_type ()->monomorphized_clone ();
263}
264
265// method call checker
266
4d021d9e
PH
267TypeCheckMethodCallExpr::TypeCheckMethodCallExpr (
268 Analysis::NodeMapping call_mappings, std::vector<Argument> &args,
269 Location call_locus, Location receiver_locus, TyTy::BaseType *adjusted_self,
270 Resolver::TypeCheckContext *context)
271 : call_mappings (call_mappings), arguments (args), call_locus (call_locus),
272 receiver_locus (receiver_locus), adjusted_self (adjusted_self),
273 context (context), mappings (Analysis::Mappings::get ())
274{}
275
276BaseType *
277TypeCheckMethodCallExpr::go (FnType *ref, HIR::MethodCallExpr &call,
278 TyTy::BaseType *adjusted_self,
279 Resolver::TypeCheckContext *context)
280{
281 std::vector<Argument> args;
282 for (auto &arg : call.get_arguments ())
283 {
284 BaseType *argument_expr_tyty
285 = Resolver::TypeCheckExpr::Resolve (arg.get ());
286 if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
287 {
288 rust_error_at (arg->get_locus (),
289 "failed to resolve type for argument");
290 return new ErrorType (ref->get_ref ());
291 }
292
293 Argument a (arg->get_mappings (), argument_expr_tyty, arg->get_locus ());
294 args.push_back (std::move (a));
295 }
296
297 TypeCheckMethodCallExpr checker (call.get_mappings (), args,
298 call.get_locus (),
299 call.get_receiver ()->get_locus (),
300 adjusted_self, context);
301 return checker.check (*ref);
302}
303
304BaseType *
305TypeCheckMethodCallExpr::go (FnType *ref, Analysis::NodeMapping call_mappings,
306 std::vector<Argument> &args, Location call_locus,
307 Location receiver_locus,
308 TyTy::BaseType *adjusted_self,
309 Resolver::TypeCheckContext *context)
310{
311 TypeCheckMethodCallExpr checker (call_mappings, args, call_locus,
312 receiver_locus, adjusted_self, context);
313 return checker.check (*ref);
314}
315
316BaseType *
317TypeCheckMethodCallExpr::check (FnType &type)
06688fe4 318{
7ad24d80 319 Resolver::TypeCheckBase::unify_site (
4d021d9e
PH
320 call_mappings.get_hirid (), TyWithLocation (type.get_self_type ()),
321 TyWithLocation (adjusted_self, receiver_locus), call_locus);
06688fe4
PH
322
323 // +1 for the receiver self
4d021d9e 324 size_t num_args_to_call = arguments.size () + 1;
06688fe4
PH
325 if (num_args_to_call != type.num_params ())
326 {
4d021d9e 327 rust_error_at (call_locus,
06688fe4 328 "unexpected number of arguments %lu expected %lu",
4d021d9e 329 (unsigned long) num_args_to_call,
06688fe4 330 (unsigned long) type.num_params ());
4d021d9e 331 return new ErrorType (type.get_ref ());
06688fe4
PH
332 }
333
334 size_t i = 1;
4d021d9e 335 for (auto &argument : arguments)
06688fe4 336 {
4d021d9e 337 Location arg_locus = argument.get_locus ();
af22b54a 338
06688fe4 339 auto fnparam = type.param_at (i);
af22b54a
PH
340 HIR::Pattern *fn_param_pattern = fnparam.first;
341 BaseType *param_ty = fnparam.second;
342 Location param_locus
343 = fn_param_pattern == nullptr
344 ? mappings->lookup_location (param_ty->get_ref ())
345 : fn_param_pattern->get_locus ();
346
4d021d9e
PH
347 auto argument_expr_tyty = argument.get_argument_type ();
348 HirId coercion_side_id = argument.get_mappings ().get_hirid ();
06688fe4 349 auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site (
af22b54a 350 coercion_side_id, TyWithLocation (param_ty, param_locus),
4d021d9e 351 TyWithLocation (argument_expr_tyty, arg_locus), arg_locus);
06688fe4
PH
352 if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
353 {
4d021d9e 354 return new ErrorType (type.get_ref ());
06688fe4
PH
355 }
356
357 i++;
358 }
359
360 if (i != num_args_to_call)
361 {
4d021d9e 362 rust_error_at (call_locus,
06688fe4 363 "unexpected number of arguments %lu expected %lu",
4d021d9e
PH
364 (unsigned long) i, (unsigned long) arguments.size ());
365 return new ErrorType (type.get_ref ());
06688fe4
PH
366 }
367
368 type.monomorphize ();
369
4d021d9e 370 return type.get_return_type ()->monomorphized_clone ();
06688fe4
PH
371}
372
373} // namespace TyTy
374} // namespace Rust