]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/typecheck/rust-tyty-call.cc
Daily bump.
[thirdparty/gcc.git] / gcc / rust / typecheck / rust-tyty-call.cc
CommitLineData
6441eb6d 1// Copyright (C) 2020-2025 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"
385a03ae 21#include "rust-type-util.h"
06688fe4
PH
22
23namespace Rust {
24namespace TyTy {
25
8ab098a7 26void
9cc353d7 27emit_unexpected_argument_error (location_t loc,
8ab098a7
MM
28 unsigned long unexpected_arg_count,
29 unsigned long expected_arg_count)
30{
31 // https://doc.rust-lang.org/error_codes/E0061.html
32 // rustc treats 1 as singular and others as plural
33 std::string err_msg = "this function takes %lu ";
34 if (expected_arg_count == 1)
35 {
36 err_msg += "argument";
37 }
38 else
39 {
40 err_msg += "arguments";
41 }
42
43 if (unexpected_arg_count == 1)
44 {
45 err_msg += " but %lu argument was supplied";
46 }
47 else
48 {
49 err_msg += " but %lu arguments were supplied";
50 }
55f8b63a 51 rust_error_at (loc, ErrorCode::E0061, err_msg.c_str (), expected_arg_count,
8ab098a7
MM
52 unexpected_arg_count);
53}
54
06688fe4
PH
55void
56TypeCheckCallExpr::visit (ADTType &type)
57{
58 rust_assert (!variant.is_error ());
59 if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
60 {
61 rust_error_at (
55f8b63a 62 call.get_locus (), ErrorCode::E0423,
9f06b910 63 "expected function, tuple struct or tuple variant, found struct %qs",
06688fe4
PH
64 type.get_name ().c_str ());
65 return;
66 }
67
68 if (call.num_params () != variant.num_fields ())
69 {
8ab098a7
MM
70 emit_unexpected_argument_error (call.get_locus (),
71 (unsigned long) call.num_params (),
72 (unsigned long) variant.num_fields ());
06688fe4
PH
73 return;
74 }
75
76 size_t i = 0;
77 for (auto &argument : call.get_arguments ())
78 {
79 StructFieldType *field = variant.get_field_at_index (i);
80 BaseType *field_tyty = field->get_field_type ();
9cc353d7 81 location_t arg_locus = argument->get_locus ();
06688fe4 82
c29a3bc9 83 BaseType *arg = Resolver::TypeCheckExpr::Resolve (*argument);
06688fe4
PH
84 if (arg->get_kind () == TyTy::TypeKind::ERROR)
85 {
86 rust_error_at (argument->get_locus (),
87 "failed to resolve argument type");
88 return;
89 }
90
af22b54a 91 HirId coercion_side_id = argument->get_mappings ().get_hirid ();
f8770d18
PEP
92 auto res = Resolver::coercion_site (coercion_side_id,
93 TyWithLocation (field_tyty),
94 TyWithLocation (arg, arg_locus),
95 argument->get_locus ());
06688fe4
PH
96 if (res->get_kind () == TyTy::TypeKind::ERROR)
97 {
98 return;
99 }
100
06688fe4
PH
101 i++;
102 }
103
104 if (i != call.num_params ())
105 {
8ab098a7
MM
106 emit_unexpected_argument_error (call.get_locus (), (unsigned long) i,
107 (unsigned long) call.num_params ());
06688fe4
PH
108 return;
109 }
110
111 resolved = type.clone ();
112}
113
114void
115TypeCheckCallExpr::visit (FnType &type)
116{
06688fe4
PH
117 if (call.num_params () != type.num_params ())
118 {
0a99bfe1 119 if (type.is_variadic ())
06688fe4
PH
120 {
121 if (call.num_params () < type.num_params ())
122 {
8ab098a7
MM
123 emit_unexpected_argument_error (
124 call.get_locus (), (unsigned long) call.num_params (),
125 (unsigned long) type.num_params ());
06688fe4
PH
126 return;
127 }
128 }
129 else
130 {
8ab098a7
MM
131 emit_unexpected_argument_error (call.get_locus (),
132 (unsigned long) call.num_params (),
133 (unsigned long) type.num_params ());
06688fe4
PH
134 return;
135 }
136 }
137
138 size_t i = 0;
139 for (auto &argument : call.get_arguments ())
140 {
9cc353d7 141 location_t arg_locus = argument->get_locus ();
c29a3bc9 142 auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (*argument);
a362f8a7
PH
143 if (argument_expr_tyty->is<TyTy::ErrorType> ())
144 return;
06688fe4 145
a9d72ef2 146 // it might be a variadic function
06688fe4
PH
147 if (i < type.num_params ())
148 {
c29a3bc9 149 auto &fnparam = type.param_at (i);
d123f43e 150 BaseType *param_ty = fnparam.get_type ();
9cc353d7 151 location_t param_locus
d123f43e 152 = fnparam.has_pattern ()
b3246d3f
PEP
153 ? fnparam.get_pattern ().get_locus ()
154 : mappings.lookup_location (param_ty->get_ref ());
af22b54a
PH
155
156 HirId coercion_side_id = argument->get_mappings ().get_hirid ();
f8770d18
PEP
157 auto resolved_argument_type
158 = Resolver::coercion_site (coercion_side_id,
159 TyWithLocation (param_ty, param_locus),
160 TyWithLocation (argument_expr_tyty,
161 arg_locus),
162 argument->get_locus ());
06688fe4
PH
163 if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
164 {
06688fe4
PH
165 return;
166 }
167 }
a9d72ef2
OA
168 else
169 {
170 switch (argument_expr_tyty->get_kind ())
171 {
172 case TyTy::TypeKind::ERROR:
173 return;
dd65cf1d
MP
174 case TyTy::TypeKind::INT:
175 {
a9d72ef2
OA
176 auto &int_ty
177 = static_cast<TyTy::IntType &> (*argument_expr_tyty);
178 if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8)
179 || (int_ty.get_int_kind () == TyTy::IntType::IntKind::I16))
180 {
718b65a9
MM
181 rich_location richloc (line_table, arg_locus);
182 richloc.add_fixit_replace (
183 "cast the value to c_int: as c_int");
184 rust_error_at (richloc, ErrorCode::E0617,
a9d72ef2
OA
185 "expected %<c_int%> variadic argument");
186 return;
187 }
188 break;
189 }
dd65cf1d
MP
190 case TyTy::TypeKind::UINT:
191 {
a9d72ef2
OA
192 auto &uint_ty
193 = static_cast<TyTy::UintType &> (*argument_expr_tyty);
194 if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8)
195 || (uint_ty.get_uint_kind ()
196 == TyTy::UintType::UintKind::U16))
197 {
718b65a9
MM
198 rich_location richloc (line_table, arg_locus);
199 richloc.add_fixit_replace (
200 "cast the value to c_uint: as c_uint");
201 rust_error_at (richloc, ErrorCode::E0617,
a9d72ef2
OA
202 "expected %<c_uint%> variadic argument");
203 return;
204 }
205 break;
206 }
dd65cf1d
MP
207 case TyTy::TypeKind::FLOAT:
208 {
a9d72ef2
OA
209 if (static_cast<TyTy::FloatType &> (*argument_expr_tyty)
210 .get_float_kind ()
211 == TyTy::FloatType::FloatKind::F32)
212 {
718b65a9
MM
213 rich_location richloc (line_table, arg_locus);
214 richloc.add_fixit_replace (
215 "cast the value to c_double: as c_double");
216 rust_error_at (richloc, ErrorCode::E0617,
a9d72ef2
OA
217 "expected %<c_double%> variadic argument");
218 return;
219 }
220 break;
221 }
dd65cf1d
MP
222 case TyTy::TypeKind::BOOL:
223 {
718b65a9
MM
224 rich_location richloc (line_table, arg_locus);
225 richloc.add_fixit_replace ("cast the value to c_int: as c_int");
226 rust_error_at (arg_locus, ErrorCode::E0617,
227 "expected %<c_int%> variadic argument");
228 return;
229 }
dd65cf1d
MP
230 case TyTy::TypeKind::FNDEF:
231 {
718b65a9
MM
232 rust_error_at (
233 arg_locus, ErrorCode::E0617,
234 "unexpected function definition type as variadic "
235 "argument - cast to function pointer");
236 }
a9d72ef2
OA
237 return;
238 default:
239 break;
240 }
241 }
06688fe4
PH
242
243 i++;
244 }
245
246 if (i < call.num_params ())
247 {
8ab098a7
MM
248 emit_unexpected_argument_error (call.get_locus (), (unsigned long) i,
249 (unsigned long) call.num_params ());
06688fe4
PH
250 return;
251 }
252
253 type.monomorphize ();
7aa25295 254 resolved = type.get_return_type ()->monomorphized_clone ();
06688fe4
PH
255}
256
257void
258TypeCheckCallExpr::visit (FnPtr &type)
259{
260 if (call.num_params () != type.num_params ())
261 {
8ab098a7
MM
262 emit_unexpected_argument_error (call.get_locus (),
263 (unsigned long) call.num_params (),
264 (unsigned long) type.num_params ());
06688fe4
PH
265 return;
266 }
267
268 size_t i = 0;
269 for (auto &argument : call.get_arguments ())
270 {
9cc353d7 271 location_t arg_locus = argument->get_locus ();
14025f73 272 BaseType *fnparam = type.get_param_type_at (i);
c29a3bc9 273 auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (*argument);
06688fe4
PH
274 if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
275 {
276 rust_error_at (
277 argument->get_locus (),
278 "failed to resolve type for argument expr in CallExpr");
279 return;
280 }
281
f8770d18 282 auto resolved_argument_type = Resolver::coercion_site (
af22b54a
PH
283 argument->get_mappings ().get_hirid (), TyWithLocation (fnparam),
284 TyWithLocation (argument_expr_tyty, arg_locus), argument->get_locus ());
06688fe4
PH
285 if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
286 {
06688fe4
PH
287 return;
288 }
289
290 i++;
291 }
292
293 if (i != call.num_params ())
294 {
8ab098a7
MM
295 emit_unexpected_argument_error (call.get_locus (), (unsigned long) i,
296 (unsigned long) call.num_params ());
06688fe4
PH
297 return;
298 }
299
300 resolved = type.get_return_type ()->monomorphized_clone ();
301}
302
303// method call checker
304
4d021d9e
PH
305TypeCheckMethodCallExpr::TypeCheckMethodCallExpr (
306 Analysis::NodeMapping call_mappings, std::vector<Argument> &args,
9cc353d7
OA
307 location_t call_locus, location_t receiver_locus,
308 TyTy::BaseType *adjusted_self, Resolver::TypeCheckContext *context)
4d021d9e
PH
309 : call_mappings (call_mappings), arguments (args), call_locus (call_locus),
310 receiver_locus (receiver_locus), adjusted_self (adjusted_self),
311 context (context), mappings (Analysis::Mappings::get ())
312{}
313
314BaseType *
315TypeCheckMethodCallExpr::go (FnType *ref, HIR::MethodCallExpr &call,
316 TyTy::BaseType *adjusted_self,
317 Resolver::TypeCheckContext *context)
318{
319 std::vector<Argument> args;
320 for (auto &arg : call.get_arguments ())
321 {
c29a3bc9 322 BaseType *argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (*arg);
4d021d9e
PH
323 if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
324 {
325 rust_error_at (arg->get_locus (),
326 "failed to resolve type for argument");
327 return new ErrorType (ref->get_ref ());
328 }
329
330 Argument a (arg->get_mappings (), argument_expr_tyty, arg->get_locus ());
331 args.push_back (std::move (a));
332 }
333
334 TypeCheckMethodCallExpr checker (call.get_mappings (), args,
335 call.get_locus (),
c29a3bc9 336 call.get_receiver ().get_locus (),
4d021d9e
PH
337 adjusted_self, context);
338 return checker.check (*ref);
339}
340
341BaseType *
342TypeCheckMethodCallExpr::go (FnType *ref, Analysis::NodeMapping call_mappings,
9cc353d7
OA
343 std::vector<Argument> &args, location_t call_locus,
344 location_t receiver_locus,
4d021d9e
PH
345 TyTy::BaseType *adjusted_self,
346 Resolver::TypeCheckContext *context)
347{
348 TypeCheckMethodCallExpr checker (call_mappings, args, call_locus,
349 receiver_locus, adjusted_self, context);
350 return checker.check (*ref);
351}
352
353BaseType *
354TypeCheckMethodCallExpr::check (FnType &type)
06688fe4 355{
f97c3809
PEP
356 Resolver::unify_site (call_mappings.get_hirid (),
357 TyWithLocation (type.get_self_type ()),
358 TyWithLocation (adjusted_self, receiver_locus),
359 call_locus);
06688fe4
PH
360
361 // +1 for the receiver self
4d021d9e 362 size_t num_args_to_call = arguments.size () + 1;
06688fe4
PH
363 if (num_args_to_call != type.num_params ())
364 {
8ab098a7
MM
365 emit_unexpected_argument_error (call_locus,
366 (unsigned long) num_args_to_call,
367 (unsigned long) type.num_params ());
4d021d9e 368 return new ErrorType (type.get_ref ());
06688fe4
PH
369 }
370
371 size_t i = 1;
4d021d9e 372 for (auto &argument : arguments)
06688fe4 373 {
9cc353d7 374 location_t arg_locus = argument.get_locus ();
af22b54a 375
c29a3bc9 376 auto &fnparam = type.param_at (i);
d123f43e 377 BaseType *param_ty = fnparam.get_type ();
9cc353d7 378 location_t param_locus
d123f43e 379 = fnparam.has_pattern ()
b3246d3f
PEP
380 ? fnparam.get_pattern ().get_locus ()
381 : mappings.lookup_location (param_ty->get_ref ());
af22b54a 382
4d021d9e
PH
383 auto argument_expr_tyty = argument.get_argument_type ();
384 HirId coercion_side_id = argument.get_mappings ().get_hirid ();
f8770d18 385 auto resolved_argument_type = Resolver::coercion_site (
af22b54a 386 coercion_side_id, TyWithLocation (param_ty, param_locus),
4d021d9e 387 TyWithLocation (argument_expr_tyty, arg_locus), arg_locus);
06688fe4
PH
388 if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
389 {
4d021d9e 390 return new ErrorType (type.get_ref ());
06688fe4
PH
391 }
392
393 i++;
394 }
395
396 if (i != num_args_to_call)
397 {
8ab098a7
MM
398 emit_unexpected_argument_error (call_locus, (unsigned long) i,
399 (unsigned long) arguments.size ());
4d021d9e 400 return new ErrorType (type.get_ref ());
06688fe4
PH
401 }
402
403 type.monomorphize ();
404
4d021d9e 405 return type.get_return_type ()->monomorphized_clone ();
06688fe4
PH
406}
407
408} // namespace TyTy
409} // namespace Rust