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