1 // Copyright (C) 2020-2025 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
19 #include "rust-tyty-call.h"
20 #include "rust-hir-type-check-struct-field.h"
21 #include "rust-hir-path-probe.h"
22 #include "rust-substitution-mapper.h"
23 #include "rust-hir-trait-resolve.h"
24 #include "rust-hir-dot-operator.h"
25 #include "rust-hir-type-check-pattern.h"
26 #include "rust-hir-type-check-expr.h"
27 #include "rust-hir-type-check-stmt.h"
28 #include "rust-hir-type-check-item.h"
29 #include "rust-type-util.h"
34 TypeCheckExpr::TypeCheckExpr () : TypeCheckBase (), infered (nullptr) {}
36 // Perform type checking on expr. Also runs type unification algorithm.
37 // Returns the unified type of expr
39 TypeCheckExpr::Resolve (HIR::Expr
*expr
)
41 TypeCheckExpr resolver
;
42 expr
->accept_vis (resolver
);
44 if (resolver
.infered
== nullptr)
45 return new TyTy::ErrorType (expr
->get_mappings ().get_hirid ());
47 auto ref
= expr
->get_mappings ().get_hirid ();
48 resolver
.infered
->set_ref (ref
);
49 resolver
.context
->insert_type (expr
->get_mappings (), resolver
.infered
);
51 return resolver
.infered
;
55 TypeCheckExpr::visit (HIR::TupleIndexExpr
&expr
)
57 auto resolved
= TypeCheckExpr::Resolve (expr
.get_tuple_expr ().get ());
58 if (resolved
->get_kind () == TyTy::TypeKind::ERROR
)
60 rust_error_at (expr
.get_tuple_expr ()->get_locus (),
61 "failed to resolve TupleIndexExpr receiver");
65 // FIXME does this require autoderef here?
66 if (resolved
->get_kind () == TyTy::TypeKind::REF
)
68 TyTy::ReferenceType
*r
= static_cast<TyTy::ReferenceType
*> (resolved
);
69 resolved
= r
->get_base ();
72 bool is_valid_type
= resolved
->get_kind () == TyTy::TypeKind::ADT
73 || resolved
->get_kind () == TyTy::TypeKind::TUPLE
;
76 rust_error_at (expr
.get_tuple_expr ()->get_locus (),
77 "Expected Tuple or ADT got: %s",
78 resolved
->as_string ().c_str ());
82 if (resolved
->get_kind () == TyTy::TypeKind::TUPLE
)
84 TyTy::TupleType
*tuple
= static_cast<TyTy::TupleType
*> (resolved
);
85 TupleIndex index
= expr
.get_tuple_index ();
86 if ((size_t) index
>= tuple
->num_fields ())
88 rust_error_at (expr
.get_locus (), "unknown field at index %i", index
);
92 auto field_tyty
= tuple
->get_field ((size_t) index
);
93 if (field_tyty
== nullptr)
95 rust_error_at (expr
.get_locus (),
96 "failed to lookup field type at index %i", index
);
100 infered
= field_tyty
;
104 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (resolved
);
105 rust_assert (!adt
->is_enum ());
106 rust_assert (adt
->number_of_variants () == 1);
108 TyTy::VariantDef
*variant
= adt
->get_variants ().at (0);
109 TupleIndex index
= expr
.get_tuple_index ();
110 if ((size_t) index
>= variant
->num_fields ())
112 rust_error_at (expr
.get_locus (), "unknown field at index %i", index
);
116 auto field_tyty
= variant
->get_field_at_index ((size_t) index
);
117 if (field_tyty
== nullptr)
119 rust_error_at (expr
.get_locus (),
120 "failed to lookup field type at index %i", index
);
124 infered
= field_tyty
->get_field_type ();
128 TypeCheckExpr::visit (HIR::TupleExpr
&expr
)
132 auto unit_node_id
= resolver
->get_unit_type_node_id ();
133 if (!context
->lookup_builtin (unit_node_id
, &infered
))
135 rust_error_at (expr
.get_locus (),
136 "failed to lookup builtin unit type");
141 std::vector
<TyTy::TyVar
> fields
;
142 for (auto &elem
: expr
.get_tuple_elems ())
144 auto field_ty
= TypeCheckExpr::Resolve (elem
.get ());
145 fields
.push_back (TyTy::TyVar (field_ty
->get_ref ()));
147 infered
= new TyTy::TupleType (expr
.get_mappings ().get_hirid (),
148 expr
.get_locus (), fields
);
152 TypeCheckExpr::visit (HIR::ReturnExpr
&expr
)
154 if (!context
->have_function_context ())
156 rust_error_at (expr
.get_locus (), ErrorCode::E0572
,
157 "return statement outside of function body");
158 infered
= new TyTy::ErrorType (expr
.get_mappings ().get_hirid ());
162 auto fn_return_tyty
= context
->peek_return_type ();
163 location_t expr_locus
= expr
.has_return_expr ()
164 ? expr
.get_expr ()->get_locus ()
166 TyTy::BaseType
*expr_ty
167 = expr
.has_return_expr ()
168 ? TypeCheckExpr::Resolve (expr
.get_expr ().get ())
169 : TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
171 coercion_site (expr
.get_mappings ().get_hirid (),
172 TyTy::TyWithLocation (fn_return_tyty
),
173 TyTy::TyWithLocation (expr_ty
, expr_locus
), expr
.get_locus ());
175 infered
= new TyTy::NeverType (expr
.get_mappings ().get_hirid ());
179 TypeCheckExpr::visit (HIR::CallExpr
&expr
)
181 TyTy::BaseType
*function_tyty
182 = TypeCheckExpr::Resolve (expr
.get_fnexpr ().get ());
184 rust_debug_loc (expr
.get_locus (), "resolved_call_expr to: {%s}",
185 function_tyty
->get_name ().c_str ());
187 TyTy::VariantDef
&variant
= TyTy::VariantDef::get_error_node ();
188 if (function_tyty
->get_kind () == TyTy::TypeKind::ADT
)
190 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (function_tyty
);
195 bool ok
= context
->lookup_variant_definition (
196 expr
.get_fnexpr ()->get_mappings ().get_hirid (), &variant_id
);
199 TyTy::VariantDef
*lookup_variant
= nullptr;
200 ok
= adt
->lookup_variant_by_id (variant_id
, &lookup_variant
);
203 variant
= *lookup_variant
;
207 rust_assert (adt
->number_of_variants () == 1);
208 variant
= *adt
->get_variants ().at (0);
212 = TyTy::TypeCheckCallExpr::go (function_tyty
, expr
, variant
, context
);
216 bool resolved_fn_trait_call
217 = resolve_fn_trait_call (expr
, function_tyty
, &infered
);
218 if (resolved_fn_trait_call
)
221 bool valid_tyty
= function_tyty
->get_kind () == TyTy::TypeKind::FNDEF
222 || function_tyty
->get_kind () == TyTy::TypeKind::FNPTR
;
225 rust_error_at (expr
.get_locus (),
226 "Failed to resolve expression of function call");
230 infered
= TyTy::TypeCheckCallExpr::go (function_tyty
, expr
, variant
, context
);
234 TypeCheckExpr::visit (HIR::AssignmentExpr
&expr
)
236 infered
= TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
238 auto lhs
= TypeCheckExpr::Resolve (expr
.get_lhs ().get ());
239 auto rhs
= TypeCheckExpr::Resolve (expr
.get_rhs ().get ());
241 coercion_site (expr
.get_mappings ().get_hirid (),
242 TyTy::TyWithLocation (lhs
, expr
.get_lhs ()->get_locus ()),
243 TyTy::TyWithLocation (rhs
, expr
.get_rhs ()->get_locus ()),
248 TypeCheckExpr::visit (HIR::CompoundAssignmentExpr
&expr
)
250 infered
= TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
252 auto lhs
= TypeCheckExpr::Resolve (expr
.get_lhs ().get ());
253 auto rhs
= TypeCheckExpr::Resolve (expr
.get_rhs ().get ());
255 // we dont care about the result of the unify from a compound assignment
256 // since this is a unit-type expr
257 coercion_site (expr
.get_mappings ().get_hirid (),
258 TyTy::TyWithLocation (lhs
, expr
.get_lhs ()->get_locus ()),
259 TyTy::TyWithLocation (rhs
, expr
.get_rhs ()->get_locus ()),
263 = LangItem::CompoundAssignmentOperatorToLangItem (expr
.get_expr_type ());
264 bool operator_overloaded
265 = resolve_operator_overload (lang_item_type
, expr
, lhs
, rhs
);
266 if (operator_overloaded
)
269 bool valid_lhs
= validate_arithmetic_type (lhs
, expr
.get_expr_type ());
270 bool valid_rhs
= validate_arithmetic_type (rhs
, expr
.get_expr_type ());
271 bool valid
= valid_lhs
&& valid_rhs
;
274 rust_error_at (expr
.get_locus (),
275 "cannot apply this operator to types %s and %s",
276 lhs
->as_string ().c_str (), rhs
->as_string ().c_str ());
282 TypeCheckExpr::visit (HIR::LiteralExpr
&expr
)
284 infered
= resolve_literal (expr
.get_mappings (), expr
.get_literal (),
289 TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr
&expr
)
291 auto lhs
= TypeCheckExpr::Resolve (expr
.get_lhs ().get ());
292 auto rhs
= TypeCheckExpr::Resolve (expr
.get_rhs ().get ());
294 auto lang_item_type
= LangItem::OperatorToLangItem (expr
.get_expr_type ());
295 bool operator_overloaded
296 = resolve_operator_overload (lang_item_type
, expr
, lhs
, rhs
);
297 if (operator_overloaded
)
300 bool valid_lhs
= validate_arithmetic_type (lhs
, expr
.get_expr_type ());
301 bool valid_rhs
= validate_arithmetic_type (rhs
, expr
.get_expr_type ());
302 bool valid
= valid_lhs
&& valid_rhs
;
305 rust_error_at (expr
.get_locus (),
306 "cannot apply this operator to types %s and %s",
307 lhs
->as_string ().c_str (), rhs
->as_string ().c_str ());
311 switch (expr
.get_expr_type ())
313 case ArithmeticOrLogicalOperator::LEFT_SHIFT
:
314 case ArithmeticOrLogicalOperator::RIGHT_SHIFT
: {
315 TyTy::TyWithLocation
from (rhs
, expr
.get_rhs ()->get_locus ());
316 TyTy::TyWithLocation
to (lhs
, expr
.get_lhs ()->get_locus ());
317 infered
= cast_site (expr
.get_mappings ().get_hirid (), from
, to
,
323 infered
= unify_site (
324 expr
.get_mappings ().get_hirid (),
325 TyTy::TyWithLocation (lhs
, expr
.get_lhs ()->get_locus ()),
326 TyTy::TyWithLocation (rhs
, expr
.get_rhs ()->get_locus ()),
334 TypeCheckExpr::visit (HIR::ComparisonExpr
&expr
)
336 auto lhs
= TypeCheckExpr::Resolve (expr
.get_lhs ().get ());
337 auto rhs
= TypeCheckExpr::Resolve (expr
.get_rhs ().get ());
339 unify_site (expr
.get_mappings ().get_hirid (),
340 TyTy::TyWithLocation (lhs
, expr
.get_lhs ()->get_locus ()),
341 TyTy::TyWithLocation (rhs
, expr
.get_rhs ()->get_locus ()),
344 bool ok
= context
->lookup_builtin ("bool", &infered
);
349 TypeCheckExpr::visit (HIR::LazyBooleanExpr
&expr
)
351 auto lhs
= TypeCheckExpr::Resolve (expr
.get_lhs ().get ());
352 auto rhs
= TypeCheckExpr::Resolve (expr
.get_rhs ().get ());
354 // we expect the lhs and rhs must be bools at this point
355 TyTy::BaseType
*boolean_node
= nullptr;
356 bool ok
= context
->lookup_builtin ("bool", &boolean_node
);
359 // verify the lhs and rhs before unifying together
360 lhs
= unify_site (expr
.get_mappings ().get_hirid (),
361 TyTy::TyWithLocation (boolean_node
,
362 expr
.get_lhs ()->get_locus ()),
363 TyTy::TyWithLocation (lhs
, expr
.get_lhs ()->get_locus ()),
366 rhs
= unify_site (expr
.get_mappings ().get_hirid (),
367 TyTy::TyWithLocation (boolean_node
,
368 expr
.get_rhs ()->get_locus ()),
369 TyTy::TyWithLocation (rhs
, expr
.get_rhs ()->get_locus ()),
373 = unify_site (expr
.get_mappings ().get_hirid (),
374 TyTy::TyWithLocation (lhs
, expr
.get_lhs ()->get_locus ()),
375 TyTy::TyWithLocation (rhs
, expr
.get_rhs ()->get_locus ()),
380 TypeCheckExpr::visit (HIR::NegationExpr
&expr
)
382 auto negated_expr_ty
= TypeCheckExpr::Resolve (expr
.get_expr ().get ());
384 // check for operator overload
386 = LangItem::NegationOperatorToLangItem (expr
.get_expr_type ());
387 bool operator_overloaded
388 = resolve_operator_overload (lang_item_type
, expr
, negated_expr_ty
,
390 if (operator_overloaded
)
393 // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators
394 switch (expr
.get_expr_type ())
396 case NegationOperator::NEGATE
: {
398 = (negated_expr_ty
->get_kind () == TyTy::TypeKind::INT
)
399 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::UINT
)
400 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::FLOAT
)
401 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::ISIZE
)
402 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::USIZE
)
403 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::INFER
404 && (((TyTy::InferType
*) negated_expr_ty
)->get_infer_kind ()
405 == TyTy::InferType::INTEGRAL
))
406 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::INFER
407 && (((TyTy::InferType
*) negated_expr_ty
)->get_infer_kind ()
408 == TyTy::InferType::FLOAT
));
411 rust_error_at (expr
.get_locus (), "cannot apply unary - to %s",
412 negated_expr_ty
->as_string ().c_str ());
418 case NegationOperator::NOT
: {
420 = (negated_expr_ty
->get_kind () == TyTy::TypeKind::BOOL
)
421 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::INT
)
422 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::UINT
)
423 || (negated_expr_ty
->get_kind () == TyTy::TypeKind::INFER
424 && (((TyTy::InferType
*) negated_expr_ty
)->get_infer_kind ()
425 == TyTy::InferType::INTEGRAL
));
428 rust_error_at (expr
.get_locus (), "cannot apply unary %<!%> to %s",
429 negated_expr_ty
->as_string ().c_str ());
436 infered
= negated_expr_ty
->clone ();
437 infered
->append_reference (negated_expr_ty
->get_ref ());
441 TypeCheckExpr::visit (HIR::IfExpr
&expr
)
443 TyTy::BaseType
*bool_ty
= nullptr;
444 bool ok
= context
->lookup_builtin ("bool", &bool_ty
);
447 TyTy::BaseType
*cond_type
448 = TypeCheckExpr::Resolve (expr
.get_if_condition ().get ());
450 unify_site (expr
.get_mappings ().get_hirid (), TyTy::TyWithLocation (bool_ty
),
451 TyTy::TyWithLocation (cond_type
,
452 expr
.get_if_condition ()->get_locus ()),
455 TypeCheckExpr::Resolve (expr
.get_if_block ().get ());
457 infered
= TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
461 TypeCheckExpr::visit (HIR::IfExprConseqElse
&expr
)
463 TyTy::BaseType
*bool_ty
= nullptr;
464 bool ok
= context
->lookup_builtin ("bool", &bool_ty
);
467 TyTy::BaseType
*cond_type
468 = TypeCheckExpr::Resolve (expr
.get_if_condition ().get ());
470 unify_site (expr
.get_mappings ().get_hirid (), TyTy::TyWithLocation (bool_ty
),
471 TyTy::TyWithLocation (cond_type
,
472 expr
.get_if_condition ()->get_locus ()),
475 auto if_blk_resolved
= TypeCheckExpr::Resolve (expr
.get_if_block ().get ());
476 auto else_blk_resolved
477 = TypeCheckExpr::Resolve (expr
.get_else_block ().get ());
479 if (if_blk_resolved
->get_kind () == TyTy::NEVER
)
480 infered
= else_blk_resolved
;
481 else if (else_blk_resolved
->get_kind () == TyTy::NEVER
)
482 infered
= if_blk_resolved
;
485 infered
= unify_site (
486 expr
.get_mappings ().get_hirid (),
487 TyTy::TyWithLocation (if_blk_resolved
,
488 expr
.get_if_block ()->get_locus ()),
489 TyTy::TyWithLocation (else_blk_resolved
,
490 expr
.get_else_block ()->get_locus ()),
496 TypeCheckExpr::visit (HIR::IfLetExpr
&expr
)
498 // this needs to perform a least upper bound coercion on the blocks and then
499 // unify the scruintee and arms
500 TyTy::BaseType
*scrutinee_tyty
501 = TypeCheckExpr::Resolve (expr
.get_scrutinee_expr ().get ());
503 for (auto &pattern
: expr
.get_patterns ())
505 TyTy::BaseType
*kase_arm_ty
506 = TypeCheckPattern::Resolve (pattern
.get (), scrutinee_tyty
);
508 unify_site (expr
.get_mappings ().get_hirid (),
509 TyTy::TyWithLocation (scrutinee_tyty
),
510 TyTy::TyWithLocation (kase_arm_ty
, pattern
->get_locus ()),
514 TypeCheckExpr::Resolve (expr
.get_if_block ().get ());
516 infered
= TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
520 TypeCheckExpr::visit (HIR::IfLetExprConseqElse
&expr
)
522 TyTy::BaseType
*scrutinee_tyty
523 = TypeCheckExpr::Resolve (expr
.get_scrutinee_expr ().get ());
525 for (auto &pattern
: expr
.get_patterns ())
527 TyTy::BaseType
*kase_arm_ty
528 = TypeCheckPattern::Resolve (pattern
.get (), scrutinee_tyty
);
530 unify_site (expr
.get_mappings ().get_hirid (),
531 TyTy::TyWithLocation (scrutinee_tyty
),
532 TyTy::TyWithLocation (kase_arm_ty
, pattern
->get_locus ()),
536 auto if_blk_resolved
= TypeCheckExpr::Resolve (expr
.get_if_block ().get ());
537 auto else_blk_resolved
538 = TypeCheckExpr::Resolve (expr
.get_else_block ().get ());
540 if (if_blk_resolved
->get_kind () == TyTy::NEVER
)
541 infered
= else_blk_resolved
;
542 else if (else_blk_resolved
->get_kind () == TyTy::NEVER
)
543 infered
= if_blk_resolved
;
546 infered
= unify_site (
547 expr
.get_mappings ().get_hirid (),
548 TyTy::TyWithLocation (if_blk_resolved
,
549 expr
.get_if_block ()->get_locus ()),
550 TyTy::TyWithLocation (else_blk_resolved
,
551 expr
.get_else_block ()->get_locus ()),
557 TypeCheckExpr::visit (HIR::UnsafeBlockExpr
&expr
)
559 infered
= TypeCheckExpr::Resolve (expr
.get_block_expr ().get ());
563 TypeCheckExpr::visit (HIR::BlockExpr
&expr
)
565 if (expr
.has_label ())
566 context
->push_new_loop_context (expr
.get_mappings ().get_hirid (),
569 for (auto &s
: expr
.get_statements ())
574 TypeCheckStmt::Resolve (s
.get ());
577 for (auto &s
: expr
.get_statements ())
582 auto resolved
= TypeCheckStmt::Resolve (s
.get ());
583 if (resolved
== nullptr)
585 rust_error_at (s
->get_locus (), "failure to resolve type");
589 if (s
->is_unit_check_needed () && !resolved
->is_unit ())
592 = TyTy::TupleType::get_unit_type (s
->get_mappings ().get_hirid ());
594 = unify_site (s
->get_mappings ().get_hirid (),
595 TyTy::TyWithLocation (unit
),
596 TyTy::TyWithLocation (resolved
), s
->get_locus ());
600 if (expr
.has_expr ())
601 infered
= TypeCheckExpr::Resolve (expr
.get_final_expr ().get ())->clone ();
602 else if (expr
.is_tail_reachable ())
604 = TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
605 else if (expr
.has_label ())
607 TyTy::BaseType
*loop_context_type
= context
->pop_loop_context ();
609 bool loop_context_type_infered
610 = (loop_context_type
->get_kind () != TyTy::TypeKind::INFER
)
611 || ((loop_context_type
->get_kind () == TyTy::TypeKind::INFER
)
612 && (((TyTy::InferType
*) loop_context_type
)->get_infer_kind ()
613 != TyTy::InferType::GENERAL
));
615 infered
= loop_context_type_infered
? loop_context_type
616 : TyTy::TupleType::get_unit_type (
617 expr
.get_mappings ().get_hirid ());
621 // FIXME this seems wrong
622 infered
= new TyTy::NeverType (expr
.get_mappings ().get_hirid ());
627 TypeCheckExpr::visit (HIR::RangeFromToExpr
&expr
)
629 auto lang_item_type
= LangItem::Kind::RANGE
;
631 DefId respective_lang_item_id
= UNKNOWN_DEFID
;
632 bool lang_item_defined
633 = mappings
->lookup_lang_item (lang_item_type
, &respective_lang_item_id
);
635 // we need to have it maybe
636 if (!lang_item_defined
)
638 rust_internal_error_at (expr
.get_locus (),
639 "unable to find relevant lang item: %s",
640 LangItem::ToString (lang_item_type
).c_str ());
644 // look it up and it _must_ be a struct definition
645 HIR::Item
*item
= mappings
->lookup_defid (respective_lang_item_id
);
646 rust_assert (item
!= nullptr);
648 TyTy::BaseType
*item_type
= nullptr;
650 = context
->lookup_type (item
->get_mappings ().get_hirid (), &item_type
);
652 rust_assert (item_type
->get_kind () == TyTy::TypeKind::ADT
);
653 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (item_type
);
655 // this is a single generic item lets assert that
656 rust_assert (adt
->get_num_substitutions () == 1);
658 // resolve the range expressions and these types must unify then we use that
659 // type to substitute into the ADT
660 TyTy::BaseType
*from_ty
661 = TypeCheckExpr::Resolve (expr
.get_from_expr ().get ());
662 TyTy::BaseType
*to_ty
= TypeCheckExpr::Resolve (expr
.get_to_expr ().get ());
664 TyTy::BaseType
*unified
= unify_site (
665 expr
.get_mappings ().get_hirid (),
666 TyTy::TyWithLocation (from_ty
, expr
.get_from_expr ()->get_locus ()),
667 TyTy::TyWithLocation (to_ty
, expr
.get_to_expr ()->get_locus ()),
671 std::vector
<TyTy::SubstitutionArg
> subst_mappings
;
672 const TyTy::SubstitutionParamMapping
*param_ref
= &adt
->get_substs ().at (0);
673 subst_mappings
.push_back (TyTy::SubstitutionArg (param_ref
, unified
));
675 TyTy::SubstitutionArgumentMappings
subst (
676 subst_mappings
, {}, adt
->get_substitution_arguments ().get_regions (),
678 infered
= SubstMapperInternal::Resolve (adt
, subst
);
682 TypeCheckExpr::visit (HIR::RangeFromExpr
&expr
)
684 auto lang_item_type
= LangItem::Kind::RANGE_FROM
;
686 DefId respective_lang_item_id
= UNKNOWN_DEFID
;
687 bool lang_item_defined
688 = mappings
->lookup_lang_item (lang_item_type
, &respective_lang_item_id
);
690 // we need to have it maybe
691 if (!lang_item_defined
)
693 rust_internal_error_at (expr
.get_locus (),
694 "unable to find relevant lang item: %s",
695 LangItem::ToString (lang_item_type
).c_str ());
699 // look it up and it _must_ be a struct definition
700 HIR::Item
*item
= mappings
->lookup_defid (respective_lang_item_id
);
701 rust_assert (item
!= nullptr);
703 TyTy::BaseType
*item_type
= nullptr;
705 = context
->lookup_type (item
->get_mappings ().get_hirid (), &item_type
);
707 rust_assert (item_type
->get_kind () == TyTy::TypeKind::ADT
);
708 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (item_type
);
710 // this is a single generic item lets assert that
711 rust_assert (adt
->get_num_substitutions () == 1);
713 // resolve the range expressions and these types must unify then we use that
714 // type to substitute into the ADT
715 TyTy::BaseType
*from_ty
716 = TypeCheckExpr::Resolve (expr
.get_from_expr ().get ());
719 std::vector
<TyTy::SubstitutionArg
> subst_mappings
;
720 const TyTy::SubstitutionParamMapping
*param_ref
= &adt
->get_substs ().at (0);
721 subst_mappings
.push_back (TyTy::SubstitutionArg (param_ref
, from_ty
));
723 TyTy::SubstitutionArgumentMappings
subst (
724 subst_mappings
, {}, adt
->get_substitution_arguments ().get_regions (),
726 infered
= SubstMapperInternal::Resolve (adt
, subst
);
730 TypeCheckExpr::visit (HIR::RangeToExpr
&expr
)
732 auto lang_item_type
= LangItem::Kind::RANGE_TO
;
734 DefId respective_lang_item_id
= UNKNOWN_DEFID
;
735 bool lang_item_defined
736 = mappings
->lookup_lang_item (lang_item_type
, &respective_lang_item_id
);
738 // we need to have it maybe
739 if (!lang_item_defined
)
741 rust_internal_error_at (expr
.get_locus (),
742 "unable to find relevant lang item: %s",
743 LangItem::ToString (lang_item_type
).c_str ());
747 // look it up and it _must_ be a struct definition
748 HIR::Item
*item
= mappings
->lookup_defid (respective_lang_item_id
);
749 rust_assert (item
!= nullptr);
751 TyTy::BaseType
*item_type
= nullptr;
753 = context
->lookup_type (item
->get_mappings ().get_hirid (), &item_type
);
755 rust_assert (item_type
->get_kind () == TyTy::TypeKind::ADT
);
756 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (item_type
);
758 // this is a single generic item lets assert that
759 rust_assert (adt
->get_num_substitutions () == 1);
761 // resolve the range expressions and these types must unify then we use that
762 // type to substitute into the ADT
763 TyTy::BaseType
*from_ty
= TypeCheckExpr::Resolve (expr
.get_to_expr ().get ());
766 std::vector
<TyTy::SubstitutionArg
> subst_mappings
;
767 const TyTy::SubstitutionParamMapping
*param_ref
= &adt
->get_substs ().at (0);
768 subst_mappings
.push_back (TyTy::SubstitutionArg (param_ref
, from_ty
));
770 TyTy::SubstitutionArgumentMappings
subst (
771 subst_mappings
, {}, adt
->get_substitution_arguments ().get_regions (),
773 infered
= SubstMapperInternal::Resolve (adt
, subst
);
777 TypeCheckExpr::visit (HIR::RangeFullExpr
&expr
)
779 auto lang_item_type
= LangItem::Kind::RANGE_FULL
;
781 DefId respective_lang_item_id
= UNKNOWN_DEFID
;
782 bool lang_item_defined
783 = mappings
->lookup_lang_item (lang_item_type
, &respective_lang_item_id
);
785 // we need to have it maybe
786 if (!lang_item_defined
)
788 rust_internal_error_at (expr
.get_locus (),
789 "unable to find relevant lang item: %s",
790 LangItem::ToString (lang_item_type
).c_str ());
794 // look it up and it _must_ be a struct definition
795 HIR::Item
*item
= mappings
->lookup_defid (respective_lang_item_id
);
796 rust_assert (item
!= nullptr);
798 TyTy::BaseType
*item_type
= nullptr;
800 = context
->lookup_type (item
->get_mappings ().get_hirid (), &item_type
);
802 rust_assert (item_type
->is_unit ());
808 TypeCheckExpr::visit (HIR::RangeFromToInclExpr
&expr
)
810 auto lang_item_type
= LangItem::Kind::RANGE_INCLUSIVE
;
812 DefId respective_lang_item_id
= UNKNOWN_DEFID
;
813 bool lang_item_defined
814 = mappings
->lookup_lang_item (lang_item_type
, &respective_lang_item_id
);
816 // we need to have it maybe
817 if (!lang_item_defined
)
819 rust_internal_error_at (expr
.get_locus (),
820 "unable to find relevant lang item: %s",
821 LangItem::ToString (lang_item_type
).c_str ());
825 // look it up and it _must_ be a struct definition
826 HIR::Item
*item
= mappings
->lookup_defid (respective_lang_item_id
);
827 rust_assert (item
!= nullptr);
829 TyTy::BaseType
*item_type
= nullptr;
831 = context
->lookup_type (item
->get_mappings ().get_hirid (), &item_type
);
833 rust_assert (item_type
->get_kind () == TyTy::TypeKind::ADT
);
834 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (item_type
);
836 // this is a single generic item lets assert that
837 rust_assert (adt
->get_num_substitutions () == 1);
839 // resolve the range expressions and these types must unify then we use that
840 // type to substitute into the ADT
841 TyTy::BaseType
*from_ty
842 = TypeCheckExpr::Resolve (expr
.get_from_expr ().get ());
843 TyTy::BaseType
*to_ty
= TypeCheckExpr::Resolve (expr
.get_to_expr ().get ());
844 TyTy::BaseType
*unified
= unify_site (
845 expr
.get_mappings ().get_hirid (),
846 TyTy::TyWithLocation (from_ty
, expr
.get_from_expr ()->get_locus ()),
847 TyTy::TyWithLocation (to_ty
, expr
.get_to_expr ()->get_locus ()),
851 std::vector
<TyTy::SubstitutionArg
> subst_mappings
;
852 const TyTy::SubstitutionParamMapping
*param_ref
= &adt
->get_substs ().at (0);
853 subst_mappings
.push_back (TyTy::SubstitutionArg (param_ref
, unified
));
855 TyTy::SubstitutionArgumentMappings
subst (
856 subst_mappings
, {}, adt
->get_substitution_arguments ().get_regions (),
858 infered
= SubstMapperInternal::Resolve (adt
, subst
);
862 TypeCheckExpr::visit (HIR::ArrayIndexExpr
&expr
)
864 auto array_expr_ty
= TypeCheckExpr::Resolve (expr
.get_array_expr ().get ());
865 if (array_expr_ty
->get_kind () == TyTy::TypeKind::ERROR
)
868 auto index_expr_ty
= TypeCheckExpr::Resolve (expr
.get_index_expr ().get ());
869 if (index_expr_ty
->get_kind () == TyTy::TypeKind::ERROR
)
872 // first attempt to use direct array index logic
873 auto direct_array_expr_ty
= array_expr_ty
;
874 if (direct_array_expr_ty
->get_kind () == TyTy::TypeKind::REF
)
876 // lets try and deref it since rust allows this
877 auto ref
= static_cast<TyTy::ReferenceType
*> (direct_array_expr_ty
);
878 auto base
= ref
->get_base ();
879 if (base
->get_kind () == TyTy::TypeKind::ARRAY
)
880 direct_array_expr_ty
= base
;
883 TyTy::BaseType
*size_ty
;
884 bool ok
= context
->lookup_builtin ("usize", &size_ty
);
887 bool maybe_simple_array_access
= index_expr_ty
->can_eq (size_ty
, false);
888 if (maybe_simple_array_access
889 && direct_array_expr_ty
->get_kind () == TyTy::TypeKind::ARRAY
)
891 unify_site (expr
.get_index_expr ()->get_mappings ().get_hirid (),
892 TyTy::TyWithLocation (size_ty
),
893 TyTy::TyWithLocation (index_expr_ty
,
894 expr
.get_index_expr ()->get_locus ()),
897 TyTy::ArrayType
*array_type
898 = static_cast<TyTy::ArrayType
*> (direct_array_expr_ty
);
899 infered
= array_type
->get_element_type ()->clone ();
903 // is this a case of core::ops::index?
904 auto lang_item_type
= LangItem::Kind::INDEX
;
905 bool operator_overloaded
906 = resolve_operator_overload (lang_item_type
, expr
, array_expr_ty
,
908 if (operator_overloaded
)
910 // index and index mut always return a reference to the element
911 TyTy::BaseType
*resolved
= infered
;
912 rust_assert (resolved
->get_kind () == TyTy::TypeKind::REF
);
913 TyTy::ReferenceType
*ref
= static_cast<TyTy::ReferenceType
*> (resolved
);
915 infered
= ref
->get_base ()->clone ();
919 // error[E0277]: the type `[{integer}]` cannot be indexed by `u32`
920 rich_location
r (line_table
, expr
.get_locus ());
921 r
.add_range (expr
.get_array_expr ()->get_locus ());
922 r
.add_range (expr
.get_index_expr ()->get_locus ());
923 rust_error_at (r
, ErrorCode::E0277
,
924 "the type %qs cannot be indexed by %qs",
925 array_expr_ty
->get_name ().c_str (),
926 index_expr_ty
->get_name ().c_str ());
930 TypeCheckExpr::visit (HIR::ArrayExpr
&expr
)
932 HIR::ArrayElems
&elements
= *expr
.get_internal_elements ();
934 HIR::Expr
*capacity_expr
= nullptr;
935 TyTy::BaseType
*element_type
= nullptr;
936 switch (elements
.get_array_expr_type ())
938 case HIR::ArrayElems::ArrayExprType::COPIED
: {
939 HIR::ArrayElemsCopied
&elems
940 = static_cast<HIR::ArrayElemsCopied
&> (elements
);
942 = TypeCheckExpr::Resolve (elems
.get_elem_to_copy ().get ());
945 = TypeCheckExpr::Resolve (elems
.get_num_copies_expr ().get ());
947 TyTy::BaseType
*expected_ty
= nullptr;
948 bool ok
= context
->lookup_builtin ("usize", &expected_ty
);
950 context
->insert_type (elems
.get_num_copies_expr ()->get_mappings (),
954 expr
.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty
),
955 TyTy::TyWithLocation (capacity_type
,
956 elems
.get_num_copies_expr ()->get_locus ()),
959 capacity_expr
= elems
.get_num_copies_expr ().get ();
963 case HIR::ArrayElems::ArrayExprType::VALUES
: {
964 HIR::ArrayElemsValues
&elems
965 = static_cast<HIR::ArrayElemsValues
&> (elements
);
967 std::vector
<TyTy::BaseType
*> types
;
968 for (auto &elem
: elems
.get_values ())
970 types
.push_back (TypeCheckExpr::Resolve (elem
.get ()));
975 = TyTy::TyVar::get_implicit_infer_var (expr
.get_locus ()).get_tyty ();
976 for (auto &type
: types
)
979 = unify_site (expr
.get_mappings ().get_hirid (),
980 TyTy::TyWithLocation (element_type
),
981 TyTy::TyWithLocation (type
, type
->get_locus ()),
985 auto crate_num
= mappings
->get_current_crate ();
986 Analysis::NodeMapping
mapping (crate_num
, UNKNOWN_NODEID
,
987 mappings
->get_next_hir_id (crate_num
),
988 UNKNOWN_LOCAL_DEFID
);
989 std::string capacity_str
= std::to_string (elems
.get_num_elements ());
990 capacity_expr
= new HIR::LiteralExpr (mapping
, capacity_str
,
991 HIR::Literal::LitType::INT
,
992 PrimitiveCoreType::CORETYPE_USIZE
,
995 // mark the type for this implicit node
996 TyTy::BaseType
*expected_ty
= nullptr;
997 bool ok
= context
->lookup_builtin ("usize", &expected_ty
);
999 context
->insert_type (mapping
, expected_ty
);
1004 infered
= new TyTy::ArrayType (expr
.get_mappings ().get_hirid (),
1005 expr
.get_locus (), *capacity_expr
,
1006 TyTy::TyVar (element_type
->get_ref ()));
1011 TypeCheckExpr::visit (HIR::StructExprStruct
&struct_expr
)
1013 TyTy::BaseType
*struct_path_ty
1014 = TypeCheckExpr::Resolve (&struct_expr
.get_struct_name ());
1015 if (struct_path_ty
->get_kind () != TyTy::TypeKind::ADT
)
1017 rust_error_at (struct_expr
.get_struct_name ().get_locus (),
1018 "expected an ADT type for constructor");
1022 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (struct_path_ty
);
1023 for (auto variant
: adt
->get_variants ())
1025 if (!variant
->get_fields ().empty ())
1027 std::vector
<std::string
> field_names
;
1028 for (auto &field
: variant
->get_fields ())
1029 field_names
.push_back (field
->get_name ());
1030 Error missing_fields_error
1031 = TypeCheckStructExpr::make_missing_field_error (
1032 struct_expr
.get_locus (), field_names
,
1033 struct_path_ty
->get_name ());
1034 // We might want to return or handle these in the future emit for now.
1035 missing_fields_error
.emit ();
1040 infered
= struct_path_ty
;
1044 TypeCheckExpr::visit (HIR::StructExprStructFields
&struct_expr
)
1046 infered
= TypeCheckStructExpr::Resolve (&struct_expr
);
1050 TypeCheckExpr::visit (HIR::GroupedExpr
&expr
)
1052 infered
= TypeCheckExpr::Resolve (expr
.get_expr_in_parens ().get ());
1056 TypeCheckExpr::visit (HIR::FieldAccessExpr
&expr
)
1058 auto struct_base
= TypeCheckExpr::Resolve (expr
.get_receiver_expr ().get ());
1060 // FIXME does this require autoderef here?
1061 if (struct_base
->get_kind () == TyTy::TypeKind::REF
)
1063 TyTy::ReferenceType
*r
= static_cast<TyTy::ReferenceType
*> (struct_base
);
1064 struct_base
= r
->get_base ();
1067 bool is_valid_type
= struct_base
->get_kind () == TyTy::TypeKind::ADT
;
1070 rust_error_at (expr
.get_locus (),
1071 "expected algebraic data type got: [%s]",
1072 struct_base
->as_string ().c_str ());
1076 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (struct_base
);
1077 rust_assert (!adt
->is_enum ());
1078 rust_assert (adt
->number_of_variants () == 1);
1080 TyTy::VariantDef
*vaiant
= adt
->get_variants ().at (0);
1082 TyTy::StructFieldType
*lookup
= nullptr;
1083 bool found
= vaiant
->lookup_field (expr
.get_field_name ().as_string (),
1087 rust_error_at (expr
.get_locus (), "unknown field [%s] for type [%s]",
1088 expr
.get_field_name ().as_string ().c_str (),
1089 adt
->as_string ().c_str ());
1093 infered
= lookup
->get_field_type ();
1097 TypeCheckExpr::visit (HIR::MethodCallExpr
&expr
)
1099 auto receiver_tyty
= TypeCheckExpr::Resolve (expr
.get_receiver ().get ());
1100 if (receiver_tyty
->get_kind () == TyTy::TypeKind::ERROR
)
1102 rust_error_at (expr
.get_receiver ()->get_locus (),
1103 "failed to resolve receiver in MethodCallExpr");
1107 context
->insert_receiver (expr
.get_mappings ().get_hirid (), receiver_tyty
);
1109 rust_debug_loc (expr
.get_locus (), "attempting to resolve method for %s",
1110 receiver_tyty
->debug_str ().c_str ());
1112 = MethodResolver::Probe (receiver_tyty
,
1113 expr
.get_method_name ().get_segment ());
1114 if (candidates
.empty ())
1116 rich_location
richloc (line_table
, expr
.get_method_name ().get_locus ());
1117 richloc
.add_fixit_replace ("method not found");
1119 richloc
, ErrorCode::E0599
,
1120 "no method named %qs found in the current scope",
1121 expr
.get_method_name ().get_segment ().as_string ().c_str ());
1125 if (candidates
.size () > 1)
1127 rich_location
r (line_table
, expr
.get_method_name ().get_locus ());
1128 std::string rich_msg
1129 = "multiple " + expr
.get_method_name ().get_segment ().as_string ()
1132 for (auto &c
: candidates
)
1133 r
.add_range (c
.candidate
.locus
);
1135 r
.add_fixit_replace (rich_msg
.c_str ());
1138 r
, ErrorCode::E0592
, "duplicate definitions with name %qs",
1139 expr
.get_method_name ().get_segment ().as_string ().c_str ());
1143 auto candidate
= *candidates
.begin ();
1144 rust_debug_loc (expr
.get_method_name ().get_locus (),
1145 "resolved method to: {%u} {%s} with [%lu] adjustments",
1146 candidate
.candidate
.ty
->get_ref (),
1147 candidate
.candidate
.ty
->debug_str ().c_str (),
1148 (unsigned long) candidate
.adjustments
.size ());
1150 // Get the adjusted self
1151 Adjuster
adj (receiver_tyty
);
1152 TyTy::BaseType
*adjusted_self
= adj
.adjust_type (candidate
.adjustments
);
1153 rust_debug ("receiver: %s adjusted self %s",
1154 receiver_tyty
->debug_str ().c_str (),
1155 adjusted_self
->debug_str ().c_str ());
1157 // store the adjustments for code-generation to know what to do which must be
1158 // stored onto the receiver to so as we don't trigger duplicate deref mappings
1159 // ICE when an argument is a method call
1160 HirId autoderef_mappings_id
1161 = expr
.get_receiver ()->get_mappings ().get_hirid ();
1162 context
->insert_autoderef_mappings (autoderef_mappings_id
,
1163 std::move (candidate
.adjustments
));
1165 PathProbeCandidate
&resolved_candidate
= candidate
.candidate
;
1166 TyTy::BaseType
*lookup_tyty
= candidate
.candidate
.ty
;
1167 NodeId resolved_node_id
1168 = resolved_candidate
.is_impl_candidate ()
1169 ? resolved_candidate
.item
.impl
.impl_item
->get_impl_mappings ()
1171 : resolved_candidate
.item
.trait
.item_ref
->get_mappings ().get_nodeid ();
1173 if (lookup_tyty
->get_kind () != TyTy::TypeKind::FNDEF
)
1175 rich_location
r (line_table
, expr
.get_method_name ().get_locus ());
1176 r
.add_range (resolved_candidate
.locus
);
1177 rust_error_at (r
, "associated impl item is not a method");
1181 TyTy::BaseType
*lookup
= lookup_tyty
;
1182 TyTy::FnType
*fn
= static_cast<TyTy::FnType
*> (lookup
);
1183 if (!fn
->is_method ())
1185 rich_location
r (line_table
, expr
.get_method_name ().get_locus ());
1186 r
.add_range (resolved_candidate
.locus
);
1187 rust_error_at (r
, "associated function is not a method");
1191 fn
->prepare_higher_ranked_bounds ();
1192 rust_debug_loc (expr
.get_locus (), "resolved method call to: {%u} {%s}",
1193 candidate
.candidate
.ty
->get_ref (),
1194 candidate
.candidate
.ty
->debug_str ().c_str ());
1196 if (resolved_candidate
.is_impl_candidate ())
1198 auto infer_arguments
= TyTy::SubstitutionArgumentMappings::empty ();
1199 infer_arguments
.get_mut_regions ()
1200 = fn
->get_used_arguments ().get_regions ();
1201 HIR::ImplBlock
&impl
= *resolved_candidate
.item
.impl
.parent
;
1202 TyTy::BaseType
*impl_self_infer
1203 = TypeCheckItem::ResolveImplBlockSelfWithInference (impl
,
1206 if (impl_self_infer
->get_kind () == TyTy::TypeKind::ERROR
)
1208 rich_location
r (line_table
, expr
.get_locus ());
1209 r
.add_range (impl
.get_type ()->get_locus ());
1211 r
, "failed to resolve impl type for method call resolution");
1215 if (!infer_arguments
.is_empty ())
1217 lookup
= SubstMapperInternal::Resolve (lookup
, infer_arguments
);
1222 // apply any remaining generic arguments
1223 if (expr
.get_method_name ().has_generic_args ())
1225 HIR::GenericArgs
&args
= expr
.get_method_name ().get_generic_args ();
1226 rust_debug_loc (args
.get_locus (),
1227 "applying generic arguments to method_call: {%s}",
1228 lookup
->debug_str ().c_str ());
1231 = SubstMapper::Resolve (lookup
, expr
.get_method_name ().get_locus (),
1233 if (lookup
->get_kind () == TyTy::TypeKind::ERROR
)
1236 else if (lookup
->needs_generic_substitutions ())
1238 rust_debug ("method needs inference: {%s}",
1239 lookup
->debug_str ().c_str ());
1240 lookup
= SubstMapper::InferSubst (lookup
,
1241 expr
.get_method_name ().get_locus ());
1244 rust_debug ("type-checking method_call: {%s}", lookup
->debug_str ().c_str ());
1246 TyTy::BaseType
*function_ret_tyty
1247 = TyTy::TypeCheckMethodCallExpr::go (static_cast<TyTy::FnType
*> (lookup
),
1248 expr
, adjusted_self
, context
);
1249 if (function_ret_tyty
== nullptr
1250 || function_ret_tyty
->get_kind () == TyTy::TypeKind::ERROR
)
1252 rust_error_at (expr
.get_locus (),
1253 "failed to lookup type to MethodCallExpr");
1257 // store the expected fntype
1258 context
->insert_type (expr
.get_method_name ().get_mappings (), lookup
);
1260 // set up the resolved name on the path
1261 if (resolver
->get_name_scope ().decl_was_declared_here (resolved_node_id
))
1263 resolver
->insert_resolved_name (expr
.get_mappings ().get_nodeid (),
1268 resolver
->insert_resolved_misc (expr
.get_mappings ().get_nodeid (),
1272 // return the result of the function back
1273 infered
= function_ret_tyty
;
1277 TypeCheckExpr::visit (HIR::LoopExpr
&expr
)
1279 context
->push_new_loop_context (expr
.get_mappings ().get_hirid (),
1281 TyTy::BaseType
*block_expr
1282 = TypeCheckExpr::Resolve (expr
.get_loop_block ().get ());
1283 if (!block_expr
->is_unit ())
1285 rust_error_at (expr
.get_loop_block ()->get_locus (),
1286 "expected %<()%> got %s",
1287 block_expr
->as_string ().c_str ());
1291 TyTy::BaseType
*loop_context_type
= context
->pop_loop_context ();
1293 bool loop_context_type_infered
1294 = (loop_context_type
->get_kind () != TyTy::TypeKind::INFER
)
1295 || ((loop_context_type
->get_kind () == TyTy::TypeKind::INFER
)
1296 && (((TyTy::InferType
*) loop_context_type
)->get_infer_kind ()
1297 != TyTy::InferType::GENERAL
));
1300 = loop_context_type_infered
1302 : TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
1306 TypeCheckExpr::visit (HIR::WhileLoopExpr
&expr
)
1308 context
->push_new_while_loop_context (expr
.get_mappings ().get_hirid ());
1310 TypeCheckExpr::Resolve (expr
.get_predicate_expr ().get ());
1311 TyTy::BaseType
*block_expr
1312 = TypeCheckExpr::Resolve (expr
.get_loop_block ().get ());
1314 if (!block_expr
->is_unit ())
1316 rust_error_at (expr
.get_loop_block ()->get_locus (),
1317 "expected %<()%> got %s",
1318 block_expr
->as_string ().c_str ());
1322 context
->pop_loop_context ();
1323 infered
= TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
1327 TypeCheckExpr::visit (HIR::BreakExpr
&expr
)
1329 if (!context
->have_loop_context ())
1331 rust_error_at (expr
.get_locus (), ErrorCode::E0268
,
1332 "%<break%> outside of a loop or labeled block");
1336 if (expr
.has_break_expr ())
1338 TyTy::BaseType
*break_expr_tyty
1339 = TypeCheckExpr::Resolve (expr
.get_expr ().get ());
1341 TyTy::BaseType
*loop_context
= context
->peek_loop_context ();
1342 if (loop_context
->get_kind () == TyTy::TypeKind::ERROR
)
1345 expr
.get_locus (), ErrorCode::E0571
,
1346 "can only %<break%> with a value inside a %<loop%> block");
1350 TyTy::BaseType
*unified_ty
1351 = unify_site (expr
.get_mappings ().get_hirid (),
1352 TyTy::TyWithLocation (loop_context
),
1353 TyTy::TyWithLocation (break_expr_tyty
,
1354 expr
.get_expr ()->get_locus ()),
1356 context
->swap_head_loop_context (unified_ty
);
1359 infered
= new TyTy::NeverType (expr
.get_mappings ().get_hirid ());
1363 TypeCheckExpr::visit (HIR::ContinueExpr
&expr
)
1365 if (!context
->have_loop_context ())
1367 rust_error_at (expr
.get_locus (), ErrorCode::E0268
,
1368 "%<continue%> outside of a loop");
1372 infered
= new TyTy::NeverType (expr
.get_mappings ().get_hirid ());
1376 TypeCheckExpr::visit (HIR::BorrowExpr
&expr
)
1378 TyTy::BaseType
*resolved_base
1379 = TypeCheckExpr::Resolve (expr
.get_expr ().get ());
1381 // In Rust this is valid because of DST's
1384 // let a:&str = "TEST 1";
1385 // let b:&str = &"TEST 2";
1387 if (resolved_base
->get_kind () == TyTy::TypeKind::REF
)
1389 const TyTy::ReferenceType
*ref
1390 = static_cast<const TyTy::ReferenceType
*> (resolved_base
);
1392 // this might end up being a more generic is_dyn object check but lets
1393 // double check dyn traits type-layout first
1394 if (ref
->is_dyn_str_type ())
1396 infered
= resolved_base
;
1401 infered
= new TyTy::ReferenceType (expr
.get_mappings ().get_hirid (),
1402 TyTy::TyVar (resolved_base
->get_ref ()),
1407 TypeCheckExpr::visit (HIR::DereferenceExpr
&expr
)
1409 TyTy::BaseType
*resolved_base
1410 = TypeCheckExpr::Resolve (expr
.get_expr ().get ());
1412 rust_debug_loc (expr
.get_locus (), "attempting deref operator overload");
1413 auto lang_item_type
= LangItem::Kind::DEREF
;
1414 bool operator_overloaded
1415 = resolve_operator_overload (lang_item_type
, expr
, resolved_base
, nullptr);
1416 if (operator_overloaded
)
1418 // operator overloaded deref always refurns a reference type lets assert
1420 rust_assert (infered
->get_kind () == TyTy::TypeKind::REF
);
1421 resolved_base
= infered
;
1424 bool is_valid_type
= resolved_base
->get_kind () == TyTy::TypeKind::REF
1425 || resolved_base
->get_kind () == TyTy::TypeKind::POINTER
;
1428 rust_error_at (expr
.get_locus (), "expected reference type got %s",
1429 resolved_base
->as_string ().c_str ());
1433 if (resolved_base
->get_kind () == TyTy::TypeKind::REF
)
1435 TyTy::ReferenceType
*ref_base
1436 = static_cast<TyTy::ReferenceType
*> (resolved_base
);
1437 infered
= ref_base
->get_base ()->clone ();
1441 TyTy::PointerType
*ref_base
1442 = static_cast<TyTy::PointerType
*> (resolved_base
);
1443 infered
= ref_base
->get_base ()->clone ();
1448 TypeCheckExpr::visit (HIR::TypeCastExpr
&expr
)
1450 TyTy::BaseType
*expr_to_convert
1451 = TypeCheckExpr::Resolve (expr
.get_casted_expr ().get ());
1452 TyTy::BaseType
*tyty_to_convert_to
1453 = TypeCheckType::Resolve (expr
.get_type_to_convert_to ().get ());
1455 TyTy::TyWithLocation
from (expr_to_convert
,
1456 expr
.get_casted_expr ()->get_locus ());
1457 TyTy::TyWithLocation
to (tyty_to_convert_to
,
1458 expr
.get_type_to_convert_to ()->get_locus ());
1459 infered
= cast_site (expr
.get_mappings ().get_hirid (), from
, to
,
1464 TypeCheckExpr::visit (HIR::MatchExpr
&expr
)
1466 // this needs to perform a least upper bound coercion on the blocks and then
1467 // unify the scruintee and arms
1468 TyTy::BaseType
*scrutinee_tyty
1469 = TypeCheckExpr::Resolve (expr
.get_scrutinee_expr ().get ());
1471 std::vector
<TyTy::BaseType
*> kase_block_tys
;
1472 for (auto &kase
: expr
.get_match_cases ())
1474 // lets check the arms
1475 HIR::MatchArm
&kase_arm
= kase
.get_arm ();
1476 for (auto &pattern
: kase_arm
.get_patterns ())
1478 TyTy::BaseType
*kase_arm_ty
1479 = TypeCheckPattern::Resolve (pattern
.get (), scrutinee_tyty
);
1480 if (kase_arm_ty
->get_kind () == TyTy ::TypeKind::ERROR
)
1483 TyTy::BaseType
*checked_kase
= unify_site (
1484 expr
.get_mappings ().get_hirid (),
1485 TyTy::TyWithLocation (scrutinee_tyty
,
1486 expr
.get_scrutinee_expr ()->get_locus ()),
1487 TyTy::TyWithLocation (kase_arm_ty
, pattern
->get_locus ()),
1489 if (checked_kase
->get_kind () == TyTy::TypeKind::ERROR
)
1493 // check the kase type
1494 TyTy::BaseType
*kase_block_ty
1495 = TypeCheckExpr::Resolve (kase
.get_expr ().get ());
1496 kase_block_tys
.push_back (kase_block_ty
);
1499 if (kase_block_tys
.size () == 0)
1502 = TyTy::TupleType::get_unit_type (expr
.get_mappings ().get_hirid ());
1507 infered
= kase_block_tys
.at (0);
1508 for (size_t i
= 1; i
< kase_block_tys
.size (); i
++)
1510 TyTy::BaseType
*kase_ty
= kase_block_tys
.at (i
);
1511 infered
= unify_site (expr
.get_mappings ().get_hirid (),
1512 TyTy::TyWithLocation (infered
),
1513 TyTy::TyWithLocation (kase_ty
), expr
.get_locus ());
1518 TypeCheckExpr::visit (HIR::ClosureExpr
&expr
)
1520 TypeCheckContextItem current_context
= context
->peek_context ();
1521 TyTy::FnType
*current_context_fndecl
= current_context
.get_context_type ();
1523 HirId ref
= expr
.get_mappings ().get_hirid ();
1524 DefId id
= expr
.get_mappings ().get_defid ();
1525 RustIdent ident
{current_context_fndecl
->get_ident ().path
, expr
.get_locus ()};
1527 // get from parent context
1528 std::vector
<TyTy::SubstitutionParamMapping
> subst_refs
1529 = current_context_fndecl
->clone_substs ();
1531 std::vector
<TyTy::TyVar
> parameter_types
;
1532 for (auto &p
: expr
.get_params ())
1534 TyTy::BaseType
*param_tyty
= nullptr;
1535 if (p
.has_type_given ())
1537 param_tyty
= TypeCheckType::Resolve (p
.get_type ().get ());
1541 param_tyty
= ClosureParamInfer::Resolve (p
.get_pattern ().get ());
1544 TyTy::TyVar
param_ty (param_tyty
->get_ref ());
1545 parameter_types
.push_back (param_ty
);
1547 TypeCheckPattern::Resolve (p
.get_pattern ().get (), param_ty
.get_tyty ());
1550 // we generate an implicit hirid for the closure args
1551 HirId implicit_args_id
= mappings
->get_next_hir_id ();
1552 TyTy::TupleType
*closure_args
1553 = new TyTy::TupleType (implicit_args_id
, expr
.get_locus (),
1555 context
->insert_implicit_type (closure_args
);
1557 location_t result_type_locus
= expr
.has_return_type ()
1558 ? expr
.get_return_type ()->get_locus ()
1559 : expr
.get_locus ();
1560 TyTy::TyVar result_type
1561 = expr
.has_return_type ()
1563 TypeCheckType::Resolve (expr
.get_return_type ().get ())->get_ref ())
1564 : TyTy::TyVar::get_implicit_infer_var (expr
.get_locus ());
1566 // resolve the block
1567 location_t closure_expr_locus
= expr
.get_expr ()->get_locus ();
1568 TyTy::BaseType
*closure_expr_ty
1569 = TypeCheckExpr::Resolve (expr
.get_expr ().get ());
1570 coercion_site (expr
.get_mappings ().get_hirid (),
1571 TyTy::TyWithLocation (result_type
.get_tyty (),
1573 TyTy::TyWithLocation (closure_expr_ty
, closure_expr_locus
),
1576 // generate the closure type
1577 NodeId closure_node_id
= expr
.get_mappings ().get_nodeid ();
1578 const std::set
<NodeId
> &captures
= resolver
->get_captures (closure_node_id
);
1579 infered
= new TyTy::ClosureType (ref
, id
, ident
, closure_args
, result_type
,
1580 subst_refs
, captures
);
1583 // all closures automatically inherit the appropriate fn trait. Lets just
1584 // assume FnOnce for now. I think this is based on the return type of the
1587 LangItem::Kind lang_item_type
= LangItem::Kind::FN_ONCE
;
1588 DefId respective_lang_item_id
= UNKNOWN_DEFID
;
1589 bool lang_item_defined
1590 = mappings
->lookup_lang_item (lang_item_type
, &respective_lang_item_id
);
1591 if (!lang_item_defined
)
1594 // we need to have a unified way or error'ing when we are missing lang
1595 // items that is useful
1596 rust_fatal_error (expr
.get_locus (), "unable to find lang item: %qs",
1597 LangItem::ToString (lang_item_type
).c_str ());
1599 rust_assert (lang_item_defined
);
1601 // these lang items are always traits
1602 HIR::Item
*item
= mappings
->lookup_defid (respective_lang_item_id
);
1603 rust_assert (item
->get_item_kind () == HIR::Item::ItemKind::Trait
);
1604 HIR::Trait
*trait_item
= static_cast<HIR::Trait
*> (item
);
1606 TraitReference
*trait
= TraitResolver::Resolve (*trait_item
);
1607 rust_assert (!trait
->is_error ());
1609 TyTy::TypeBoundPredicate
predicate (*trait
, BoundPolarity::RegularBound
,
1612 // resolve the trait bound where the <(Args)> are the parameter tuple type
1613 HIR::GenericArgs args
= HIR::GenericArgs::create_empty (expr
.get_locus ());
1615 // lets generate an implicit Type so that it resolves to the implict tuple
1616 // type we have created
1617 auto crate_num
= mappings
->get_current_crate ();
1618 Analysis::NodeMapping
mapping (crate_num
, expr
.get_mappings ().get_nodeid (),
1619 implicit_args_id
, UNKNOWN_LOCAL_DEFID
);
1620 HIR::TupleType
*implicit_tuple
1621 = new HIR::TupleType (mapping
,
1622 {} // we dont need to fill this out because it will
1623 // auto resolve because the hir id's match
1626 args
.get_type_args ().push_back (std::unique_ptr
<HIR::Type
> (implicit_tuple
));
1628 // apply the arguments
1629 predicate
.apply_generic_arguments (&args
, false);
1631 // finally inherit the trait bound
1632 infered
->inherit_bounds ({predicate
});
1636 TypeCheckExpr::resolve_operator_overload (LangItem::Kind lang_item_type
,
1637 HIR::OperatorExprMeta expr
,
1638 TyTy::BaseType
*lhs
,
1639 TyTy::BaseType
*rhs
)
1641 // look up lang item for arithmetic type
1642 std::string associated_item_name
= LangItem::ToString (lang_item_type
);
1643 DefId respective_lang_item_id
= UNKNOWN_DEFID
;
1644 bool lang_item_defined
1645 = mappings
->lookup_lang_item (lang_item_type
, &respective_lang_item_id
);
1647 // probe for the lang-item
1648 if (!lang_item_defined
)
1651 // we might be in a static or const context and unknown is fine
1652 TypeCheckContextItem current_context
= TypeCheckContextItem::get_error ();
1653 if (context
->have_function_context ())
1655 current_context
= context
->peek_context ();
1658 auto segment
= HIR::PathIdentSegment (associated_item_name
);
1659 auto candidates
= MethodResolver::Probe (lhs
, segment
);
1661 // remove any recursive candidates
1662 std::set
<MethodCandidate
> resolved_candidates
;
1663 for (auto &c
: candidates
)
1665 const TyTy::BaseType
*candidate_type
= c
.candidate
.ty
;
1666 rust_assert (candidate_type
->get_kind () == TyTy::TypeKind::FNDEF
);
1668 const TyTy::FnType
&fn
1669 = *static_cast<const TyTy::FnType
*> (candidate_type
);
1671 DefId current_fn_defid
= current_context
.get_defid ();
1672 bool recursive_candidated
= fn
.get_id () == current_fn_defid
;
1673 if (!recursive_candidated
)
1675 resolved_candidates
.insert (c
);
1679 std::vector
<TyTy::BaseType
*> select_args
= {};
1681 select_args
= {rhs
};
1682 auto selected_candidates
1683 = MethodResolver::Select (resolved_candidates
, lhs
, select_args
);
1685 bool have_implementation_for_lang_item
= selected_candidates
.size () > 0;
1686 if (!have_implementation_for_lang_item
)
1689 if (selected_candidates
.size () > 1)
1691 // mutliple candidates
1692 rich_location
r (line_table
, expr
.get_locus ());
1693 for (auto &c
: resolved_candidates
)
1694 r
.add_range (c
.candidate
.locus
);
1697 r
, "multiple candidates found for possible operator overload");
1702 // Get the adjusted self
1703 MethodCandidate candidate
= *selected_candidates
.begin ();
1705 TyTy::BaseType
*adjusted_self
= adj
.adjust_type (candidate
.adjustments
);
1707 // store the adjustments for code-generation to know what to do
1708 context
->insert_autoderef_mappings (expr
.get_lvalue_mappings ().get_hirid (),
1709 std::move (candidate
.adjustments
));
1711 // now its just like a method-call-expr
1712 context
->insert_receiver (expr
.get_mappings ().get_hirid (), lhs
);
1714 PathProbeCandidate
&resolved_candidate
= candidate
.candidate
;
1715 TyTy::BaseType
*lookup_tyty
= candidate
.candidate
.ty
;
1716 NodeId resolved_node_id
1717 = resolved_candidate
.is_impl_candidate ()
1718 ? resolved_candidate
.item
.impl
.impl_item
->get_impl_mappings ()
1720 : resolved_candidate
.item
.trait
.item_ref
->get_mappings ().get_nodeid ();
1722 rust_assert (lookup_tyty
->get_kind () == TyTy::TypeKind::FNDEF
);
1723 TyTy::BaseType
*lookup
= lookup_tyty
;
1724 TyTy::FnType
*fn
= static_cast<TyTy::FnType
*> (lookup
);
1725 rust_assert (fn
->is_method ());
1727 rust_debug ("is_impl_item_candidate: %s",
1728 resolved_candidate
.is_impl_candidate () ? "true" : "false");
1730 if (resolved_candidate
.is_impl_candidate ())
1732 auto infer_arguments
= TyTy::SubstitutionArgumentMappings::error ();
1733 HIR::ImplBlock
&impl
= *resolved_candidate
.item
.impl
.parent
;
1734 TyTy::BaseType
*impl_self_infer
1735 = TypeCheckItem::ResolveImplBlockSelfWithInference (impl
,
1738 if (impl_self_infer
->get_kind () == TyTy::TypeKind::ERROR
)
1742 if (!infer_arguments
.is_empty ())
1744 lookup
= SubstMapperInternal::Resolve (lookup
, infer_arguments
);
1748 // in the case where we resolve to a trait bound we have to be careful we are
1749 // able to do so there is a case where we are currently resolving the deref
1750 // operator overload function which is generic and this might resolve to the
1751 // trait item of deref which is not valid as its just another recursive case
1752 if (current_context
.get_type () == TypeCheckContextItem::ItemType::IMPL_ITEM
)
1754 auto &impl_item
= current_context
.get_impl_item ();
1755 HIR::ImplBlock
*parent
= impl_item
.first
;
1756 HIR::Function
*fn
= impl_item
.second
;
1758 if (parent
->has_trait_ref ()
1759 && fn
->get_function_name ().as_string ().compare (
1760 associated_item_name
)
1763 TraitReference
*trait_reference
1764 = TraitResolver::Lookup (*parent
->get_trait_ref ().get ());
1765 if (!trait_reference
->is_error ())
1767 TyTy::BaseType
*lookup
= nullptr;
1768 bool ok
= context
->lookup_type (fn
->get_mappings ().get_hirid (),
1771 rust_assert (lookup
->get_kind () == TyTy::TypeKind::FNDEF
);
1773 TyTy::FnType
*fntype
= static_cast<TyTy::FnType
*> (lookup
);
1774 rust_assert (fntype
->is_method ());
1776 bool is_lang_item_impl
1777 = trait_reference
->get_mappings ().get_defid ()
1778 == respective_lang_item_id
;
1779 bool self_is_lang_item_self
1780 = fntype
->get_self_type ()->is_equal (*adjusted_self
);
1781 bool recursive_operator_overload
1782 = is_lang_item_impl
&& self_is_lang_item_self
;
1784 if (recursive_operator_overload
)
1790 // we found a valid operator overload
1791 fn
->prepare_higher_ranked_bounds ();
1792 rust_debug_loc (expr
.get_locus (), "resolved operator overload to: {%u} {%s}",
1793 candidate
.candidate
.ty
->get_ref (),
1794 candidate
.candidate
.ty
->debug_str ().c_str ());
1797 if (lookup
->needs_generic_substitutions ())
1798 lookup
= SubstMapper::InferSubst (lookup
, expr
.get_locus ());
1800 // type check the arguments if required
1801 TyTy::FnType
*type
= static_cast<TyTy::FnType
*> (lookup
);
1802 rust_assert (type
->num_params () > 0);
1803 auto fnparam
= type
->param_at (0);
1805 // typecheck the self
1806 unify_site (expr
.get_mappings ().get_hirid (),
1807 TyTy::TyWithLocation (fnparam
.second
),
1808 TyTy::TyWithLocation (adjusted_self
), expr
.get_locus ());
1811 rust_assert (type
->num_params () == 1);
1815 rust_assert (type
->num_params () == 2);
1816 auto fnparam
= type
->param_at (1);
1817 unify_site (expr
.get_mappings ().get_hirid (),
1818 TyTy::TyWithLocation (fnparam
.second
),
1819 TyTy::TyWithLocation (rhs
), expr
.get_locus ());
1822 rust_assert (lookup
->get_kind () == TyTy::TypeKind::FNDEF
);
1823 fn
= static_cast<TyTy::FnType
*> (lookup
);
1824 fn
->monomorphize ();
1826 // get the return type
1827 TyTy::BaseType
*function_ret_tyty
1828 = type
->get_return_type ()->monomorphized_clone ();
1830 // store the expected fntype
1831 context
->insert_operator_overload (expr
.get_mappings ().get_hirid (), type
);
1833 // set up the resolved name on the path
1834 resolver
->insert_resolved_name (expr
.get_mappings ().get_nodeid (),
1837 // return the result of the function back
1838 infered
= function_ret_tyty
;
1843 HIR::PathIdentSegment
1844 TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
1845 TyTy::BaseType
&receiver
, TyTy::TypeBoundPredicate
*associated_predicate
)
1848 // do we need to probe possible bounds here? I think not, i think when we
1849 // support Fn traits they are explicitly specified
1852 // the logic to map the FnTrait to their respective call trait-item is
1853 // duplicated over in the backend/rust-compile-expr.cc
1854 for (auto &bound
: receiver
.get_specified_bounds ())
1856 bool found_fn
= bound
.get_name ().compare ("Fn") == 0;
1857 bool found_fn_mut
= bound
.get_name ().compare ("FnMut") == 0;
1858 bool found_fn_once
= bound
.get_name ().compare ("FnOnce") == 0;
1862 *associated_predicate
= bound
;
1863 return HIR::PathIdentSegment ("call");
1865 else if (found_fn_mut
)
1867 *associated_predicate
= bound
;
1868 return HIR::PathIdentSegment ("call_mut");
1870 else if (found_fn_once
)
1872 *associated_predicate
= bound
;
1873 return HIR::PathIdentSegment ("call_once");
1878 *associated_predicate
= TyTy::TypeBoundPredicate::error ();
1879 return HIR::PathIdentSegment ("");
1883 TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr
&expr
,
1884 TyTy::BaseType
*receiver_tyty
,
1885 TyTy::BaseType
**result
)
1887 // we turn this into a method call expr
1888 // TODO: add implicit self argument (?)
1889 auto associated_predicate
= TyTy::TypeBoundPredicate::error ();
1890 HIR::PathIdentSegment method_name
1891 = resolve_possible_fn_trait_call_method_name (*receiver_tyty
,
1892 &associated_predicate
);
1893 if (method_name
.is_error () || associated_predicate
.is_error ())
1896 auto candidates
= MethodResolver::Probe (receiver_tyty
, method_name
);
1897 if (candidates
.empty ())
1900 if (candidates
.size () > 1)
1902 rich_location
r (line_table
, expr
.get_locus ());
1903 for (auto &c
: candidates
)
1904 r
.add_range (c
.candidate
.locus
);
1907 r
, "multiple candidates found for function trait method call %qs",
1908 method_name
.as_string ().c_str ());
1912 if (receiver_tyty
->get_kind () == TyTy::TypeKind::CLOSURE
)
1914 const TyTy::ClosureType
&closure
1915 = static_cast<TyTy::ClosureType
&> (*receiver_tyty
);
1916 closure
.setup_fn_once_output ();
1919 auto candidate
= *candidates
.begin ();
1920 rust_debug_loc (expr
.get_locus (),
1921 "resolved call-expr to fn trait: {%u} {%s}",
1922 candidate
.candidate
.ty
->get_ref (),
1923 candidate
.candidate
.ty
->debug_str ().c_str ());
1925 // Get the adjusted self
1926 Adjuster
adj (receiver_tyty
);
1927 TyTy::BaseType
*adjusted_self
= adj
.adjust_type (candidate
.adjustments
);
1929 // store the adjustments for code-generation to know what to do which must be
1930 // stored onto the receiver to so as we don't trigger duplicate deref mappings
1931 // ICE when an argument is a method call
1932 HIR::Expr
*fnexpr
= expr
.get_fnexpr ().get ();
1933 HirId autoderef_mappings_id
= fnexpr
->get_mappings ().get_hirid ();
1934 context
->insert_autoderef_mappings (autoderef_mappings_id
,
1935 std::move (candidate
.adjustments
));
1936 context
->insert_receiver (expr
.get_mappings ().get_hirid (), receiver_tyty
);
1938 PathProbeCandidate
&resolved_candidate
= candidate
.candidate
;
1939 TyTy::BaseType
*lookup_tyty
= candidate
.candidate
.ty
;
1940 NodeId resolved_node_id
1941 = resolved_candidate
.is_impl_candidate ()
1942 ? resolved_candidate
.item
.impl
.impl_item
->get_impl_mappings ()
1944 : resolved_candidate
.item
.trait
.item_ref
->get_mappings ().get_nodeid ();
1946 if (lookup_tyty
->get_kind () != TyTy::TypeKind::FNDEF
)
1948 rich_location
r (line_table
, expr
.get_locus ());
1949 r
.add_range (resolved_candidate
.locus
);
1950 rust_error_at (r
, "associated impl item is not a method");
1954 TyTy::BaseType
*lookup
= lookup_tyty
;
1955 TyTy::FnType
*fn
= static_cast<TyTy::FnType
*> (lookup
);
1956 if (!fn
->is_method ())
1958 rich_location
r (line_table
, expr
.get_locus ());
1959 r
.add_range (resolved_candidate
.locus
);
1960 rust_error_at (r
, "associated function is not a method");
1964 // fn traits only support tuple argument passing so we need to implicitly set
1965 // this up to get the same type checking we get in the rest of the pipeline
1967 std::vector
<TyTy::TyVar
> call_args
;
1968 for (auto &arg
: expr
.get_arguments ())
1970 TyTy::BaseType
*a
= TypeCheckExpr::Resolve (arg
.get ());
1971 call_args
.push_back (TyTy::TyVar (a
->get_ref ()));
1974 // crate implicit tuple
1975 HirId implicit_arg_id
= mappings
->get_next_hir_id ();
1976 Analysis::NodeMapping
mapping (mappings
->get_current_crate (), UNKNOWN_NODEID
,
1977 implicit_arg_id
, UNKNOWN_LOCAL_DEFID
);
1979 TyTy::TupleType
*tuple
1980 = new TyTy::TupleType (implicit_arg_id
, expr
.get_locus (), call_args
);
1981 context
->insert_implicit_type (implicit_arg_id
, tuple
);
1983 std::vector
<TyTy::Argument
> args
;
1984 TyTy::Argument
a (mapping
, tuple
,
1985 expr
.get_locus () /*FIXME is there a better location*/);
1986 args
.push_back (std::move (a
));
1988 TyTy::BaseType
*function_ret_tyty
1989 = TyTy::TypeCheckMethodCallExpr::go (fn
, expr
.get_mappings (), args
,
1990 expr
.get_locus (), expr
.get_locus (),
1991 adjusted_self
, context
);
1992 if (function_ret_tyty
== nullptr
1993 || function_ret_tyty
->get_kind () == TyTy::TypeKind::ERROR
)
1995 rust_error_at (expr
.get_locus (),
1996 "failed check fn trait call-expr MethodCallExpr");
2000 // store the expected fntype
2001 context
->insert_operator_overload (expr
.get_mappings ().get_hirid (), fn
);
2003 // set up the resolved name on the path
2004 resolver
->insert_resolved_name (expr
.get_mappings ().get_nodeid (),
2007 // return the result of the function back
2008 *result
= function_ret_tyty
;
2014 TypeCheckExpr::validate_arithmetic_type (
2015 const TyTy::BaseType
*tyty
, HIR::ArithmeticOrLogicalExpr::ExprType expr_type
)
2017 const TyTy::BaseType
*type
= tyty
->destructure ();
2019 // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators
2020 // this will change later when traits are added
2023 case ArithmeticOrLogicalOperator::ADD
:
2024 case ArithmeticOrLogicalOperator::SUBTRACT
:
2025 case ArithmeticOrLogicalOperator::MULTIPLY
:
2026 case ArithmeticOrLogicalOperator::DIVIDE
:
2027 case ArithmeticOrLogicalOperator::MODULUS
:
2028 return (type
->get_kind () == TyTy::TypeKind::INT
)
2029 || (type
->get_kind () == TyTy::TypeKind::UINT
)
2030 || (type
->get_kind () == TyTy::TypeKind::FLOAT
)
2031 || (type
->get_kind () == TyTy::TypeKind::USIZE
)
2032 || (type
->get_kind () == TyTy::TypeKind::ISIZE
)
2033 || (type
->get_kind () == TyTy::TypeKind::INFER
2034 && (((const TyTy::InferType
*) type
)->get_infer_kind ()
2035 == TyTy::InferType::INTEGRAL
))
2036 || (type
->get_kind () == TyTy::TypeKind::INFER
2037 && (((const TyTy::InferType
*) type
)->get_infer_kind ()
2038 == TyTy::InferType::FLOAT
));
2040 // integers or bools
2041 case ArithmeticOrLogicalOperator::BITWISE_AND
:
2042 case ArithmeticOrLogicalOperator::BITWISE_OR
:
2043 case ArithmeticOrLogicalOperator::BITWISE_XOR
:
2044 return (type
->get_kind () == TyTy::TypeKind::INT
)
2045 || (type
->get_kind () == TyTy::TypeKind::UINT
)
2046 || (type
->get_kind () == TyTy::TypeKind::USIZE
)
2047 || (type
->get_kind () == TyTy::TypeKind::ISIZE
)
2048 || (type
->get_kind () == TyTy::TypeKind::BOOL
)
2049 || (type
->get_kind () == TyTy::TypeKind::INFER
2050 && (((const TyTy::InferType
*) type
)->get_infer_kind ()
2051 == TyTy::InferType::INTEGRAL
));
2054 case ArithmeticOrLogicalOperator::LEFT_SHIFT
:
2055 case ArithmeticOrLogicalOperator::RIGHT_SHIFT
:
2056 return (type
->get_kind () == TyTy::TypeKind::INT
)
2057 || (type
->get_kind () == TyTy::TypeKind::UINT
)
2058 || (type
->get_kind () == TyTy::TypeKind::USIZE
)
2059 || (type
->get_kind () == TyTy::TypeKind::ISIZE
)
2060 || (type
->get_kind () == TyTy::TypeKind::INFER
2061 && (((const TyTy::InferType
*) type
)->get_infer_kind ()
2062 == TyTy::InferType::INTEGRAL
));
2065 rust_unreachable ();
2069 } // namespace Resolver