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