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