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-struct-field.h"
21 : : #include "rust-hir-path-probe.h"
22 : : #include "rust-substitution-mapper.h"
23 : : #include "rust-hir-trait-resolve.h"
24 : : #include "rust-hir-dot-operator.h"
25 : : #include "rust-hir-type-check-pattern.h"
26 : : #include "rust-hir-type-check-expr.h"
27 : : #include "rust-hir-type-check-stmt.h"
28 : : #include "rust-hir-type-check-item.h"
29 : : #include "rust-type-util.h"
30 : :
31 : : namespace Rust {
32 : : namespace Resolver {
33 : :
34 : 78446 : TypeCheckExpr::TypeCheckExpr () : TypeCheckBase (), infered (nullptr) {}
35 : :
36 : : // Perform type checking on expr. Also runs type unification algorithm.
37 : : // Returns the unified type of expr
38 : : TyTy::BaseType *
39 : 78446 : TypeCheckExpr::Resolve (HIR::Expr *expr)
40 : : {
41 : 78446 : TypeCheckExpr resolver;
42 : 78446 : expr->accept_vis (resolver);
43 : :
44 : 78444 : if (resolver.infered == nullptr)
45 : 30 : return new TyTy::ErrorType (expr->get_mappings ().get_hirid ());
46 : :
47 : 78414 : auto ref = expr->get_mappings ().get_hirid ();
48 : 78414 : resolver.infered->set_ref (ref);
49 : 78414 : resolver.context->insert_type (expr->get_mappings (), resolver.infered);
50 : :
51 : 78414 : return resolver.infered;
52 : 78444 : }
53 : :
54 : : void
55 : 726 : TypeCheckExpr::visit (HIR::TupleIndexExpr &expr)
56 : : {
57 : 726 : auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get ());
58 : 726 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
59 : : {
60 : 0 : rust_error_at (expr.get_tuple_expr ()->get_locus (),
61 : : "failed to resolve TupleIndexExpr receiver");
62 : 0 : return;
63 : : }
64 : :
65 : : // FIXME does this require autoderef here?
66 : 726 : if (resolved->get_kind () == TyTy::TypeKind::REF)
67 : : {
68 : 192 : TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (resolved);
69 : 192 : resolved = r->get_base ();
70 : : }
71 : :
72 : 726 : bool is_valid_type = resolved->get_kind () == TyTy::TypeKind::ADT
73 : 726 : || resolved->get_kind () == TyTy::TypeKind::TUPLE;
74 : 726 : if (!is_valid_type)
75 : : {
76 : 2 : rust_error_at (expr.get_tuple_expr ()->get_locus (),
77 : : "Expected Tuple or ADT got: %s",
78 : 2 : resolved->as_string ().c_str ());
79 : 2 : return;
80 : : }
81 : :
82 : 724 : if (resolved->get_kind () == TyTy::TypeKind::TUPLE)
83 : : {
84 : 134 : TyTy::TupleType *tuple = static_cast<TyTy::TupleType *> (resolved);
85 : 134 : TupleIndex index = expr.get_tuple_index ();
86 : 134 : if ((size_t) index >= tuple->num_fields ())
87 : : {
88 : 0 : rust_error_at (expr.get_locus (), "unknown field at index %i", index);
89 : 0 : return;
90 : : }
91 : :
92 : 134 : auto field_tyty = tuple->get_field ((size_t) index);
93 : 134 : if (field_tyty == nullptr)
94 : : {
95 : 0 : rust_error_at (expr.get_locus (),
96 : : "failed to lookup field type at index %i", index);
97 : 0 : return;
98 : : }
99 : :
100 : 134 : infered = field_tyty;
101 : 134 : return;
102 : : }
103 : :
104 : 590 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (resolved);
105 : 590 : rust_assert (!adt->is_enum ());
106 : 590 : rust_assert (adt->number_of_variants () == 1);
107 : :
108 : 590 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
109 : 590 : TupleIndex index = expr.get_tuple_index ();
110 : 590 : if ((size_t) index >= variant->num_fields ())
111 : : {
112 : 0 : rust_error_at (expr.get_locus (), "unknown field at index %i", index);
113 : 0 : return;
114 : : }
115 : :
116 : 590 : auto field_tyty = variant->get_field_at_index ((size_t) index);
117 : 590 : if (field_tyty == nullptr)
118 : : {
119 : 0 : rust_error_at (expr.get_locus (),
120 : : "failed to lookup field type at index %i", index);
121 : 0 : return;
122 : : }
123 : :
124 : 590 : infered = field_tyty->get_field_type ();
125 : : }
126 : :
127 : : void
128 : 322 : TypeCheckExpr::visit (HIR::TupleExpr &expr)
129 : : {
130 : 322 : if (expr.is_unit ())
131 : : {
132 : 67 : auto unit_node_id = resolver->get_unit_type_node_id ();
133 : 67 : if (!context->lookup_builtin (unit_node_id, &infered))
134 : : {
135 : 0 : rust_error_at (expr.get_locus (),
136 : : "failed to lookup builtin unit type");
137 : : }
138 : 67 : return;
139 : : }
140 : :
141 : 255 : std::vector<TyTy::TyVar> fields;
142 : 877 : for (auto &elem : expr.get_tuple_elems ())
143 : : {
144 : 622 : auto field_ty = TypeCheckExpr::Resolve (elem.get ());
145 : 622 : fields.push_back (TyTy::TyVar (field_ty->get_ref ()));
146 : : }
147 : 510 : infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (),
148 : 510 : expr.get_locus (), fields);
149 : 255 : }
150 : :
151 : : void
152 : 326 : TypeCheckExpr::visit (HIR::ReturnExpr &expr)
153 : : {
154 : 326 : if (!context->have_function_context ())
155 : : {
156 : 1 : rust_error_at (expr.get_locus (), ErrorCode::E0572,
157 : : "return statement outside of function body");
158 : 1 : infered = new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
159 : 1 : return;
160 : : }
161 : :
162 : 325 : auto fn_return_tyty = context->peek_return_type ();
163 : 325 : location_t expr_locus = expr.has_return_expr ()
164 : 325 : ? expr.get_expr ()->get_locus ()
165 : 10 : : expr.get_locus ();
166 : 325 : TyTy::BaseType *expr_ty
167 : 325 : = expr.has_return_expr ()
168 : 325 : ? TypeCheckExpr::Resolve (expr.get_expr ().get ())
169 : 10 : : TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
170 : :
171 : 650 : coercion_site (expr.get_mappings ().get_hirid (),
172 : 325 : TyTy::TyWithLocation (fn_return_tyty),
173 : 325 : TyTy::TyWithLocation (expr_ty, expr_locus), expr.get_locus ());
174 : :
175 : 325 : infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
176 : : }
177 : :
178 : : void
179 : 6769 : TypeCheckExpr::visit (HIR::CallExpr &expr)
180 : : {
181 : 6769 : TyTy::BaseType *function_tyty
182 : 6769 : = TypeCheckExpr::Resolve (expr.get_fnexpr ().get ());
183 : :
184 : 6769 : rust_debug_loc (expr.get_locus (), "resolved_call_expr to: {%s}",
185 : 6769 : function_tyty->get_name ().c_str ());
186 : :
187 : 6769 : TyTy::VariantDef &variant = TyTy::VariantDef::get_error_node ();
188 : 6769 : if (function_tyty->get_kind () == TyTy::TypeKind::ADT)
189 : : {
190 : 929 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (function_tyty);
191 : 929 : if (adt->is_enum ())
192 : : {
193 : : // lookup variant id
194 : 194 : HirId variant_id;
195 : 194 : bool ok = context->lookup_variant_definition (
196 : 194 : expr.get_fnexpr ()->get_mappings ().get_hirid (), &variant_id);
197 : 194 : rust_assert (ok);
198 : :
199 : 194 : TyTy::VariantDef *lookup_variant = nullptr;
200 : 194 : ok = adt->lookup_variant_by_id (variant_id, &lookup_variant);
201 : 194 : rust_assert (ok);
202 : :
203 : 194 : variant = *lookup_variant;
204 : : }
205 : : else
206 : : {
207 : 735 : rust_assert (adt->number_of_variants () == 1);
208 : 735 : variant = *adt->get_variants ().at (0);
209 : : }
210 : :
211 : 929 : infered
212 : 929 : = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
213 : 929 : return;
214 : : }
215 : :
216 : 5840 : bool resolved_fn_trait_call
217 : 5840 : = resolve_fn_trait_call (expr, function_tyty, &infered);
218 : 5840 : if (resolved_fn_trait_call)
219 : : return;
220 : :
221 : 5786 : bool valid_tyty = function_tyty->get_kind () == TyTy::TypeKind::FNDEF
222 : 5786 : || function_tyty->get_kind () == TyTy::TypeKind::FNPTR;
223 : 5786 : if (!valid_tyty)
224 : : {
225 : 4 : rust_error_at (expr.get_locus (),
226 : : "Failed to resolve expression of function call");
227 : 4 : return;
228 : : }
229 : :
230 : 5782 : infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
231 : : }
232 : :
233 : : void
234 : 1616 : TypeCheckExpr::visit (HIR::AssignmentExpr &expr)
235 : : {
236 : 1616 : infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
237 : :
238 : 1616 : auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ().get ());
239 : 1616 : auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ().get ());
240 : :
241 : 3232 : coercion_site (expr.get_mappings ().get_hirid (),
242 : 1616 : TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
243 : 1616 : TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
244 : : expr.get_locus ());
245 : 1616 : }
246 : :
247 : : void
248 : 160 : TypeCheckExpr::visit (HIR::CompoundAssignmentExpr &expr)
249 : : {
250 : 160 : infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
251 : :
252 : 160 : auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ().get ());
253 : 160 : auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ().get ());
254 : :
255 : : // we dont care about the result of the unify from a compound assignment
256 : : // since this is a unit-type expr
257 : 320 : coercion_site (expr.get_mappings ().get_hirid (),
258 : 160 : TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
259 : 160 : TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
260 : : expr.get_locus ());
261 : :
262 : 160 : auto lang_item_type
263 : 160 : = LangItem::CompoundAssignmentOperatorToLangItem (expr.get_expr_type ());
264 : 160 : bool operator_overloaded
265 : 160 : = resolve_operator_overload (lang_item_type, expr, lhs, rhs);
266 : 160 : if (operator_overloaded)
267 : : return;
268 : :
269 : 146 : bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ());
270 : 146 : bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ());
271 : 146 : bool valid = valid_lhs && valid_rhs;
272 : 146 : if (!valid)
273 : : {
274 : 0 : rust_error_at (expr.get_locus (),
275 : : "cannot apply this operator to types %s and %s",
276 : 0 : lhs->as_string ().c_str (), rhs->as_string ().c_str ());
277 : 0 : return;
278 : : }
279 : : }
280 : :
281 : : void
282 : 12998 : TypeCheckExpr::visit (HIR::LiteralExpr &expr)
283 : : {
284 : 12998 : infered = resolve_literal (expr.get_mappings (), expr.get_literal (),
285 : : expr.get_locus ());
286 : 12998 : }
287 : :
288 : : void
289 : 2433 : TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
290 : : {
291 : 2433 : auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ().get ());
292 : 2433 : auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ().get ());
293 : :
294 : 2433 : auto lang_item_type = LangItem::OperatorToLangItem (expr.get_expr_type ());
295 : 2433 : bool operator_overloaded
296 : 2433 : = resolve_operator_overload (lang_item_type, expr, lhs, rhs);
297 : 2433 : if (operator_overloaded)
298 : : return;
299 : :
300 : 2356 : bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ());
301 : 2356 : bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ());
302 : 2356 : bool valid = valid_lhs && valid_rhs;
303 : 2356 : if (!valid)
304 : : {
305 : 1 : rust_error_at (expr.get_locus (),
306 : : "cannot apply this operator to types %s and %s",
307 : 2 : lhs->as_string ().c_str (), rhs->as_string ().c_str ());
308 : 1 : return;
309 : : }
310 : :
311 : 2355 : switch (expr.get_expr_type ())
312 : : {
313 : 30 : case ArithmeticOrLogicalOperator::LEFT_SHIFT:
314 : 30 : case ArithmeticOrLogicalOperator::RIGHT_SHIFT: {
315 : 30 : TyTy::TyWithLocation from (rhs, expr.get_rhs ()->get_locus ());
316 : 30 : TyTy::TyWithLocation to (lhs, expr.get_lhs ()->get_locus ());
317 : 30 : infered = cast_site (expr.get_mappings ().get_hirid (), from, to,
318 : : expr.get_locus ());
319 : : }
320 : 30 : break;
321 : :
322 : 2325 : default: {
323 : 4650 : infered = unify_site (
324 : 2325 : expr.get_mappings ().get_hirid (),
325 : 2325 : TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
326 : 2325 : TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
327 : : expr.get_locus ());
328 : : }
329 : 2325 : break;
330 : : }
331 : : }
332 : :
333 : : void
334 : 900 : TypeCheckExpr::visit (HIR::ComparisonExpr &expr)
335 : : {
336 : 900 : auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ().get ());
337 : 900 : auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ().get ());
338 : :
339 : 1800 : unify_site (expr.get_mappings ().get_hirid (),
340 : 900 : TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
341 : 900 : TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
342 : : expr.get_locus ());
343 : :
344 : 900 : bool ok = context->lookup_builtin ("bool", &infered);
345 : 900 : rust_assert (ok);
346 : 900 : }
347 : :
348 : : void
349 : 378 : TypeCheckExpr::visit (HIR::LazyBooleanExpr &expr)
350 : : {
351 : 378 : auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ().get ());
352 : 378 : auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ().get ());
353 : :
354 : : // we expect the lhs and rhs must be bools at this point
355 : 378 : TyTy::BaseType *boolean_node = nullptr;
356 : 378 : bool ok = context->lookup_builtin ("bool", &boolean_node);
357 : 378 : rust_assert (ok);
358 : :
359 : : // verify the lhs and rhs before unifying together
360 : 756 : lhs = unify_site (expr.get_mappings ().get_hirid (),
361 : : TyTy::TyWithLocation (boolean_node,
362 : 378 : expr.get_lhs ()->get_locus ()),
363 : 378 : TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
364 : : expr.get_locus ());
365 : :
366 : 756 : rhs = unify_site (expr.get_mappings ().get_hirid (),
367 : : TyTy::TyWithLocation (boolean_node,
368 : 378 : expr.get_rhs ()->get_locus ()),
369 : 378 : TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
370 : : expr.get_locus ());
371 : :
372 : 378 : infered
373 : 756 : = unify_site (expr.get_mappings ().get_hirid (),
374 : 378 : TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
375 : 378 : TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
376 : : expr.get_locus ());
377 : 378 : }
378 : :
379 : : void
380 : 290 : TypeCheckExpr::visit (HIR::NegationExpr &expr)
381 : : {
382 : 290 : auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ().get ());
383 : :
384 : : // check for operator overload
385 : 290 : auto lang_item_type
386 : 290 : = LangItem::NegationOperatorToLangItem (expr.get_expr_type ());
387 : 290 : bool operator_overloaded
388 : 290 : = resolve_operator_overload (lang_item_type, expr, negated_expr_ty,
389 : : nullptr);
390 : 290 : if (operator_overloaded)
391 : : return;
392 : :
393 : : // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators
394 : 276 : switch (expr.get_expr_type ())
395 : : {
396 : 180 : case NegationOperator::NEGATE: {
397 : 180 : bool valid
398 : 180 : = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
399 : 152 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT)
400 : 152 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT)
401 : 152 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::ISIZE)
402 : 150 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::USIZE)
403 : 150 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
404 : 149 : && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
405 : : == TyTy::InferType::INTEGRAL))
406 : 181 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
407 : 0 : && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
408 : 275 : == TyTy::InferType::FLOAT));
409 : 1 : if (!valid)
410 : : {
411 : 1 : rust_error_at (expr.get_locus (), "cannot apply unary - to %s",
412 : 1 : negated_expr_ty->as_string ().c_str ());
413 : 1 : return;
414 : : }
415 : : }
416 : : break;
417 : :
418 : 96 : case NegationOperator::NOT: {
419 : 96 : bool valid
420 : 96 : = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL)
421 : 17 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
422 : 10 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT)
423 : 106 : || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
424 : 9 : && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
425 : 275 : == TyTy::InferType::INTEGRAL));
426 : 1 : if (!valid)
427 : : {
428 : 1 : rust_error_at (expr.get_locus (), "cannot apply unary %<!%> to %s",
429 : 1 : negated_expr_ty->as_string ().c_str ());
430 : 1 : return;
431 : : }
432 : : }
433 : : break;
434 : : }
435 : :
436 : 274 : infered = negated_expr_ty->clone ();
437 : 274 : infered->append_reference (negated_expr_ty->get_ref ());
438 : : }
439 : :
440 : : void
441 : 300 : TypeCheckExpr::visit (HIR::IfExpr &expr)
442 : : {
443 : 300 : TyTy::BaseType *bool_ty = nullptr;
444 : 300 : bool ok = context->lookup_builtin ("bool", &bool_ty);
445 : 300 : rust_assert (ok);
446 : :
447 : 300 : TyTy::BaseType *cond_type
448 : 300 : = TypeCheckExpr::Resolve (expr.get_if_condition ().get ());
449 : :
450 : 600 : unify_site (expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (bool_ty),
451 : : TyTy::TyWithLocation (cond_type,
452 : 300 : expr.get_if_condition ()->get_locus ()),
453 : : expr.get_locus ());
454 : :
455 : 300 : TypeCheckExpr::Resolve (expr.get_if_block ().get ());
456 : :
457 : 300 : infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
458 : 300 : }
459 : :
460 : : void
461 : 347 : TypeCheckExpr::visit (HIR::IfExprConseqElse &expr)
462 : : {
463 : 347 : TyTy::BaseType *bool_ty = nullptr;
464 : 347 : bool ok = context->lookup_builtin ("bool", &bool_ty);
465 : 347 : rust_assert (ok);
466 : :
467 : 347 : TyTy::BaseType *cond_type
468 : 347 : = TypeCheckExpr::Resolve (expr.get_if_condition ().get ());
469 : :
470 : 694 : unify_site (expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (bool_ty),
471 : : TyTy::TyWithLocation (cond_type,
472 : 347 : expr.get_if_condition ()->get_locus ()),
473 : : expr.get_locus ());
474 : :
475 : 347 : auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ().get ());
476 : 347 : auto else_blk_resolved
477 : 347 : = TypeCheckExpr::Resolve (expr.get_else_block ().get ());
478 : :
479 : 347 : if (if_blk_resolved->get_kind () == TyTy::NEVER)
480 : 31 : infered = else_blk_resolved;
481 : 316 : else if (else_blk_resolved->get_kind () == TyTy::NEVER)
482 : 7 : infered = if_blk_resolved;
483 : : else
484 : : {
485 : 618 : infered = unify_site (
486 : 309 : expr.get_mappings ().get_hirid (),
487 : : TyTy::TyWithLocation (if_blk_resolved,
488 : 309 : expr.get_if_block ()->get_locus ()),
489 : : TyTy::TyWithLocation (else_blk_resolved,
490 : 309 : expr.get_else_block ()->get_locus ()),
491 : : expr.get_locus ());
492 : : }
493 : 347 : }
494 : :
495 : : void
496 : 0 : TypeCheckExpr::visit (HIR::IfLetExpr &expr)
497 : : {
498 : : // this needs to perform a least upper bound coercion on the blocks and then
499 : : // unify the scruintee and arms
500 : 0 : TyTy::BaseType *scrutinee_tyty
501 : 0 : = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ());
502 : :
503 : 0 : for (auto &pattern : expr.get_patterns ())
504 : : {
505 : 0 : TyTy::BaseType *kase_arm_ty
506 : 0 : = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
507 : :
508 : 0 : unify_site (expr.get_mappings ().get_hirid (),
509 : 0 : TyTy::TyWithLocation (scrutinee_tyty),
510 : 0 : TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
511 : : expr.get_locus ());
512 : : }
513 : :
514 : 0 : TypeCheckExpr::Resolve (expr.get_if_block ().get ());
515 : :
516 : 0 : infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
517 : 0 : }
518 : :
519 : : void
520 : 2 : TypeCheckExpr::visit (HIR::IfLetExprConseqElse &expr)
521 : : {
522 : 2 : TyTy::BaseType *scrutinee_tyty
523 : 2 : = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ());
524 : :
525 : 4 : for (auto &pattern : expr.get_patterns ())
526 : : {
527 : 2 : TyTy::BaseType *kase_arm_ty
528 : 2 : = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
529 : :
530 : 4 : unify_site (expr.get_mappings ().get_hirid (),
531 : 2 : TyTy::TyWithLocation (scrutinee_tyty),
532 : 2 : TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
533 : : expr.get_locus ());
534 : : }
535 : :
536 : 2 : auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ().get ());
537 : 2 : auto else_blk_resolved
538 : 2 : = TypeCheckExpr::Resolve (expr.get_else_block ().get ());
539 : :
540 : 2 : if (if_blk_resolved->get_kind () == TyTy::NEVER)
541 : 0 : infered = else_blk_resolved;
542 : 2 : else if (else_blk_resolved->get_kind () == TyTy::NEVER)
543 : 0 : infered = if_blk_resolved;
544 : : else
545 : : {
546 : 4 : infered = unify_site (
547 : 2 : expr.get_mappings ().get_hirid (),
548 : : TyTy::TyWithLocation (if_blk_resolved,
549 : 2 : expr.get_if_block ()->get_locus ()),
550 : : TyTy::TyWithLocation (else_blk_resolved,
551 : 2 : expr.get_else_block ()->get_locus ()),
552 : : expr.get_locus ());
553 : : }
554 : 2 : }
555 : :
556 : : void
557 : 2479 : TypeCheckExpr::visit (HIR::UnsafeBlockExpr &expr)
558 : : {
559 : 2479 : infered = TypeCheckExpr::Resolve (expr.get_block_expr ().get ());
560 : 2479 : }
561 : :
562 : : void
563 : 12798 : TypeCheckExpr::visit (HIR::BlockExpr &expr)
564 : : {
565 : 12798 : if (expr.has_label ())
566 : 0 : context->push_new_loop_context (expr.get_mappings ().get_hirid (),
567 : : expr.get_locus ());
568 : :
569 : 28934 : for (auto &s : expr.get_statements ())
570 : : {
571 : 16136 : if (!s->is_item ())
572 : 15854 : continue;
573 : :
574 : 282 : TypeCheckStmt::Resolve (s.get ());
575 : : }
576 : :
577 : 28933 : for (auto &s : expr.get_statements ())
578 : : {
579 : 16136 : if (s->is_item ())
580 : 282 : continue;
581 : :
582 : 15854 : auto resolved = TypeCheckStmt::Resolve (s.get ());
583 : 15853 : if (resolved == nullptr)
584 : : {
585 : 0 : rust_error_at (s->get_locus (), "failure to resolve type");
586 : 0 : return;
587 : : }
588 : :
589 : 15853 : if (s->is_unit_check_needed () && !resolved->is_unit ())
590 : : {
591 : 3 : auto unit
592 : 3 : = TyTy::TupleType::get_unit_type (s->get_mappings ().get_hirid ());
593 : 3 : resolved
594 : 3 : = unify_site (s->get_mappings ().get_hirid (),
595 : 3 : TyTy::TyWithLocation (unit),
596 : 3 : TyTy::TyWithLocation (resolved), s->get_locus ());
597 : : }
598 : : }
599 : :
600 : 12797 : if (expr.has_expr ())
601 : 8431 : infered = TypeCheckExpr::Resolve (expr.get_final_expr ().get ())->clone ();
602 : 4366 : else if (expr.is_tail_reachable ())
603 : 4059 : infered
604 : 4059 : = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
605 : 307 : else if (expr.has_label ())
606 : : {
607 : 0 : TyTy::BaseType *loop_context_type = context->pop_loop_context ();
608 : :
609 : 0 : bool loop_context_type_infered
610 : 0 : = (loop_context_type->get_kind () != TyTy::TypeKind::INFER)
611 : 0 : || ((loop_context_type->get_kind () == TyTy::TypeKind::INFER)
612 : 0 : && (((TyTy::InferType *) loop_context_type)->get_infer_kind ()
613 : 0 : != TyTy::InferType::GENERAL));
614 : :
615 : 0 : infered = loop_context_type_infered ? loop_context_type
616 : 0 : : TyTy::TupleType::get_unit_type (
617 : 0 : expr.get_mappings ().get_hirid ());
618 : : }
619 : : else
620 : : {
621 : : // FIXME this seems wrong
622 : 307 : infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
623 : : }
624 : : }
625 : :
626 : : void
627 : 50 : TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
628 : : {
629 : 50 : auto lang_item_type = LangItem::Kind::RANGE;
630 : :
631 : 50 : DefId respective_lang_item_id = UNKNOWN_DEFID;
632 : 50 : bool lang_item_defined
633 : 50 : = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
634 : :
635 : : // we need to have it maybe
636 : 50 : if (!lang_item_defined)
637 : : {
638 : 0 : rust_internal_error_at (expr.get_locus (),
639 : : "unable to find relevant lang item: %s",
640 : 0 : LangItem::ToString (lang_item_type).c_str ());
641 : : return;
642 : : }
643 : :
644 : : // look it up and it _must_ be a struct definition
645 : 50 : HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
646 : 50 : rust_assert (item != nullptr);
647 : :
648 : 50 : TyTy::BaseType *item_type = nullptr;
649 : 50 : bool ok
650 : 50 : = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
651 : 50 : rust_assert (ok);
652 : 50 : rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
653 : 50 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
654 : :
655 : : // this is a single generic item lets assert that
656 : 50 : rust_assert (adt->get_num_substitutions () == 1);
657 : :
658 : : // resolve the range expressions and these types must unify then we use that
659 : : // type to substitute into the ADT
660 : 50 : TyTy::BaseType *from_ty
661 : 50 : = TypeCheckExpr::Resolve (expr.get_from_expr ().get ());
662 : 50 : TyTy::BaseType *to_ty = TypeCheckExpr::Resolve (expr.get_to_expr ().get ());
663 : :
664 : 100 : TyTy::BaseType *unified = unify_site (
665 : 50 : expr.get_mappings ().get_hirid (),
666 : 50 : TyTy::TyWithLocation (from_ty, expr.get_from_expr ()->get_locus ()),
667 : 50 : TyTy::TyWithLocation (to_ty, expr.get_to_expr ()->get_locus ()),
668 : : expr.get_locus ());
669 : :
670 : : // substitute it in
671 : 50 : std::vector<TyTy::SubstitutionArg> subst_mappings;
672 : 50 : const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
673 : 50 : subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
674 : :
675 : 50 : TyTy::SubstitutionArgumentMappings subst (
676 : 50 : subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
677 : 50 : expr.get_locus ());
678 : 50 : infered = SubstMapperInternal::Resolve (adt, subst);
679 : 50 : }
680 : :
681 : : void
682 : 7 : TypeCheckExpr::visit (HIR::RangeFromExpr &expr)
683 : : {
684 : 7 : auto lang_item_type = LangItem::Kind::RANGE_FROM;
685 : :
686 : 7 : DefId respective_lang_item_id = UNKNOWN_DEFID;
687 : 7 : bool lang_item_defined
688 : 7 : = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
689 : :
690 : : // we need to have it maybe
691 : 7 : if (!lang_item_defined)
692 : : {
693 : 0 : rust_internal_error_at (expr.get_locus (),
694 : : "unable to find relevant lang item: %s",
695 : 0 : LangItem::ToString (lang_item_type).c_str ());
696 : : return;
697 : : }
698 : :
699 : : // look it up and it _must_ be a struct definition
700 : 7 : HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
701 : 7 : rust_assert (item != nullptr);
702 : :
703 : 7 : TyTy::BaseType *item_type = nullptr;
704 : 7 : bool ok
705 : 7 : = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
706 : 7 : rust_assert (ok);
707 : 7 : rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
708 : 7 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
709 : :
710 : : // this is a single generic item lets assert that
711 : 7 : rust_assert (adt->get_num_substitutions () == 1);
712 : :
713 : : // resolve the range expressions and these types must unify then we use that
714 : : // type to substitute into the ADT
715 : 7 : TyTy::BaseType *from_ty
716 : 7 : = TypeCheckExpr::Resolve (expr.get_from_expr ().get ());
717 : :
718 : : // substitute it in
719 : 7 : std::vector<TyTy::SubstitutionArg> subst_mappings;
720 : 7 : const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
721 : 7 : subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
722 : :
723 : 7 : TyTy::SubstitutionArgumentMappings subst (
724 : 7 : subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
725 : 7 : expr.get_locus ());
726 : 7 : infered = SubstMapperInternal::Resolve (adt, subst);
727 : 7 : }
728 : :
729 : : void
730 : 7 : TypeCheckExpr::visit (HIR::RangeToExpr &expr)
731 : : {
732 : 7 : auto lang_item_type = LangItem::Kind::RANGE_TO;
733 : :
734 : 7 : DefId respective_lang_item_id = UNKNOWN_DEFID;
735 : 7 : bool lang_item_defined
736 : 7 : = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
737 : :
738 : : // we need to have it maybe
739 : 7 : if (!lang_item_defined)
740 : : {
741 : 0 : rust_internal_error_at (expr.get_locus (),
742 : : "unable to find relevant lang item: %s",
743 : 0 : LangItem::ToString (lang_item_type).c_str ());
744 : : return;
745 : : }
746 : :
747 : : // look it up and it _must_ be a struct definition
748 : 7 : HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
749 : 7 : rust_assert (item != nullptr);
750 : :
751 : 7 : TyTy::BaseType *item_type = nullptr;
752 : 7 : bool ok
753 : 7 : = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
754 : 7 : rust_assert (ok);
755 : 7 : rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
756 : 7 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
757 : :
758 : : // this is a single generic item lets assert that
759 : 7 : rust_assert (adt->get_num_substitutions () == 1);
760 : :
761 : : // resolve the range expressions and these types must unify then we use that
762 : : // type to substitute into the ADT
763 : 7 : TyTy::BaseType *from_ty = TypeCheckExpr::Resolve (expr.get_to_expr ().get ());
764 : :
765 : : // substitute it in
766 : 7 : std::vector<TyTy::SubstitutionArg> subst_mappings;
767 : 7 : const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
768 : 7 : subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
769 : :
770 : 7 : TyTy::SubstitutionArgumentMappings subst (
771 : 7 : subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
772 : 7 : expr.get_locus ());
773 : 7 : infered = SubstMapperInternal::Resolve (adt, subst);
774 : 7 : }
775 : :
776 : : void
777 : 0 : TypeCheckExpr::visit (HIR::RangeFullExpr &expr)
778 : : {
779 : 0 : auto lang_item_type = LangItem::Kind::RANGE_FULL;
780 : :
781 : 0 : DefId respective_lang_item_id = UNKNOWN_DEFID;
782 : 0 : bool lang_item_defined
783 : 0 : = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
784 : :
785 : : // we need to have it maybe
786 : 0 : if (!lang_item_defined)
787 : : {
788 : 0 : rust_internal_error_at (expr.get_locus (),
789 : : "unable to find relevant lang item: %s",
790 : 0 : LangItem::ToString (lang_item_type).c_str ());
791 : : return;
792 : : }
793 : :
794 : : // look it up and it _must_ be a struct definition
795 : 0 : HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
796 : 0 : rust_assert (item != nullptr);
797 : :
798 : 0 : TyTy::BaseType *item_type = nullptr;
799 : 0 : bool ok
800 : 0 : = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
801 : 0 : rust_assert (ok);
802 : 0 : rust_assert (item_type->is_unit ());
803 : :
804 : 0 : infered = item_type;
805 : : }
806 : :
807 : : void
808 : 7 : TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr)
809 : : {
810 : 7 : auto lang_item_type = LangItem::Kind::RANGE_INCLUSIVE;
811 : :
812 : 7 : DefId respective_lang_item_id = UNKNOWN_DEFID;
813 : 7 : bool lang_item_defined
814 : 7 : = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
815 : :
816 : : // we need to have it maybe
817 : 7 : if (!lang_item_defined)
818 : : {
819 : 0 : rust_internal_error_at (expr.get_locus (),
820 : : "unable to find relevant lang item: %s",
821 : 0 : LangItem::ToString (lang_item_type).c_str ());
822 : : return;
823 : : }
824 : :
825 : : // look it up and it _must_ be a struct definition
826 : 7 : HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
827 : 7 : rust_assert (item != nullptr);
828 : :
829 : 7 : TyTy::BaseType *item_type = nullptr;
830 : 7 : bool ok
831 : 7 : = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
832 : 7 : rust_assert (ok);
833 : 7 : rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
834 : 7 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
835 : :
836 : : // this is a single generic item lets assert that
837 : 7 : rust_assert (adt->get_num_substitutions () == 1);
838 : :
839 : : // resolve the range expressions and these types must unify then we use that
840 : : // type to substitute into the ADT
841 : 7 : TyTy::BaseType *from_ty
842 : 7 : = TypeCheckExpr::Resolve (expr.get_from_expr ().get ());
843 : 7 : TyTy::BaseType *to_ty = TypeCheckExpr::Resolve (expr.get_to_expr ().get ());
844 : 14 : TyTy::BaseType *unified = unify_site (
845 : 7 : expr.get_mappings ().get_hirid (),
846 : 7 : TyTy::TyWithLocation (from_ty, expr.get_from_expr ()->get_locus ()),
847 : 7 : TyTy::TyWithLocation (to_ty, expr.get_to_expr ()->get_locus ()),
848 : : expr.get_locus ());
849 : :
850 : : // substitute it in
851 : 7 : std::vector<TyTy::SubstitutionArg> subst_mappings;
852 : 7 : const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
853 : 7 : subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
854 : :
855 : 7 : TyTy::SubstitutionArgumentMappings subst (
856 : 7 : subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
857 : 7 : expr.get_locus ());
858 : 7 : infered = SubstMapperInternal::Resolve (adt, subst);
859 : 7 : }
860 : :
861 : : void
862 : 433 : TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
863 : : {
864 : 433 : auto array_expr_ty = TypeCheckExpr::Resolve (expr.get_array_expr ().get ());
865 : 433 : if (array_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
866 : 432 : return;
867 : :
868 : 433 : auto index_expr_ty = TypeCheckExpr::Resolve (expr.get_index_expr ().get ());
869 : 433 : if (index_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
870 : : return;
871 : :
872 : : // first attempt to use direct array index logic
873 : 433 : auto direct_array_expr_ty = array_expr_ty;
874 : 433 : if (direct_array_expr_ty->get_kind () == TyTy::TypeKind::REF)
875 : : {
876 : : // lets try and deref it since rust allows this
877 : 253 : auto ref = static_cast<TyTy::ReferenceType *> (direct_array_expr_ty);
878 : 253 : auto base = ref->get_base ();
879 : 253 : if (base->get_kind () == TyTy::TypeKind::ARRAY)
880 : 433 : direct_array_expr_ty = base;
881 : : }
882 : :
883 : 433 : TyTy::BaseType *size_ty;
884 : 433 : bool ok = context->lookup_builtin ("usize", &size_ty);
885 : 433 : rust_assert (ok);
886 : :
887 : 433 : bool maybe_simple_array_access = index_expr_ty->can_eq (size_ty, false);
888 : 433 : if (maybe_simple_array_access
889 : 433 : && direct_array_expr_ty->get_kind () == TyTy::TypeKind::ARRAY)
890 : : {
891 : 738 : unify_site (expr.get_index_expr ()->get_mappings ().get_hirid (),
892 : 369 : TyTy::TyWithLocation (size_ty),
893 : : TyTy::TyWithLocation (index_expr_ty,
894 : 369 : expr.get_index_expr ()->get_locus ()),
895 : : expr.get_locus ());
896 : :
897 : 369 : TyTy::ArrayType *array_type
898 : : = static_cast<TyTy::ArrayType *> (direct_array_expr_ty);
899 : 369 : infered = array_type->get_element_type ()->clone ();
900 : 369 : return;
901 : : }
902 : :
903 : : // is this a case of core::ops::index?
904 : 64 : auto lang_item_type = LangItem::Kind::INDEX;
905 : 64 : bool operator_overloaded
906 : 64 : = resolve_operator_overload (lang_item_type, expr, array_expr_ty,
907 : : index_expr_ty);
908 : 64 : if (operator_overloaded)
909 : : {
910 : : // index and index mut always return a reference to the element
911 : 63 : TyTy::BaseType *resolved = infered;
912 : 63 : rust_assert (resolved->get_kind () == TyTy::TypeKind::REF);
913 : 63 : TyTy::ReferenceType *ref = static_cast<TyTy::ReferenceType *> (resolved);
914 : :
915 : 63 : infered = ref->get_base ()->clone ();
916 : 63 : return;
917 : : }
918 : :
919 : : // error[E0277]: the type `[{integer}]` cannot be indexed by `u32`
920 : 1 : rich_location r (line_table, expr.get_locus ());
921 : 1 : r.add_range (expr.get_array_expr ()->get_locus ());
922 : 1 : r.add_range (expr.get_index_expr ()->get_locus ());
923 : 1 : rust_error_at (r, ErrorCode::E0277,
924 : : "the type %qs cannot be indexed by %qs",
925 : 2 : array_expr_ty->get_name ().c_str (),
926 : 1 : index_expr_ty->get_name ().c_str ());
927 : 1 : }
928 : :
929 : : void
930 : 297 : TypeCheckExpr::visit (HIR::ArrayExpr &expr)
931 : : {
932 : 297 : HIR::ArrayElems &elements = *expr.get_internal_elements ();
933 : :
934 : 297 : HIR::Expr *capacity_expr = nullptr;
935 : 297 : TyTy::BaseType *element_type = nullptr;
936 : 297 : switch (elements.get_array_expr_type ())
937 : : {
938 : 108 : case HIR::ArrayElems::ArrayExprType::COPIED: {
939 : 108 : HIR::ArrayElemsCopied &elems
940 : : = static_cast<HIR::ArrayElemsCopied &> (elements);
941 : 108 : element_type
942 : 108 : = TypeCheckExpr::Resolve (elems.get_elem_to_copy ().get ());
943 : :
944 : 108 : auto capacity_type
945 : 108 : = TypeCheckExpr::Resolve (elems.get_num_copies_expr ().get ());
946 : :
947 : 108 : TyTy::BaseType *expected_ty = nullptr;
948 : 108 : bool ok = context->lookup_builtin ("usize", &expected_ty);
949 : 108 : rust_assert (ok);
950 : 108 : context->insert_type (elems.get_num_copies_expr ()->get_mappings (),
951 : : expected_ty);
952 : :
953 : 216 : unify_site (
954 : 108 : expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty),
955 : : TyTy::TyWithLocation (capacity_type,
956 : 108 : elems.get_num_copies_expr ()->get_locus ()),
957 : : expr.get_locus ());
958 : :
959 : 108 : capacity_expr = elems.get_num_copies_expr ().get ();
960 : : }
961 : 108 : break;
962 : :
963 : 189 : case HIR::ArrayElems::ArrayExprType::VALUES: {
964 : 189 : HIR::ArrayElemsValues &elems
965 : : = static_cast<HIR::ArrayElemsValues &> (elements);
966 : :
967 : 189 : std::vector<TyTy::BaseType *> types;
968 : 1118 : for (auto &elem : elems.get_values ())
969 : : {
970 : 929 : types.push_back (TypeCheckExpr::Resolve (elem.get ()));
971 : : }
972 : :
973 : : // this is a LUB
974 : 189 : element_type
975 : 189 : = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty ();
976 : 1118 : for (auto &type : types)
977 : : {
978 : 929 : element_type
979 : 929 : = unify_site (expr.get_mappings ().get_hirid (),
980 : 929 : TyTy::TyWithLocation (element_type),
981 : 929 : TyTy::TyWithLocation (type, type->get_locus ()),
982 : : expr.get_locus ());
983 : : }
984 : :
985 : 189 : auto crate_num = mappings->get_current_crate ();
986 : 189 : Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID,
987 : 189 : mappings->get_next_hir_id (crate_num),
988 : 189 : UNKNOWN_LOCAL_DEFID);
989 : 189 : std::string capacity_str = std::to_string (elems.get_num_elements ());
990 : 189 : capacity_expr = new HIR::LiteralExpr (mapping, capacity_str,
991 : : HIR::Literal::LitType::INT,
992 : : PrimitiveCoreType::CORETYPE_USIZE,
993 : 378 : UNDEF_LOCATION, {});
994 : :
995 : : // mark the type for this implicit node
996 : 189 : TyTy::BaseType *expected_ty = nullptr;
997 : 189 : bool ok = context->lookup_builtin ("usize", &expected_ty);
998 : 189 : rust_assert (ok);
999 : 189 : context->insert_type (mapping, expected_ty);
1000 : 189 : }
1001 : 189 : break;
1002 : : }
1003 : :
1004 : 297 : infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (),
1005 : : expr.get_locus (), *capacity_expr,
1006 : 297 : TyTy::TyVar (element_type->get_ref ()));
1007 : 297 : }
1008 : :
1009 : : // empty struct
1010 : : void
1011 : 51 : TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr)
1012 : : {
1013 : 51 : TyTy::BaseType *struct_path_ty
1014 : 51 : = TypeCheckExpr::Resolve (&struct_expr.get_struct_name ());
1015 : 51 : if (struct_path_ty->get_kind () != TyTy::TypeKind::ADT)
1016 : : {
1017 : 0 : rust_error_at (struct_expr.get_struct_name ().get_locus (),
1018 : : "expected an ADT type for constructor");
1019 : 0 : return;
1020 : : }
1021 : :
1022 : 51 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_path_ty);
1023 : 101 : for (auto variant : adt->get_variants ())
1024 : : {
1025 : 51 : if (!variant->get_fields ().empty ())
1026 : : {
1027 : 1 : std::vector<std::string> field_names;
1028 : 4 : for (auto &field : variant->get_fields ())
1029 : 3 : field_names.push_back (field->get_name ());
1030 : 1 : Error missing_fields_error
1031 : : = TypeCheckStructExpr::make_missing_field_error (
1032 : : struct_expr.get_locus (), field_names,
1033 : 1 : struct_path_ty->get_name ());
1034 : : // We might want to return or handle these in the future emit for now.
1035 : 1 : missing_fields_error.emit ();
1036 : 1 : return;
1037 : 1 : }
1038 : : }
1039 : :
1040 : 50 : infered = struct_path_ty;
1041 : : }
1042 : :
1043 : : void
1044 : 811 : TypeCheckExpr::visit (HIR::StructExprStructFields &struct_expr)
1045 : : {
1046 : 811 : infered = TypeCheckStructExpr::Resolve (&struct_expr);
1047 : 810 : }
1048 : :
1049 : : void
1050 : 159 : TypeCheckExpr::visit (HIR::GroupedExpr &expr)
1051 : : {
1052 : 159 : infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ());
1053 : 159 : }
1054 : :
1055 : : void
1056 : 1407 : TypeCheckExpr::visit (HIR::FieldAccessExpr &expr)
1057 : : {
1058 : 1407 : auto struct_base = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ());
1059 : :
1060 : : // FIXME does this require autoderef here?
1061 : 1407 : if (struct_base->get_kind () == TyTy::TypeKind::REF)
1062 : : {
1063 : 74 : TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (struct_base);
1064 : 74 : struct_base = r->get_base ();
1065 : : }
1066 : :
1067 : 1407 : bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT;
1068 : 1407 : if (!is_valid_type)
1069 : : {
1070 : 0 : rust_error_at (expr.get_locus (),
1071 : : "expected algebraic data type got: [%s]",
1072 : 0 : struct_base->as_string ().c_str ());
1073 : 0 : return;
1074 : : }
1075 : :
1076 : 1407 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_base);
1077 : 1407 : rust_assert (!adt->is_enum ());
1078 : 1407 : rust_assert (adt->number_of_variants () == 1);
1079 : :
1080 : 1407 : TyTy::VariantDef *vaiant = adt->get_variants ().at (0);
1081 : :
1082 : 1407 : TyTy::StructFieldType *lookup = nullptr;
1083 : 1407 : bool found = vaiant->lookup_field (expr.get_field_name ().as_string (),
1084 : : &lookup, nullptr);
1085 : 1407 : if (!found)
1086 : : {
1087 : 0 : rust_error_at (expr.get_locus (), "unknown field [%s] for type [%s]",
1088 : 0 : expr.get_field_name ().as_string ().c_str (),
1089 : 0 : adt->as_string ().c_str ());
1090 : 0 : return;
1091 : : }
1092 : :
1093 : 1407 : infered = lookup->get_field_type ();
1094 : : }
1095 : :
1096 : : void
1097 : 1035 : TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
1098 : : {
1099 : 1035 : auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ());
1100 : 1035 : if (receiver_tyty->get_kind () == TyTy::TypeKind::ERROR)
1101 : : {
1102 : 0 : rust_error_at (expr.get_receiver ()->get_locus (),
1103 : : "failed to resolve receiver in MethodCallExpr");
1104 : 6 : return;
1105 : : }
1106 : :
1107 : 1035 : context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
1108 : :
1109 : 1035 : rust_debug_loc (expr.get_locus (), "attempting to resolve method for %s",
1110 : 1035 : receiver_tyty->debug_str ().c_str ());
1111 : 1035 : auto candidates
1112 : : = MethodResolver::Probe (receiver_tyty,
1113 : 1035 : expr.get_method_name ().get_segment ());
1114 : 1035 : if (candidates.empty ())
1115 : : {
1116 : 4 : rich_location richloc (line_table, expr.get_method_name ().get_locus ());
1117 : 4 : richloc.add_fixit_replace ("method not found");
1118 : 4 : rust_error_at (
1119 : : richloc, ErrorCode::E0599,
1120 : : "no method named %qs found in the current scope",
1121 : 4 : expr.get_method_name ().get_segment ().as_string ().c_str ());
1122 : 4 : return;
1123 : 4 : }
1124 : :
1125 : 1031 : if (candidates.size () > 1)
1126 : : {
1127 : 2 : rich_location r (line_table, expr.get_method_name ().get_locus ());
1128 : 2 : std::string rich_msg
1129 : 4 : = "multiple " + expr.get_method_name ().get_segment ().as_string ()
1130 : 2 : + " found";
1131 : :
1132 : 6 : for (auto &c : candidates)
1133 : 4 : r.add_range (c.candidate.locus);
1134 : :
1135 : 2 : r.add_fixit_replace (rich_msg.c_str ());
1136 : :
1137 : 2 : rust_error_at (
1138 : : r, ErrorCode::E0592, "duplicate definitions with name %qs",
1139 : 2 : expr.get_method_name ().get_segment ().as_string ().c_str ());
1140 : 2 : return;
1141 : 2 : }
1142 : :
1143 : 1029 : auto candidate = *candidates.begin ();
1144 : 2058 : rust_debug_loc (expr.get_method_name ().get_locus (),
1145 : : "resolved method to: {%u} {%s} with [%lu] adjustments",
1146 : 1029 : candidate.candidate.ty->get_ref (),
1147 : 1029 : candidate.candidate.ty->debug_str ().c_str (),
1148 : 1029 : (unsigned long) candidate.adjustments.size ());
1149 : :
1150 : : // Get the adjusted self
1151 : 1029 : Adjuster adj (receiver_tyty);
1152 : 1029 : TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
1153 : 1029 : rust_debug ("receiver: %s adjusted self %s",
1154 : : receiver_tyty->debug_str ().c_str (),
1155 : : adjusted_self->debug_str ().c_str ());
1156 : :
1157 : : // store the adjustments for code-generation to know what to do which must be
1158 : : // stored onto the receiver to so as we don't trigger duplicate deref mappings
1159 : : // ICE when an argument is a method call
1160 : 1029 : HirId autoderef_mappings_id
1161 : 1029 : = expr.get_receiver ()->get_mappings ().get_hirid ();
1162 : 1029 : context->insert_autoderef_mappings (autoderef_mappings_id,
1163 : : std::move (candidate.adjustments));
1164 : :
1165 : 1029 : PathProbeCandidate &resolved_candidate = candidate.candidate;
1166 : 1029 : TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
1167 : 1029 : NodeId resolved_node_id
1168 : 1029 : = resolved_candidate.is_impl_candidate ()
1169 : 1029 : ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
1170 : 734 : .get_nodeid ()
1171 : 295 : : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
1172 : :
1173 : 1029 : if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
1174 : : {
1175 : 0 : rich_location r (line_table, expr.get_method_name ().get_locus ());
1176 : 0 : r.add_range (resolved_candidate.locus);
1177 : 0 : rust_error_at (r, "associated impl item is not a method");
1178 : 0 : return;
1179 : 0 : }
1180 : :
1181 : 1029 : TyTy::BaseType *lookup = lookup_tyty;
1182 : 1029 : TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
1183 : 1029 : if (!fn->is_method ())
1184 : : {
1185 : 0 : rich_location r (line_table, expr.get_method_name ().get_locus ());
1186 : 0 : r.add_range (resolved_candidate.locus);
1187 : 0 : rust_error_at (r, "associated function is not a method");
1188 : 0 : return;
1189 : 0 : }
1190 : :
1191 : 1029 : fn->prepare_higher_ranked_bounds ();
1192 : 1029 : rust_debug_loc (expr.get_locus (), "resolved method call to: {%u} {%s}",
1193 : 1029 : candidate.candidate.ty->get_ref (),
1194 : 1029 : candidate.candidate.ty->debug_str ().c_str ());
1195 : :
1196 : 1029 : if (resolved_candidate.is_impl_candidate ())
1197 : : {
1198 : 734 : auto infer_arguments = TyTy::SubstitutionArgumentMappings::empty ();
1199 : 734 : infer_arguments.get_mut_regions ()
1200 : 734 : = fn->get_used_arguments ().get_regions ();
1201 : 734 : HIR::ImplBlock &impl = *resolved_candidate.item.impl.parent;
1202 : 734 : TyTy::BaseType *impl_self_infer
1203 : 734 : = TypeCheckItem::ResolveImplBlockSelfWithInference (impl,
1204 : : expr.get_locus (),
1205 : : &infer_arguments);
1206 : 734 : if (impl_self_infer->get_kind () == TyTy::TypeKind::ERROR)
1207 : : {
1208 : 0 : rich_location r (line_table, expr.get_locus ());
1209 : 0 : r.add_range (impl.get_type ()->get_locus ());
1210 : 0 : rust_error_at (
1211 : : r, "failed to resolve impl type for method call resolution");
1212 : 0 : return;
1213 : 0 : }
1214 : :
1215 : 734 : if (!infer_arguments.is_empty ())
1216 : : {
1217 : 339 : lookup = SubstMapperInternal::Resolve (lookup, infer_arguments);
1218 : 339 : lookup->debug ();
1219 : : }
1220 : 734 : }
1221 : :
1222 : : // apply any remaining generic arguments
1223 : 1029 : if (expr.get_method_name ().has_generic_args ())
1224 : : {
1225 : 21 : HIR::GenericArgs &args = expr.get_method_name ().get_generic_args ();
1226 : 21 : rust_debug_loc (args.get_locus (),
1227 : : "applying generic arguments to method_call: {%s}",
1228 : 21 : lookup->debug_str ().c_str ());
1229 : :
1230 : 21 : lookup
1231 : 21 : = SubstMapper::Resolve (lookup, expr.get_method_name ().get_locus (),
1232 : : &args);
1233 : 21 : if (lookup->get_kind () == TyTy::TypeKind::ERROR)
1234 : : return;
1235 : : }
1236 : 1008 : else if (lookup->needs_generic_substitutions ())
1237 : : {
1238 : 338 : rust_debug ("method needs inference: {%s}",
1239 : : lookup->debug_str ().c_str ());
1240 : 338 : lookup = SubstMapper::InferSubst (lookup,
1241 : 338 : expr.get_method_name ().get_locus ());
1242 : : }
1243 : :
1244 : 1029 : rust_debug ("type-checking method_call: {%s}", lookup->debug_str ().c_str ());
1245 : :
1246 : 1029 : TyTy::BaseType *function_ret_tyty
1247 : 1029 : = TyTy::TypeCheckMethodCallExpr::go (static_cast<TyTy::FnType *> (lookup),
1248 : : expr, adjusted_self, context);
1249 : 1029 : if (function_ret_tyty == nullptr
1250 : 1029 : || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
1251 : : {
1252 : 0 : rust_error_at (expr.get_locus (),
1253 : : "failed to lookup type to MethodCallExpr");
1254 : 0 : return;
1255 : : }
1256 : :
1257 : : // store the expected fntype
1258 : 1029 : context->insert_type (expr.get_method_name ().get_mappings (), lookup);
1259 : :
1260 : : // set up the resolved name on the path
1261 : 1029 : if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
1262 : : {
1263 : 1028 : resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
1264 : : resolved_node_id);
1265 : : }
1266 : : else
1267 : : {
1268 : 1 : resolver->insert_resolved_misc (expr.get_mappings ().get_nodeid (),
1269 : : resolved_node_id);
1270 : : }
1271 : :
1272 : : // return the result of the function back
1273 : 1029 : infered = function_ret_tyty;
1274 : 1035 : }
1275 : :
1276 : : void
1277 : 90 : TypeCheckExpr::visit (HIR::LoopExpr &expr)
1278 : : {
1279 : 90 : context->push_new_loop_context (expr.get_mappings ().get_hirid (),
1280 : : expr.get_locus ());
1281 : 90 : TyTy::BaseType *block_expr
1282 : 90 : = TypeCheckExpr::Resolve (expr.get_loop_block ().get ());
1283 : 90 : if (!block_expr->is_unit ())
1284 : : {
1285 : 0 : rust_error_at (expr.get_loop_block ()->get_locus (),
1286 : : "expected %<()%> got %s",
1287 : 0 : block_expr->as_string ().c_str ());
1288 : 0 : return;
1289 : : }
1290 : :
1291 : 90 : TyTy::BaseType *loop_context_type = context->pop_loop_context ();
1292 : :
1293 : 90 : bool loop_context_type_infered
1294 : 90 : = (loop_context_type->get_kind () != TyTy::TypeKind::INFER)
1295 : 90 : || ((loop_context_type->get_kind () == TyTy::TypeKind::INFER)
1296 : 82 : && (((TyTy::InferType *) loop_context_type)->get_infer_kind ()
1297 : 165 : != TyTy::InferType::GENERAL));
1298 : :
1299 : 75 : infered
1300 : 90 : = loop_context_type_infered
1301 : : ? loop_context_type
1302 : 75 : : TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
1303 : : }
1304 : :
1305 : : void
1306 : 35 : TypeCheckExpr::visit (HIR::WhileLoopExpr &expr)
1307 : : {
1308 : 35 : context->push_new_while_loop_context (expr.get_mappings ().get_hirid ());
1309 : :
1310 : 35 : TypeCheckExpr::Resolve (expr.get_predicate_expr ().get ());
1311 : 35 : TyTy::BaseType *block_expr
1312 : 35 : = TypeCheckExpr::Resolve (expr.get_loop_block ().get ());
1313 : :
1314 : 35 : if (!block_expr->is_unit ())
1315 : : {
1316 : 0 : rust_error_at (expr.get_loop_block ()->get_locus (),
1317 : : "expected %<()%> got %s",
1318 : 0 : block_expr->as_string ().c_str ());
1319 : 0 : return;
1320 : : }
1321 : :
1322 : 35 : context->pop_loop_context ();
1323 : 35 : infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
1324 : : }
1325 : :
1326 : : void
1327 : 59 : TypeCheckExpr::visit (HIR::BreakExpr &expr)
1328 : : {
1329 : 59 : if (!context->have_loop_context ())
1330 : : {
1331 : 2 : rust_error_at (expr.get_locus (), ErrorCode::E0268,
1332 : : "%<break%> outside of a loop or labeled block");
1333 : 2 : return;
1334 : : }
1335 : :
1336 : 57 : if (expr.has_break_expr ())
1337 : : {
1338 : 17 : TyTy::BaseType *break_expr_tyty
1339 : 17 : = TypeCheckExpr::Resolve (expr.get_expr ().get ());
1340 : :
1341 : 17 : TyTy::BaseType *loop_context = context->peek_loop_context ();
1342 : 17 : if (loop_context->get_kind () == TyTy::TypeKind::ERROR)
1343 : : {
1344 : 2 : rust_error_at (
1345 : : expr.get_locus (), ErrorCode::E0571,
1346 : : "can only %<break%> with a value inside a %<loop%> block");
1347 : 2 : return;
1348 : : }
1349 : :
1350 : 15 : TyTy::BaseType *unified_ty
1351 : 30 : = unify_site (expr.get_mappings ().get_hirid (),
1352 : 15 : TyTy::TyWithLocation (loop_context),
1353 : : TyTy::TyWithLocation (break_expr_tyty,
1354 : 15 : expr.get_expr ()->get_locus ()),
1355 : : expr.get_locus ());
1356 : 15 : context->swap_head_loop_context (unified_ty);
1357 : : }
1358 : :
1359 : 55 : infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
1360 : : }
1361 : :
1362 : : void
1363 : 9 : TypeCheckExpr::visit (HIR::ContinueExpr &expr)
1364 : : {
1365 : 9 : if (!context->have_loop_context ())
1366 : : {
1367 : 2 : rust_error_at (expr.get_locus (), ErrorCode::E0268,
1368 : : "%<continue%> outside of a loop");
1369 : 2 : return;
1370 : : }
1371 : :
1372 : 7 : infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
1373 : : }
1374 : :
1375 : : void
1376 : 938 : TypeCheckExpr::visit (HIR::BorrowExpr &expr)
1377 : : {
1378 : 938 : TyTy::BaseType *resolved_base
1379 : 938 : = TypeCheckExpr::Resolve (expr.get_expr ().get ());
1380 : :
1381 : : // In Rust this is valid because of DST's
1382 : : //
1383 : : // fn test() {
1384 : : // let a:&str = "TEST 1";
1385 : : // let b:&str = &"TEST 2";
1386 : : // }
1387 : 938 : if (resolved_base->get_kind () == TyTy::TypeKind::REF)
1388 : : {
1389 : 42 : const TyTy::ReferenceType *ref
1390 : : = static_cast<const TyTy::ReferenceType *> (resolved_base);
1391 : :
1392 : : // this might end up being a more generic is_dyn object check but lets
1393 : : // double check dyn traits type-layout first
1394 : 42 : if (ref->is_dyn_str_type ())
1395 : : {
1396 : 9 : infered = resolved_base;
1397 : 9 : return;
1398 : : }
1399 : : }
1400 : :
1401 : 929 : infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (),
1402 : 929 : TyTy::TyVar (resolved_base->get_ref ()),
1403 : 1858 : expr.get_mut ());
1404 : : }
1405 : :
1406 : : void
1407 : 1232 : TypeCheckExpr::visit (HIR::DereferenceExpr &expr)
1408 : : {
1409 : 1232 : TyTy::BaseType *resolved_base
1410 : 1232 : = TypeCheckExpr::Resolve (expr.get_expr ().get ());
1411 : :
1412 : 1232 : rust_debug_loc (expr.get_locus (), "attempting deref operator overload");
1413 : 1232 : auto lang_item_type = LangItem::Kind::DEREF;
1414 : 1232 : bool operator_overloaded
1415 : 1232 : = resolve_operator_overload (lang_item_type, expr, resolved_base, nullptr);
1416 : 1232 : if (operator_overloaded)
1417 : : {
1418 : : // operator overloaded deref always refurns a reference type lets assert
1419 : : // this
1420 : 49 : rust_assert (infered->get_kind () == TyTy::TypeKind::REF);
1421 : 49 : resolved_base = infered;
1422 : : }
1423 : :
1424 : 1232 : bool is_valid_type = resolved_base->get_kind () == TyTy::TypeKind::REF
1425 : 1232 : || resolved_base->get_kind () == TyTy::TypeKind::POINTER;
1426 : 1232 : if (!is_valid_type)
1427 : : {
1428 : 0 : rust_error_at (expr.get_locus (), "expected reference type got %s",
1429 : 0 : resolved_base->as_string ().c_str ());
1430 : 0 : return;
1431 : : }
1432 : :
1433 : 1232 : if (resolved_base->get_kind () == TyTy::TypeKind::REF)
1434 : : {
1435 : 1069 : TyTy::ReferenceType *ref_base
1436 : : = static_cast<TyTy::ReferenceType *> (resolved_base);
1437 : 1069 : infered = ref_base->get_base ()->clone ();
1438 : : }
1439 : : else
1440 : : {
1441 : 163 : TyTy::PointerType *ref_base
1442 : : = static_cast<TyTy::PointerType *> (resolved_base);
1443 : 163 : infered = ref_base->get_base ()->clone ();
1444 : : }
1445 : : }
1446 : :
1447 : : void
1448 : 3283 : TypeCheckExpr::visit (HIR::TypeCastExpr &expr)
1449 : : {
1450 : 3283 : TyTy::BaseType *expr_to_convert
1451 : 3283 : = TypeCheckExpr::Resolve (expr.get_casted_expr ().get ());
1452 : 3283 : TyTy::BaseType *tyty_to_convert_to
1453 : 3283 : = TypeCheckType::Resolve (expr.get_type_to_convert_to ().get ());
1454 : :
1455 : 3283 : TyTy::TyWithLocation from (expr_to_convert,
1456 : 3283 : expr.get_casted_expr ()->get_locus ());
1457 : 3283 : TyTy::TyWithLocation to (tyty_to_convert_to,
1458 : 3283 : expr.get_type_to_convert_to ()->get_locus ());
1459 : 3283 : infered = cast_site (expr.get_mappings ().get_hirid (), from, to,
1460 : : expr.get_locus ());
1461 : 3283 : }
1462 : :
1463 : : void
1464 : 198 : TypeCheckExpr::visit (HIR::MatchExpr &expr)
1465 : : {
1466 : : // this needs to perform a least upper bound coercion on the blocks and then
1467 : : // unify the scruintee and arms
1468 : 198 : TyTy::BaseType *scrutinee_tyty
1469 : 198 : = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ());
1470 : :
1471 : 198 : std::vector<TyTy::BaseType *> kase_block_tys;
1472 : 692 : for (auto &kase : expr.get_match_cases ())
1473 : : {
1474 : : // lets check the arms
1475 : 496 : HIR::MatchArm &kase_arm = kase.get_arm ();
1476 : 990 : for (auto &pattern : kase_arm.get_patterns ())
1477 : : {
1478 : 496 : TyTy::BaseType *kase_arm_ty
1479 : 496 : = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
1480 : 496 : if (kase_arm_ty->get_kind () == TyTy ::TypeKind::ERROR)
1481 : 2 : return;
1482 : :
1483 : 988 : TyTy::BaseType *checked_kase = unify_site (
1484 : 494 : expr.get_mappings ().get_hirid (),
1485 : : TyTy::TyWithLocation (scrutinee_tyty,
1486 : 494 : expr.get_scrutinee_expr ()->get_locus ()),
1487 : 494 : TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
1488 : : expr.get_locus ());
1489 : 494 : if (checked_kase->get_kind () == TyTy::TypeKind::ERROR)
1490 : : return;
1491 : : }
1492 : :
1493 : : // check the kase type
1494 : 494 : TyTy::BaseType *kase_block_ty
1495 : 494 : = TypeCheckExpr::Resolve (kase.get_expr ().get ());
1496 : 494 : kase_block_tys.push_back (kase_block_ty);
1497 : : }
1498 : :
1499 : 196 : if (kase_block_tys.size () == 0)
1500 : : {
1501 : 0 : infered
1502 : 0 : = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
1503 : 0 : return;
1504 : : }
1505 : :
1506 : : // this is a LUB
1507 : 196 : infered = kase_block_tys.at (0);
1508 : 494 : for (size_t i = 1; i < kase_block_tys.size (); i++)
1509 : : {
1510 : 298 : TyTy::BaseType *kase_ty = kase_block_tys.at (i);
1511 : 596 : infered = unify_site (expr.get_mappings ().get_hirid (),
1512 : 298 : TyTy::TyWithLocation (infered),
1513 : 298 : TyTy::TyWithLocation (kase_ty), expr.get_locus ());
1514 : : }
1515 : 198 : }
1516 : :
1517 : : void
1518 : 53 : TypeCheckExpr::visit (HIR::ClosureExpr &expr)
1519 : : {
1520 : 53 : TypeCheckContextItem current_context = context->peek_context ();
1521 : 53 : TyTy::FnType *current_context_fndecl = current_context.get_context_type ();
1522 : :
1523 : 53 : HirId ref = expr.get_mappings ().get_hirid ();
1524 : 53 : DefId id = expr.get_mappings ().get_defid ();
1525 : 53 : RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()};
1526 : :
1527 : : // get from parent context
1528 : 53 : std::vector<TyTy::SubstitutionParamMapping> subst_refs
1529 : 53 : = current_context_fndecl->clone_substs ();
1530 : :
1531 : 53 : std::vector<TyTy::TyVar> parameter_types;
1532 : 106 : for (auto &p : expr.get_params ())
1533 : : {
1534 : 53 : TyTy::BaseType *param_tyty = nullptr;
1535 : 53 : if (p.has_type_given ())
1536 : : {
1537 : 51 : param_tyty = TypeCheckType::Resolve (p.get_type ().get ());
1538 : : }
1539 : : else
1540 : : {
1541 : 2 : param_tyty = ClosureParamInfer::Resolve (p.get_pattern ().get ());
1542 : : }
1543 : :
1544 : 53 : TyTy::TyVar param_ty (param_tyty->get_ref ());
1545 : 53 : parameter_types.push_back (param_ty);
1546 : :
1547 : 53 : TypeCheckPattern::Resolve (p.get_pattern ().get (), param_ty.get_tyty ());
1548 : : }
1549 : :
1550 : : // we generate an implicit hirid for the closure args
1551 : 53 : HirId implicit_args_id = mappings->get_next_hir_id ();
1552 : 53 : TyTy::TupleType *closure_args
1553 : : = new TyTy::TupleType (implicit_args_id, expr.get_locus (),
1554 : 53 : parameter_types);
1555 : 53 : context->insert_implicit_type (closure_args);
1556 : :
1557 : 53 : location_t result_type_locus = expr.has_return_type ()
1558 : 53 : ? expr.get_return_type ()->get_locus ()
1559 : 53 : : expr.get_locus ();
1560 : 53 : TyTy::TyVar result_type
1561 : 53 : = expr.has_return_type ()
1562 : 53 : ? TyTy::TyVar (
1563 : 0 : TypeCheckType::Resolve (expr.get_return_type ().get ())->get_ref ())
1564 : 53 : : TyTy::TyVar::get_implicit_infer_var (expr.get_locus ());
1565 : :
1566 : : // resolve the block
1567 : 53 : location_t closure_expr_locus = expr.get_expr ()->get_locus ();
1568 : 53 : TyTy::BaseType *closure_expr_ty
1569 : 53 : = TypeCheckExpr::Resolve (expr.get_expr ().get ());
1570 : 106 : coercion_site (expr.get_mappings ().get_hirid (),
1571 : : TyTy::TyWithLocation (result_type.get_tyty (),
1572 : 53 : result_type_locus),
1573 : 53 : TyTy::TyWithLocation (closure_expr_ty, closure_expr_locus),
1574 : : expr.get_locus ());
1575 : :
1576 : : // generate the closure type
1577 : 53 : NodeId closure_node_id = expr.get_mappings ().get_nodeid ();
1578 : 53 : const std::set<NodeId> &captures = resolver->get_captures (closure_node_id);
1579 : 53 : infered = new TyTy::ClosureType (ref, id, ident, closure_args, result_type,
1580 : 106 : subst_refs, captures);
1581 : :
1582 : : // FIXME
1583 : : // all closures automatically inherit the appropriate fn trait. Lets just
1584 : : // assume FnOnce for now. I think this is based on the return type of the
1585 : : // closure
1586 : :
1587 : 53 : LangItem::Kind lang_item_type = LangItem::Kind::FN_ONCE;
1588 : 53 : DefId respective_lang_item_id = UNKNOWN_DEFID;
1589 : 53 : bool lang_item_defined
1590 : 53 : = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
1591 : 53 : if (!lang_item_defined)
1592 : : {
1593 : : // FIXME
1594 : : // we need to have a unified way or error'ing when we are missing lang
1595 : : // items that is useful
1596 : 0 : rust_fatal_error (expr.get_locus (), "unable to find lang item: %qs",
1597 : 0 : LangItem::ToString (lang_item_type).c_str ());
1598 : : }
1599 : 53 : rust_assert (lang_item_defined);
1600 : :
1601 : : // these lang items are always traits
1602 : 53 : HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
1603 : 53 : rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
1604 : 53 : HIR::Trait *trait_item = static_cast<HIR::Trait *> (item);
1605 : :
1606 : 53 : TraitReference *trait = TraitResolver::Resolve (*trait_item);
1607 : 53 : rust_assert (!trait->is_error ());
1608 : :
1609 : 53 : TyTy::TypeBoundPredicate predicate (*trait, BoundPolarity::RegularBound,
1610 : 53 : expr.get_locus ());
1611 : :
1612 : : // resolve the trait bound where the <(Args)> are the parameter tuple type
1613 : 53 : HIR::GenericArgs args = HIR::GenericArgs::create_empty (expr.get_locus ());
1614 : :
1615 : : // lets generate an implicit Type so that it resolves to the implict tuple
1616 : : // type we have created
1617 : 53 : auto crate_num = mappings->get_current_crate ();
1618 : 53 : Analysis::NodeMapping mapping (crate_num, expr.get_mappings ().get_nodeid (),
1619 : 53 : implicit_args_id, UNKNOWN_LOCAL_DEFID);
1620 : 53 : HIR::TupleType *implicit_tuple
1621 : : = new HIR::TupleType (mapping,
1622 : : {} // we dont need to fill this out because it will
1623 : : // auto resolve because the hir id's match
1624 : : ,
1625 : 53 : expr.get_locus ());
1626 : 53 : args.get_type_args ().push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
1627 : :
1628 : : // apply the arguments
1629 : 53 : predicate.apply_generic_arguments (&args, false);
1630 : :
1631 : : // finally inherit the trait bound
1632 : 106 : infered->inherit_bounds ({predicate});
1633 : 53 : }
1634 : :
1635 : : bool
1636 : 4179 : TypeCheckExpr::resolve_operator_overload (LangItem::Kind lang_item_type,
1637 : : HIR::OperatorExprMeta expr,
1638 : : TyTy::BaseType *lhs,
1639 : : TyTy::BaseType *rhs)
1640 : : {
1641 : : // look up lang item for arithmetic type
1642 : 4179 : std::string associated_item_name = LangItem::ToString (lang_item_type);
1643 : 4179 : DefId respective_lang_item_id = UNKNOWN_DEFID;
1644 : 4179 : bool lang_item_defined
1645 : 4179 : = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
1646 : :
1647 : : // probe for the lang-item
1648 : 4179 : if (!lang_item_defined)
1649 : : return false;
1650 : :
1651 : : // we might be in a static or const context and unknown is fine
1652 : 561 : TypeCheckContextItem current_context = TypeCheckContextItem::get_error ();
1653 : 561 : if (context->have_function_context ())
1654 : : {
1655 : 561 : current_context = context->peek_context ();
1656 : : }
1657 : :
1658 : 561 : auto segment = HIR::PathIdentSegment (associated_item_name);
1659 : 561 : auto candidates = MethodResolver::Probe (lhs, segment);
1660 : :
1661 : : // remove any recursive candidates
1662 : 561 : std::set<MethodCandidate> resolved_candidates;
1663 : 1114 : for (auto &c : candidates)
1664 : : {
1665 : 553 : const TyTy::BaseType *candidate_type = c.candidate.ty;
1666 : 553 : rust_assert (candidate_type->get_kind () == TyTy::TypeKind::FNDEF);
1667 : :
1668 : 553 : const TyTy::FnType &fn
1669 : : = *static_cast<const TyTy::FnType *> (candidate_type);
1670 : :
1671 : 553 : DefId current_fn_defid = current_context.get_defid ();
1672 : 1106 : bool recursive_candidated = fn.get_id () == current_fn_defid;
1673 : 492 : if (!recursive_candidated)
1674 : : {
1675 : 492 : resolved_candidates.insert (c);
1676 : : }
1677 : : }
1678 : :
1679 : 561 : std::vector<TyTy::BaseType *> select_args = {};
1680 : 561 : if (rhs != nullptr)
1681 : 344 : select_args = {rhs};
1682 : 561 : auto selected_candidates
1683 : 561 : = MethodResolver::Select (resolved_candidates, lhs, select_args);
1684 : :
1685 : 561 : bool have_implementation_for_lang_item = selected_candidates.size () > 0;
1686 : 561 : if (!have_implementation_for_lang_item)
1687 : : return false;
1688 : :
1689 : 475 : if (selected_candidates.size () > 1)
1690 : : {
1691 : : // mutliple candidates
1692 : 0 : rich_location r (line_table, expr.get_locus ());
1693 : 0 : for (auto &c : resolved_candidates)
1694 : 0 : r.add_range (c.candidate.locus);
1695 : :
1696 : 0 : rust_error_at (
1697 : : r, "multiple candidates found for possible operator overload");
1698 : :
1699 : 0 : return false;
1700 : 0 : }
1701 : :
1702 : : // Get the adjusted self
1703 : 475 : MethodCandidate candidate = *selected_candidates.begin ();
1704 : 475 : Adjuster adj (lhs);
1705 : 475 : TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
1706 : :
1707 : : // store the adjustments for code-generation to know what to do
1708 : 475 : context->insert_autoderef_mappings (expr.get_lvalue_mappings ().get_hirid (),
1709 : : std::move (candidate.adjustments));
1710 : :
1711 : : // now its just like a method-call-expr
1712 : 475 : context->insert_receiver (expr.get_mappings ().get_hirid (), lhs);
1713 : :
1714 : 475 : PathProbeCandidate &resolved_candidate = candidate.candidate;
1715 : 475 : TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
1716 : 475 : NodeId resolved_node_id
1717 : 475 : = resolved_candidate.is_impl_candidate ()
1718 : 475 : ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
1719 : 200 : .get_nodeid ()
1720 : 275 : : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
1721 : :
1722 : 475 : rust_assert (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF);
1723 : 475 : TyTy::BaseType *lookup = lookup_tyty;
1724 : 475 : TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
1725 : 475 : rust_assert (fn->is_method ());
1726 : :
1727 : 750 : rust_debug ("is_impl_item_candidate: %s",
1728 : : resolved_candidate.is_impl_candidate () ? "true" : "false");
1729 : :
1730 : 475 : if (resolved_candidate.is_impl_candidate ())
1731 : : {
1732 : 200 : auto infer_arguments = TyTy::SubstitutionArgumentMappings::error ();
1733 : 200 : HIR::ImplBlock &impl = *resolved_candidate.item.impl.parent;
1734 : 200 : TyTy::BaseType *impl_self_infer
1735 : 200 : = TypeCheckItem::ResolveImplBlockSelfWithInference (impl,
1736 : : expr.get_locus (),
1737 : : &infer_arguments);
1738 : 200 : if (impl_self_infer->get_kind () == TyTy::TypeKind::ERROR)
1739 : : {
1740 : 0 : return false;
1741 : : }
1742 : 200 : if (!infer_arguments.is_empty ())
1743 : : {
1744 : 98 : lookup = SubstMapperInternal::Resolve (lookup, infer_arguments);
1745 : : }
1746 : 200 : }
1747 : :
1748 : : // in the case where we resolve to a trait bound we have to be careful we are
1749 : : // able to do so there is a case where we are currently resolving the deref
1750 : : // operator overload function which is generic and this might resolve to the
1751 : : // trait item of deref which is not valid as its just another recursive case
1752 : 475 : if (current_context.get_type () == TypeCheckContextItem::ItemType::IMPL_ITEM)
1753 : : {
1754 : 273 : auto &impl_item = current_context.get_impl_item ();
1755 : 273 : HIR::ImplBlock *parent = impl_item.first;
1756 : 273 : HIR::Function *fn = impl_item.second;
1757 : :
1758 : 546 : if (parent->has_trait_ref ()
1759 : 819 : && fn->get_function_name ().as_string ().compare (
1760 : : associated_item_name)
1761 : : == 0)
1762 : : {
1763 : 265 : TraitReference *trait_reference
1764 : 265 : = TraitResolver::Lookup (*parent->get_trait_ref ().get ());
1765 : 265 : if (!trait_reference->is_error ())
1766 : : {
1767 : 265 : TyTy::BaseType *lookup = nullptr;
1768 : 265 : bool ok = context->lookup_type (fn->get_mappings ().get_hirid (),
1769 : : &lookup);
1770 : 265 : rust_assert (ok);
1771 : 265 : rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
1772 : :
1773 : 265 : TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
1774 : 265 : rust_assert (fntype->is_method ());
1775 : :
1776 : 265 : bool is_lang_item_impl
1777 : 265 : = trait_reference->get_mappings ().get_defid ()
1778 : 265 : == respective_lang_item_id;
1779 : 265 : bool self_is_lang_item_self
1780 : 265 : = fntype->get_self_type ()->is_equal (*adjusted_self);
1781 : 265 : bool recursive_operator_overload
1782 : : = is_lang_item_impl && self_is_lang_item_self;
1783 : :
1784 : 265 : if (recursive_operator_overload)
1785 : 258 : return false;
1786 : : }
1787 : : }
1788 : : }
1789 : :
1790 : : // we found a valid operator overload
1791 : 217 : fn->prepare_higher_ranked_bounds ();
1792 : 217 : rust_debug_loc (expr.get_locus (), "resolved operator overload to: {%u} {%s}",
1793 : 217 : candidate.candidate.ty->get_ref (),
1794 : 217 : candidate.candidate.ty->debug_str ().c_str ());
1795 : :
1796 : : // handle generics
1797 : 217 : if (lookup->needs_generic_substitutions ())
1798 : 17 : lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
1799 : :
1800 : : // type check the arguments if required
1801 : 217 : TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
1802 : 217 : rust_assert (type->num_params () > 0);
1803 : 217 : auto fnparam = type->param_at (0);
1804 : :
1805 : : // typecheck the self
1806 : 434 : unify_site (expr.get_mappings ().get_hirid (),
1807 : 217 : TyTy::TyWithLocation (fnparam.second),
1808 : 217 : TyTy::TyWithLocation (adjusted_self), expr.get_locus ());
1809 : 217 : if (rhs == nullptr)
1810 : : {
1811 : 63 : rust_assert (type->num_params () == 1);
1812 : : }
1813 : : else
1814 : : {
1815 : 154 : rust_assert (type->num_params () == 2);
1816 : 154 : auto fnparam = type->param_at (1);
1817 : 308 : unify_site (expr.get_mappings ().get_hirid (),
1818 : 154 : TyTy::TyWithLocation (fnparam.second),
1819 : 154 : TyTy::TyWithLocation (rhs), expr.get_locus ());
1820 : : }
1821 : :
1822 : 217 : rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
1823 : 217 : fn = static_cast<TyTy::FnType *> (lookup);
1824 : 217 : fn->monomorphize ();
1825 : :
1826 : : // get the return type
1827 : 217 : TyTy::BaseType *function_ret_tyty
1828 : 217 : = type->get_return_type ()->monomorphized_clone ();
1829 : :
1830 : : // store the expected fntype
1831 : 217 : context->insert_operator_overload (expr.get_mappings ().get_hirid (), type);
1832 : :
1833 : : // set up the resolved name on the path
1834 : 217 : resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
1835 : : resolved_node_id);
1836 : :
1837 : : // return the result of the function back
1838 : 217 : infered = function_ret_tyty;
1839 : :
1840 : 217 : return true;
1841 : 1036 : }
1842 : :
1843 : : HIR::PathIdentSegment
1844 : 5840 : TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
1845 : : TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate)
1846 : : {
1847 : : // Question
1848 : : // do we need to probe possible bounds here? I think not, i think when we
1849 : : // support Fn traits they are explicitly specified
1850 : :
1851 : : // FIXME
1852 : : // the logic to map the FnTrait to their respective call trait-item is
1853 : : // duplicated over in the backend/rust-compile-expr.cc
1854 : 5857 : for (auto &bound : receiver.get_specified_bounds ())
1855 : : {
1856 : 71 : bool found_fn = bound.get_name ().compare ("Fn") == 0;
1857 : 71 : bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
1858 : 71 : bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0;
1859 : :
1860 : 71 : if (found_fn)
1861 : : {
1862 : 0 : *associated_predicate = bound;
1863 : 0 : return HIR::PathIdentSegment ("call");
1864 : : }
1865 : 71 : else if (found_fn_mut)
1866 : : {
1867 : 0 : *associated_predicate = bound;
1868 : 0 : return HIR::PathIdentSegment ("call_mut");
1869 : : }
1870 : 71 : else if (found_fn_once)
1871 : : {
1872 : 54 : *associated_predicate = bound;
1873 : 54 : return HIR::PathIdentSegment ("call_once");
1874 : : }
1875 : : }
1876 : :
1877 : : // nothing
1878 : 5786 : *associated_predicate = TyTy::TypeBoundPredicate::error ();
1879 : 5786 : return HIR::PathIdentSegment ("");
1880 : : }
1881 : :
1882 : : bool
1883 : 5840 : TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr,
1884 : : TyTy::BaseType *receiver_tyty,
1885 : : TyTy::BaseType **result)
1886 : : {
1887 : : // we turn this into a method call expr
1888 : : // TODO: add implicit self argument (?)
1889 : 5840 : auto associated_predicate = TyTy::TypeBoundPredicate::error ();
1890 : 5840 : HIR::PathIdentSegment method_name
1891 : : = resolve_possible_fn_trait_call_method_name (*receiver_tyty,
1892 : 5840 : &associated_predicate);
1893 : 5840 : if (method_name.is_error () || associated_predicate.is_error ())
1894 : 5786 : return false;
1895 : :
1896 : 54 : auto candidates = MethodResolver::Probe (receiver_tyty, method_name);
1897 : 54 : if (candidates.empty ())
1898 : : return false;
1899 : :
1900 : 54 : if (candidates.size () > 1)
1901 : : {
1902 : 0 : rich_location r (line_table, expr.get_locus ());
1903 : 0 : for (auto &c : candidates)
1904 : 0 : r.add_range (c.candidate.locus);
1905 : :
1906 : 0 : rust_error_at (
1907 : : r, "multiple candidates found for function trait method call %qs",
1908 : 0 : method_name.as_string ().c_str ());
1909 : 0 : return false;
1910 : 0 : }
1911 : :
1912 : 54 : if (receiver_tyty->get_kind () == TyTy::TypeKind::CLOSURE)
1913 : : {
1914 : 37 : const TyTy::ClosureType &closure
1915 : : = static_cast<TyTy::ClosureType &> (*receiver_tyty);
1916 : 37 : closure.setup_fn_once_output ();
1917 : : }
1918 : :
1919 : 54 : auto candidate = *candidates.begin ();
1920 : 54 : rust_debug_loc (expr.get_locus (),
1921 : : "resolved call-expr to fn trait: {%u} {%s}",
1922 : 54 : candidate.candidate.ty->get_ref (),
1923 : 54 : candidate.candidate.ty->debug_str ().c_str ());
1924 : :
1925 : : // Get the adjusted self
1926 : 54 : Adjuster adj (receiver_tyty);
1927 : 54 : TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
1928 : :
1929 : : // store the adjustments for code-generation to know what to do which must be
1930 : : // stored onto the receiver to so as we don't trigger duplicate deref mappings
1931 : : // ICE when an argument is a method call
1932 : 54 : HIR::Expr *fnexpr = expr.get_fnexpr ().get ();
1933 : 54 : HirId autoderef_mappings_id = fnexpr->get_mappings ().get_hirid ();
1934 : 54 : context->insert_autoderef_mappings (autoderef_mappings_id,
1935 : : std::move (candidate.adjustments));
1936 : 54 : context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
1937 : :
1938 : 54 : PathProbeCandidate &resolved_candidate = candidate.candidate;
1939 : 54 : TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
1940 : 54 : NodeId resolved_node_id
1941 : 54 : = resolved_candidate.is_impl_candidate ()
1942 : 54 : ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
1943 : 0 : .get_nodeid ()
1944 : 54 : : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
1945 : :
1946 : 54 : if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
1947 : : {
1948 : 0 : rich_location r (line_table, expr.get_locus ());
1949 : 0 : r.add_range (resolved_candidate.locus);
1950 : 0 : rust_error_at (r, "associated impl item is not a method");
1951 : 0 : return false;
1952 : 0 : }
1953 : :
1954 : 54 : TyTy::BaseType *lookup = lookup_tyty;
1955 : 54 : TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
1956 : 54 : if (!fn->is_method ())
1957 : : {
1958 : 0 : rich_location r (line_table, expr.get_locus ());
1959 : 0 : r.add_range (resolved_candidate.locus);
1960 : 0 : rust_error_at (r, "associated function is not a method");
1961 : 0 : return false;
1962 : 0 : }
1963 : :
1964 : : // fn traits only support tuple argument passing so we need to implicitly set
1965 : : // this up to get the same type checking we get in the rest of the pipeline
1966 : :
1967 : 54 : std::vector<TyTy::TyVar> call_args;
1968 : 108 : for (auto &arg : expr.get_arguments ())
1969 : : {
1970 : 54 : TyTy::BaseType *a = TypeCheckExpr::Resolve (arg.get ());
1971 : 54 : call_args.push_back (TyTy::TyVar (a->get_ref ()));
1972 : : }
1973 : :
1974 : : // crate implicit tuple
1975 : 54 : HirId implicit_arg_id = mappings->get_next_hir_id ();
1976 : 54 : Analysis::NodeMapping mapping (mappings->get_current_crate (), UNKNOWN_NODEID,
1977 : 54 : implicit_arg_id, UNKNOWN_LOCAL_DEFID);
1978 : :
1979 : 54 : TyTy::TupleType *tuple
1980 : 54 : = new TyTy::TupleType (implicit_arg_id, expr.get_locus (), call_args);
1981 : 54 : context->insert_implicit_type (implicit_arg_id, tuple);
1982 : :
1983 : 54 : std::vector<TyTy::Argument> args;
1984 : 54 : TyTy::Argument a (mapping, tuple,
1985 : 54 : expr.get_locus () /*FIXME is there a better location*/);
1986 : 54 : args.push_back (std::move (a));
1987 : :
1988 : 54 : TyTy::BaseType *function_ret_tyty
1989 : 54 : = TyTy::TypeCheckMethodCallExpr::go (fn, expr.get_mappings (), args,
1990 : : expr.get_locus (), expr.get_locus (),
1991 : : adjusted_self, context);
1992 : 54 : if (function_ret_tyty == nullptr
1993 : 54 : || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
1994 : : {
1995 : 0 : rust_error_at (expr.get_locus (),
1996 : : "failed check fn trait call-expr MethodCallExpr");
1997 : 0 : return false;
1998 : : }
1999 : :
2000 : : // store the expected fntype
2001 : 54 : context->insert_operator_overload (expr.get_mappings ().get_hirid (), fn);
2002 : :
2003 : : // set up the resolved name on the path
2004 : 54 : resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
2005 : : resolved_node_id);
2006 : :
2007 : : // return the result of the function back
2008 : 54 : *result = function_ret_tyty;
2009 : :
2010 : 54 : return true;
2011 : 6002 : }
2012 : :
2013 : : bool
2014 : 5004 : TypeCheckExpr::validate_arithmetic_type (
2015 : : const TyTy::BaseType *tyty, HIR::ArithmeticOrLogicalExpr::ExprType expr_type)
2016 : : {
2017 : 5004 : const TyTy::BaseType *type = tyty->destructure ();
2018 : :
2019 : : // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators
2020 : : // this will change later when traits are added
2021 : 5004 : switch (expr_type)
2022 : : {
2023 : 4756 : case ArithmeticOrLogicalOperator::ADD:
2024 : 4756 : case ArithmeticOrLogicalOperator::SUBTRACT:
2025 : 4756 : case ArithmeticOrLogicalOperator::MULTIPLY:
2026 : 4756 : case ArithmeticOrLogicalOperator::DIVIDE:
2027 : 4756 : case ArithmeticOrLogicalOperator::MODULUS:
2028 : 4756 : return (type->get_kind () == TyTy::TypeKind::INT)
2029 : 3653 : || (type->get_kind () == TyTy::TypeKind::UINT)
2030 : 3143 : || (type->get_kind () == TyTy::TypeKind::FLOAT)
2031 : 2920 : || (type->get_kind () == TyTy::TypeKind::USIZE)
2032 : 2619 : || (type->get_kind () == TyTy::TypeKind::ISIZE)
2033 : 2568 : || (type->get_kind () == TyTy::TypeKind::INFER
2034 : 2567 : && (((const TyTy::InferType *) type)->get_infer_kind ()
2035 : : == TyTy::InferType::INTEGRAL))
2036 : 4792 : || (type->get_kind () == TyTy::TypeKind::INFER
2037 : 35 : && (((const TyTy::InferType *) type)->get_infer_kind ()
2038 : : == TyTy::InferType::FLOAT));
2039 : :
2040 : : // integers or bools
2041 : 160 : case ArithmeticOrLogicalOperator::BITWISE_AND:
2042 : 160 : case ArithmeticOrLogicalOperator::BITWISE_OR:
2043 : 160 : case ArithmeticOrLogicalOperator::BITWISE_XOR:
2044 : 160 : return (type->get_kind () == TyTy::TypeKind::INT)
2045 : 111 : || (type->get_kind () == TyTy::TypeKind::UINT)
2046 : 111 : || (type->get_kind () == TyTy::TypeKind::USIZE)
2047 : 111 : || (type->get_kind () == TyTy::TypeKind::ISIZE)
2048 : 111 : || (type->get_kind () == TyTy::TypeKind::BOOL)
2049 : 229 : || (type->get_kind () == TyTy::TypeKind::INFER
2050 : 69 : && (((const TyTy::InferType *) type)->get_infer_kind ()
2051 : : == TyTy::InferType::INTEGRAL));
2052 : :
2053 : : // integers only
2054 : 88 : case ArithmeticOrLogicalOperator::LEFT_SHIFT:
2055 : 88 : case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
2056 : 88 : return (type->get_kind () == TyTy::TypeKind::INT)
2057 : 74 : || (type->get_kind () == TyTy::TypeKind::UINT)
2058 : 72 : || (type->get_kind () == TyTy::TypeKind::USIZE)
2059 : 72 : || (type->get_kind () == TyTy::TypeKind::ISIZE)
2060 : 160 : || (type->get_kind () == TyTy::TypeKind::INFER
2061 : 72 : && (((const TyTy::InferType *) type)->get_infer_kind ()
2062 : : == TyTy::InferType::INTEGRAL));
2063 : : }
2064 : :
2065 : 0 : rust_unreachable ();
2066 : : return false;
2067 : : }
2068 : :
2069 : : } // namespace Resolver
2070 : : } // namespace Rust
|