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