aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc169
-rw-r--r--gcc/rust/backend/rust-compile-expr.h43
-rw-r--r--gcc/rust/backend/rust-compile-type.cc7
-rw-r--r--gcc/rust/backend/rust-compile-type.h1
-rw-r--r--gcc/rust/backend/rust-compile-tyty.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h79
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h44
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc490
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h241
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty-cast.h53
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h61
-rw-r--r--gcc/rust/typecheck/rust-tyty-coercion.h54
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h53
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc90
-rw-r--r--gcc/rust/typecheck/rust-tyty.h45
-rw-r--r--gcc/rust/util/rust-lang-item.h20
-rw-r--r--gcc/testsuite/rust/compile/torture/range-lang-item1.rs32
-rw-r--r--gcc/testsuite/rust/compile/usize1.rs1
-rw-r--r--gcc/testsuite/rust/execute/torture/index1.rs28
23 files changed, 1252 insertions, 270 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 9de93fe..69943f9 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -95,6 +95,7 @@ GRS_OBJS = \
rust/rust-hir-type-check-type.o \
rust/rust-hir-type-check-struct.o \
rust/rust-hir-type-check-pattern.o \
+ rust/rust-hir-type-check-expr.o \
rust/rust-hir-dot-operator.o \
rust/rust-autoderef.o \
rust/rust-substitution-mapper.o \
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 65f159e..bf47661 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -790,7 +790,7 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
tree
CompileExpr::resolve_operator_overload (
- Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExpr &expr,
+ Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExprMeta expr,
tree lhs, tree rhs, HIR::Expr *lhs_expr, HIR::Expr *rhs_expr)
{
TyTy::FnType *fntype;
@@ -1377,5 +1377,172 @@ CompileExpr::visit (HIR::IdentifierExpr &expr)
}
}
+void
+CompileExpr::visit (HIR::RangeFromToExpr &expr)
+{
+ tree from = CompileExpr::Compile (expr.get_from_expr ().get (), ctx);
+ tree to = CompileExpr::Compile (expr.get_to_expr ().get (), ctx);
+ if (from == error_mark_node || to == error_mark_node)
+ {
+ translated = error_mark_node;
+ return;
+ }
+
+ TyTy::BaseType *tyty = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
+ rust_assert (ok);
+
+ tree adt = TyTyResolveCompile::compile (ctx, tyty);
+
+ // make the constructor
+ translated
+ = ctx->get_backend ()->constructor_expression (adt, false, {from, to}, -1,
+ expr.get_locus ());
+}
+
+void
+CompileExpr::visit (HIR::RangeFromExpr &expr)
+{
+ tree from = CompileExpr::Compile (expr.get_from_expr ().get (), ctx);
+ if (from == error_mark_node)
+ {
+ translated = error_mark_node;
+ return;
+ }
+
+ TyTy::BaseType *tyty = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
+ rust_assert (ok);
+
+ tree adt = TyTyResolveCompile::compile (ctx, tyty);
+
+ // make the constructor
+ translated
+ = ctx->get_backend ()->constructor_expression (adt, false, {from}, -1,
+ expr.get_locus ());
+}
+
+void
+CompileExpr::visit (HIR::RangeToExpr &expr)
+{
+ tree to = CompileExpr::Compile (expr.get_to_expr ().get (), ctx);
+ if (to == error_mark_node)
+ {
+ translated = error_mark_node;
+ return;
+ }
+
+ TyTy::BaseType *tyty = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
+ rust_assert (ok);
+
+ tree adt = TyTyResolveCompile::compile (ctx, tyty);
+
+ // make the constructor
+ translated
+ = ctx->get_backend ()->constructor_expression (adt, false, {to}, -1,
+ expr.get_locus ());
+}
+
+void
+CompileExpr::visit (HIR::RangeFullExpr &expr)
+{
+ TyTy::BaseType *tyty = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
+ rust_assert (ok);
+
+ tree adt = TyTyResolveCompile::compile (ctx, tyty);
+ translated = ctx->get_backend ()->constructor_expression (adt, false, {}, -1,
+ expr.get_locus ());
+}
+
+void
+CompileExpr::visit (HIR::RangeFromToInclExpr &expr)
+{
+ tree from = CompileExpr::Compile (expr.get_from_expr ().get (), ctx);
+ tree to = CompileExpr::Compile (expr.get_to_expr ().get (), ctx);
+ if (from == error_mark_node || to == error_mark_node)
+ {
+ translated = error_mark_node;
+ return;
+ }
+
+ TyTy::BaseType *tyty = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty);
+ rust_assert (ok);
+
+ tree adt = TyTyResolveCompile::compile (ctx, tyty);
+
+ // make the constructor
+ translated
+ = ctx->get_backend ()->constructor_expression (adt, false, {from, to}, -1,
+ expr.get_locus ());
+}
+
+void
+CompileExpr::visit (HIR::ArrayIndexExpr &expr)
+{
+ tree array_reference = CompileExpr::Compile (expr.get_array_expr (), ctx);
+ tree index = CompileExpr::Compile (expr.get_index_expr (), ctx);
+
+ // this might be an core::ops::index lang item situation
+ TyTy::FnType *fntype;
+ bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
+ expr.get_mappings ().get_hirid (), &fntype);
+ if (is_op_overload)
+ {
+ auto lang_item_type = Analysis::RustLangItem::ItemType::INDEX;
+ tree operator_overload_call
+ = resolve_operator_overload (lang_item_type, expr, array_reference,
+ index, expr.get_array_expr (),
+ expr.get_index_expr ());
+
+ // lookup the expected type for this expression
+ TyTy::BaseType *tyty = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &tyty);
+ rust_assert (ok);
+ tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
+
+ // rust deref always returns a reference from this overload then we can
+ // actually do the indirection
+ translated
+ = ctx->get_backend ()->indirect_expression (expected_type,
+ operator_overload_call,
+ true, expr.get_locus ());
+ return;
+ }
+
+ // lets check if the array is a reference type then we can add an
+ // indirection if required
+ TyTy::BaseType *array_expr_ty = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ expr.get_array_expr ()->get_mappings ().get_hirid (), &array_expr_ty);
+ rust_assert (ok);
+
+ // do we need to add an indirect reference
+ if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
+ {
+ TyTy::ReferenceType *r
+ = static_cast<TyTy::ReferenceType *> (array_expr_ty);
+ TyTy::BaseType *tuple_type = r->get_base ();
+ tree array_tyty = TyTyResolveCompile::compile (ctx, tuple_type);
+
+ array_reference
+ = ctx->get_backend ()->indirect_expression (array_tyty, array_reference,
+ true, expr.get_locus ());
+ }
+
+ translated
+ = ctx->get_backend ()->array_index_expression (array_reference, index,
+ expr.get_locus ());
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 2fee3be..f2b4df8 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -201,36 +201,7 @@ public:
void visit (HIR::CompoundAssignmentExpr &expr) override;
- void visit (HIR::ArrayIndexExpr &expr) override
- {
- tree array_reference = CompileExpr::Compile (expr.get_array_expr (), ctx);
- tree index = CompileExpr::Compile (expr.get_index_expr (), ctx);
-
- // lets check if the array is a reference type then we can add an
- // indirection if required
- TyTy::BaseType *array_expr_ty = nullptr;
- bool ok = ctx->get_tyctx ()->lookup_type (
- expr.get_array_expr ()->get_mappings ().get_hirid (), &array_expr_ty);
- rust_assert (ok);
-
- // do we need to add an indirect reference
- if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
- {
- TyTy::ReferenceType *r
- = static_cast<TyTy::ReferenceType *> (array_expr_ty);
- TyTy::BaseType *tuple_type = r->get_base ();
- tree array_tyty = TyTyResolveCompile::compile (ctx, tuple_type);
-
- array_reference
- = ctx->get_backend ()->indirect_expression (array_tyty,
- array_reference, true,
- expr.get_locus ());
- }
-
- translated
- = ctx->get_backend ()->array_index_expression (array_reference, index,
- expr.get_locus ());
- }
+ void visit (HIR::ArrayIndexExpr &expr) override;
void visit (HIR::ArrayExpr &expr) override;
@@ -803,6 +774,16 @@ public:
void visit (HIR::MatchExpr &expr) override;
+ void visit (HIR::RangeFromToExpr &expr) override;
+
+ void visit (HIR::RangeFromExpr &expr) override;
+
+ void visit (HIR::RangeToExpr &expr) override;
+
+ void visit (HIR::RangeFullExpr &expr) override;
+
+ void visit (HIR::RangeFromToInclExpr &expr) override;
+
protected:
tree compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn,
TyTy::BaseType *receiver,
@@ -818,7 +799,7 @@ protected:
tree
resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type,
- HIR::OperatorExpr &expr, tree lhs, tree rhs,
+ HIR::OperatorExprMeta expr, tree lhs, tree rhs,
HIR::Expr *lhs_expr, HIR::Expr *rhs_expr);
tree compile_bool_literal (const HIR::LiteralExpr &expr,
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index 6de063b..21da9af 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -345,6 +345,13 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
}
void
+TyTyResolveCompile::visit (const TyTy::SliceType &type)
+{
+ // TODO
+ gcc_unreachable ();
+}
+
+void
TyTyResolveCompile::visit (const TyTy::BoolType &type)
{
tree compiled_type = nullptr;
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index 50598de..4f9c403 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -43,6 +43,7 @@ public:
void visit (const TyTy::FnType &) override;
void visit (const TyTy::FnPtr &) override;
void visit (const TyTy::ArrayType &) override;
+ void visit (const TyTy::SliceType &) override;
void visit (const TyTy::BoolType &) override;
void visit (const TyTy::IntType &) override;
void visit (const TyTy::UintType &) override;
diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h
index 2e5a769..a3720f8 100644
--- a/gcc/rust/backend/rust-compile-tyty.h
+++ b/gcc/rust/backend/rust-compile-tyty.h
@@ -62,6 +62,8 @@ public:
void visit (TyTy::ArrayType &) override { gcc_unreachable (); }
+ void visit (TyTy::SliceType &) override { gcc_unreachable (); }
+
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
void visit (TyTy::PointerType &) override { gcc_unreachable (); }
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index a8048bb..df836fc 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -728,6 +728,85 @@ public:
expr.get_outer_attrs (), expr.get_locus ());
}
+ void visit (AST::RangeFromToExpr &expr) override
+ {
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *range_from
+ = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+ HIR::Expr *range_to
+ = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+ translated
+ = new HIR::RangeFromToExpr (mapping,
+ std::unique_ptr<HIR::Expr> (range_from),
+ std::unique_ptr<HIR::Expr> (range_to),
+ expr.get_locus ());
+ }
+
+ void visit (AST::RangeFromExpr &expr) override
+ {
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *range_from
+ = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+
+ translated
+ = new HIR::RangeFromExpr (mapping,
+ std::unique_ptr<HIR::Expr> (range_from),
+ expr.get_locus ());
+ }
+
+ void visit (AST::RangeToExpr &expr) override
+ {
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *range_to
+ = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+ translated
+ = new HIR::RangeToExpr (mapping, std::unique_ptr<HIR::Expr> (range_to),
+ expr.get_locus ());
+ }
+
+ void visit (AST::RangeFullExpr &expr) override
+ {
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::RangeFullExpr (mapping, expr.get_locus ());
+ }
+
+ void visit (AST::RangeFromToInclExpr &expr) override
+ {
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *range_from
+ = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+ HIR::Expr *range_to
+ = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+ translated
+ = new HIR::RangeFromToInclExpr (mapping,
+ std::unique_ptr<HIR::Expr> (range_from),
+ std::unique_ptr<HIR::Expr> (range_to),
+ expr.get_locus ());
+ }
+
private:
ASTLoweringExpr ()
: ASTLoweringBase (), translated (nullptr),
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index b8d3354..b77545a 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -2430,6 +2430,9 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
+ std::unique_ptr<Expr> &get_from_expr () { return from; }
+ std::unique_ptr<Expr> &get_to_expr () { return to; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2480,6 +2483,8 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
+ std::unique_ptr<Expr> &get_from_expr () { return from; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2531,6 +2536,8 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
+ std::unique_ptr<Expr> &get_to_expr () { return to; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2617,6 +2624,9 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
+ std::unique_ptr<Expr> &get_from_expr () { return from; }
+ std::unique_ptr<Expr> &get_to_expr () { return to; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4019,6 +4029,40 @@ protected:
return new AsyncBlockExpr (*this);
}
};
+
+// this is a utility helper class for type-checking and code-generation
+class OperatorExprMeta
+{
+public:
+ OperatorExprMeta (HIR::CompoundAssignmentExpr &expr)
+ : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ {}
+
+ OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr)
+ : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ {}
+
+ OperatorExprMeta (HIR::NegationExpr &expr)
+ : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ {}
+
+ OperatorExprMeta (HIR::DereferenceExpr &expr)
+ : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ {}
+
+ OperatorExprMeta (HIR::ArrayIndexExpr &expr)
+ : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ {}
+
+ const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
+
+ Location get_locus () const { return locus; }
+
+private:
+ const Analysis::NodeMapping node_mappings;
+ Location locus;
+};
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
new file mode 100644
index 0000000..539a3fe
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -0,0 +1,490 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-check-expr.h"
+
+namespace Rust {
+namespace Resolver {
+
+void
+TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
+{
+ auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE;
+
+ DefId respective_lang_item_id = UNKNOWN_DEFID;
+ bool lang_item_defined
+ = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
+
+ // we need to have it maybe
+ if (!lang_item_defined)
+ {
+ rust_internal_error_at (
+ expr.get_locus (), "unable to find relevant lang item: %s",
+ Analysis::RustLangItem::ToString (lang_item_type).c_str ());
+ return;
+ }
+
+ // look it up and it _must_ be a struct definition
+ HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
+ rust_assert (item != nullptr);
+
+ TyTy::BaseType *item_type = nullptr;
+ bool ok
+ = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
+ rust_assert (ok);
+ rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
+
+ // this is a single generic item lets assert that
+ rust_assert (adt->get_num_substitutions () == 1);
+
+ // resolve the range expressions and these types must unify then we use that
+ // type to substitute into the ADT
+ TyTy::BaseType *from_ty
+ = TypeCheckExpr::Resolve (expr.get_from_expr ().get (), false);
+ TyTy::BaseType *to_ty
+ = TypeCheckExpr::Resolve (expr.get_to_expr ().get (), false);
+ TyTy::BaseType *unified = from_ty->unify (to_ty);
+
+ // substitute it in
+ std::vector<TyTy::SubstitutionArg> subst_mappings;
+ const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
+ subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
+
+ TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+ infered = SubstMapperInternal::Resolve (adt, subst);
+}
+
+void
+TypeCheckExpr::visit (HIR::RangeFromExpr &expr)
+{
+ auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE_FROM;
+
+ DefId respective_lang_item_id = UNKNOWN_DEFID;
+ bool lang_item_defined
+ = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
+
+ // we need to have it maybe
+ if (!lang_item_defined)
+ {
+ rust_internal_error_at (
+ expr.get_locus (), "unable to find relevant lang item: %s",
+ Analysis::RustLangItem::ToString (lang_item_type).c_str ());
+ return;
+ }
+
+ // look it up and it _must_ be a struct definition
+ HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
+ rust_assert (item != nullptr);
+
+ TyTy::BaseType *item_type = nullptr;
+ bool ok
+ = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
+ rust_assert (ok);
+ rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
+
+ // this is a single generic item lets assert that
+ rust_assert (adt->get_num_substitutions () == 1);
+
+ // resolve the range expressions and these types must unify then we use that
+ // type to substitute into the ADT
+ TyTy::BaseType *from_ty
+ = TypeCheckExpr::Resolve (expr.get_from_expr ().get (), false);
+
+ // substitute it in
+ std::vector<TyTy::SubstitutionArg> subst_mappings;
+ const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
+ subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
+
+ TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+ infered = SubstMapperInternal::Resolve (adt, subst);
+}
+
+void
+TypeCheckExpr::visit (HIR::RangeToExpr &expr)
+{
+ auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE_TO;
+
+ DefId respective_lang_item_id = UNKNOWN_DEFID;
+ bool lang_item_defined
+ = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
+
+ // we need to have it maybe
+ if (!lang_item_defined)
+ {
+ rust_internal_error_at (
+ expr.get_locus (), "unable to find relevant lang item: %s",
+ Analysis::RustLangItem::ToString (lang_item_type).c_str ());
+ return;
+ }
+
+ // look it up and it _must_ be a struct definition
+ HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
+ rust_assert (item != nullptr);
+
+ TyTy::BaseType *item_type = nullptr;
+ bool ok
+ = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
+ rust_assert (ok);
+ rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
+
+ // this is a single generic item lets assert that
+ rust_assert (adt->get_num_substitutions () == 1);
+
+ // resolve the range expressions and these types must unify then we use that
+ // type to substitute into the ADT
+ TyTy::BaseType *from_ty
+ = TypeCheckExpr::Resolve (expr.get_to_expr ().get (), false);
+
+ // substitute it in
+ std::vector<TyTy::SubstitutionArg> subst_mappings;
+ const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
+ subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
+
+ TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+ infered = SubstMapperInternal::Resolve (adt, subst);
+}
+
+void
+TypeCheckExpr::visit (HIR::RangeFullExpr &expr)
+{
+ auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE_FULL;
+
+ DefId respective_lang_item_id = UNKNOWN_DEFID;
+ bool lang_item_defined
+ = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
+
+ // we need to have it maybe
+ if (!lang_item_defined)
+ {
+ rust_internal_error_at (
+ expr.get_locus (), "unable to find relevant lang item: %s",
+ Analysis::RustLangItem::ToString (lang_item_type).c_str ());
+ return;
+ }
+
+ // look it up and it _must_ be a struct definition
+ HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
+ rust_assert (item != nullptr);
+
+ TyTy::BaseType *item_type = nullptr;
+ bool ok
+ = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
+ rust_assert (ok);
+ rust_assert (item_type->is_unit ());
+
+ infered = item_type;
+}
+
+void
+TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr)
+{
+ auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE_INCLUSIVE;
+
+ DefId respective_lang_item_id = UNKNOWN_DEFID;
+ bool lang_item_defined
+ = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
+
+ // we need to have it maybe
+ if (!lang_item_defined)
+ {
+ rust_internal_error_at (
+ expr.get_locus (), "unable to find relevant lang item: %s",
+ Analysis::RustLangItem::ToString (lang_item_type).c_str ());
+ return;
+ }
+
+ // look it up and it _must_ be a struct definition
+ HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
+ rust_assert (item != nullptr);
+
+ TyTy::BaseType *item_type = nullptr;
+ bool ok
+ = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
+ rust_assert (ok);
+ rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
+
+ // this is a single generic item lets assert that
+ rust_assert (adt->get_num_substitutions () == 1);
+
+ // resolve the range expressions and these types must unify then we use that
+ // type to substitute into the ADT
+ TyTy::BaseType *from_ty
+ = TypeCheckExpr::Resolve (expr.get_from_expr ().get (), false);
+ TyTy::BaseType *to_ty
+ = TypeCheckExpr::Resolve (expr.get_to_expr ().get (), false);
+ TyTy::BaseType *unified = from_ty->unify (to_ty);
+
+ // substitute it in
+ std::vector<TyTy::SubstitutionArg> subst_mappings;
+ const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
+ subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
+
+ TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+ infered = SubstMapperInternal::Resolve (adt, subst);
+}
+
+void
+TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
+{
+ auto array_expr_ty
+ = TypeCheckExpr::Resolve (expr.get_array_expr (), inside_loop);
+ if (array_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ auto index_expr_ty = TypeCheckExpr::Resolve (expr.get_index_expr (), false);
+ if (index_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ // is this a case of core::ops::index?
+ auto lang_item_type = Analysis::RustLangItem::ItemType::INDEX;
+ bool operator_overloaded
+ = resolve_operator_overload (lang_item_type, expr, array_expr_ty,
+ index_expr_ty);
+ if (operator_overloaded)
+ {
+ // index and index mut always return a reference to the element
+ TyTy::BaseType *resolved = infered;
+ rust_assert (resolved->get_kind () == TyTy::TypeKind::REF);
+ TyTy::ReferenceType *ref = static_cast<TyTy::ReferenceType *> (resolved);
+
+ infered = ref->get_base ()->clone ();
+ return;
+ }
+
+ if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
+ {
+ // lets try and deref it since rust allows this
+ auto ref = static_cast<TyTy::ReferenceType *> (array_expr_ty);
+ auto base = ref->get_base ();
+ if (base->get_kind () == TyTy::TypeKind::ARRAY)
+ array_expr_ty = base;
+ }
+
+ if (array_expr_ty->get_kind () != TyTy::TypeKind::ARRAY)
+ {
+ rust_error_at (expr.get_index_expr ()->get_locus (),
+ "expected an ArrayType got [%s]",
+ array_expr_ty->as_string ().c_str ());
+ return;
+ }
+
+ TyTy::BaseType *size_ty;
+ bool ok = context->lookup_builtin ("usize", &size_ty);
+ rust_assert (ok);
+
+ auto resolved_index_expr
+ = size_ty->unify (TypeCheckExpr::Resolve (expr.get_index_expr (), false));
+ if (resolved_index_expr->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ TyTy::ArrayType *array_type = static_cast<TyTy::ArrayType *> (array_expr_ty);
+ infered = array_type->get_element_type ()->clone ();
+}
+
+bool
+TypeCheckExpr::resolve_operator_overload (
+ Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExprMeta expr,
+ TyTy::BaseType *lhs, TyTy::BaseType *rhs)
+{
+ // look up lang item for arithmetic type
+ std::string associated_item_name
+ = Analysis::RustLangItem::ToString (lang_item_type);
+ DefId respective_lang_item_id = UNKNOWN_DEFID;
+ bool lang_item_defined
+ = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
+
+ // probe for the lang-item
+ if (!lang_item_defined)
+ return false;
+
+ auto segment = HIR::PathIdentSegment (associated_item_name);
+ auto candidate
+ = MethodResolver::Probe (lhs, HIR::PathIdentSegment (associated_item_name));
+
+ bool have_implementation_for_lang_item = !candidate.is_error ();
+ if (!have_implementation_for_lang_item)
+ return false;
+
+ // Get the adjusted self
+ Adjuster adj (lhs);
+ TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
+
+ // is this the case we are recursive
+ // handle the case where we are within the impl block for this lang_item
+ // otherwise we end up with a recursive operator overload such as the i32
+ // operator overload trait
+ TypeCheckContextItem &fn_context = context->peek_context ();
+ if (fn_context.get_type () == TypeCheckContextItem::ItemType::IMPL_ITEM)
+ {
+ auto &impl_item = fn_context.get_impl_item ();
+ HIR::ImplBlock *parent = impl_item.first;
+ HIR::Function *fn = impl_item.second;
+
+ if (parent->has_trait_ref ()
+ && fn->get_function_name ().compare (associated_item_name) == 0)
+ {
+ TraitReference *trait_reference
+ = TraitResolver::Lookup (*parent->get_trait_ref ().get ());
+ if (!trait_reference->is_error ())
+ {
+ TyTy::BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (fn->get_mappings ().get_hirid (),
+ &lookup);
+ rust_assert (ok);
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
+
+ TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
+ rust_assert (fntype->is_method ());
+
+ bool is_lang_item_impl
+ = trait_reference->get_mappings ().get_defid ()
+ == respective_lang_item_id;
+ bool self_is_lang_item_self
+ = fntype->get_self_type ()->is_equal (*adjusted_self);
+ bool recursive_operator_overload
+ = is_lang_item_impl && self_is_lang_item_self;
+
+ if (recursive_operator_overload)
+ return false;
+ }
+ }
+ }
+
+ // store the adjustments for code-generation to know what to do
+ context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
+ std::move (candidate.adjustments));
+
+ // now its just like a method-call-expr
+ context->insert_receiver (expr.get_mappings ().get_hirid (), lhs);
+
+ PathProbeCandidate &resolved_candidate = candidate.candidate;
+ TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
+ NodeId resolved_node_id
+ = resolved_candidate.is_impl_candidate ()
+ ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
+ .get_nodeid ()
+ : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
+
+ rust_assert (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::BaseType *lookup = lookup_tyty;
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
+ rust_assert (fn->is_method ());
+
+ auto root = lhs->get_root ();
+ bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
+ if (root->get_kind () == TyTy::TypeKind::ADT)
+ {
+ const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
+ if (adt->has_substitutions () && fn->needs_substitution ())
+ {
+ // consider the case where we have:
+ //
+ // struct Foo<X,Y>(X,Y);
+ //
+ // impl<T> Foo<T, i32> {
+ // fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
+ // }
+ //
+ // In this case we end up with an fn type of:
+ //
+ // fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
+ //
+ // This means the instance or self we are calling this method for
+ // will be substituted such that we can get the inherited type
+ // arguments but then need to use the turbo fish if available or
+ // infer the remaining arguments. Luckily rust does not allow for
+ // default types GenericParams on impl blocks since these must
+ // always be at the end of the list
+
+ auto s = fn->get_self_type ()->get_root ();
+ rust_assert (s->can_eq (adt, false));
+ rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
+ const TyTy::ADTType *self_adt
+ = static_cast<const TyTy::ADTType *> (s);
+
+ // we need to grab the Self substitutions as the inherit type
+ // parameters for this
+ if (self_adt->needs_substitution ())
+ {
+ rust_assert (adt->was_substituted ());
+
+ TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
+ = GetUsedSubstArgs::From (adt);
+
+ TyTy::SubstitutionArgumentMappings inherit_type_args
+ = self_adt->solve_mappings_from_receiver_for_self (
+ used_args_in_prev_segment);
+
+ // there may or may not be inherited type arguments
+ if (!inherit_type_args.is_error ())
+ {
+ // need to apply the inherited type arguments to the
+ // function
+ lookup = fn->handle_substitions (inherit_type_args);
+ }
+ }
+ }
+ }
+
+ // handle generics
+ if (!receiver_is_type_param)
+ {
+ if (lookup->needs_generic_substitutions ())
+ {
+ lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
+ }
+ }
+
+ // type check the arguments if required
+ TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
+ rust_assert (type->num_params () > 0);
+ auto fnparam = type->param_at (0);
+ fnparam.second->unify (adjusted_self); // typecheck the self
+ if (rhs == nullptr)
+ {
+ rust_assert (type->num_params () == 1);
+ }
+ else
+ {
+ rust_assert (type->num_params () == 2);
+ auto fnparam = type->param_at (1);
+ fnparam.second->unify (rhs); // typecheck the rhs
+ }
+
+ // get the return type
+ TyTy::BaseType *function_ret_tyty = type->get_return_type ()->clone ();
+
+ // store the expected fntype
+ context->insert_operator_overload (expr.get_mappings ().get_hirid (), type);
+
+ // set up the resolved name on the path
+ resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
+ resolved_node_id);
+
+ // return the result of the function back
+ infered = function_ret_tyty;
+
+ return true;
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index a4b8f0a..93aa868 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -879,52 +879,7 @@ public:
= TypeCheckExpr::Resolve (expr.get_block_expr ().get (), inside_loop);
}
- void visit (HIR::ArrayIndexExpr &expr) override
- {
- TyTy::BaseType *size_ty;
- if (!context->lookup_builtin ("usize", &size_ty))
- {
- rust_error_at (
- expr.get_locus (),
- "Failure looking up size type for index in ArrayIndexExpr");
- return;
- }
-
- auto resolved_index_expr
- = size_ty->unify (TypeCheckExpr::Resolve (expr.get_index_expr (), false));
- if (resolved_index_expr->get_kind () != TyTy::TypeKind::ERROR)
- {
- // allow the index expr to fail lets just continue on
- context->insert_type (expr.get_index_expr ()->get_mappings (),
- resolved_index_expr);
- }
-
- auto array_expr_ty
- = TypeCheckExpr::Resolve (expr.get_array_expr (), inside_loop);
- if (array_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
- return;
- else if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
- {
- // lets try and deref it since rust allows this
- auto ref = static_cast<TyTy::ReferenceType *> (array_expr_ty);
- auto base = ref->get_base ();
- if (base->get_kind () == TyTy::TypeKind::ARRAY)
- array_expr_ty = base;
- }
-
- if (array_expr_ty->get_kind () != TyTy::TypeKind::ARRAY)
- {
- rust_error_at (expr.get_index_expr ()->get_locus (),
- "expected an ArrayType got [%s]",
- infered->as_string ().c_str ());
- infered = nullptr;
- return;
- }
-
- TyTy::ArrayType *array_type
- = static_cast<TyTy::ArrayType *> (array_expr_ty);
- infered = array_type->get_element_type ()->clone ();
- }
+ void visit (HIR::ArrayIndexExpr &expr) override;
void visit (HIR::ArrayExpr &expr) override
{
@@ -1271,195 +1226,21 @@ public:
}
}
-protected:
- bool
- resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type,
- HIR::OperatorExpr &expr, TyTy::BaseType *lhs,
- TyTy::BaseType *rhs)
- {
- // look up lang item for arithmetic type
- std::string associated_item_name
- = Analysis::RustLangItem::ToString (lang_item_type);
- DefId respective_lang_item_id = UNKNOWN_DEFID;
- bool lang_item_defined
- = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
-
- // probe for the lang-item
- if (!lang_item_defined)
- return false;
-
- auto segment = HIR::PathIdentSegment (associated_item_name);
- auto candidate
- = MethodResolver::Probe (lhs,
- HIR::PathIdentSegment (associated_item_name));
+ void visit (HIR::RangeFromToExpr &expr) override;
- bool have_implementation_for_lang_item = !candidate.is_error ();
- if (!have_implementation_for_lang_item)
- return false;
+ void visit (HIR::RangeFromExpr &expr) override;
- // Get the adjusted self
- Adjuster adj (lhs);
- TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
+ void visit (HIR::RangeToExpr &expr) override;
- // is this the case we are recursive
- // handle the case where we are within the impl block for this lang_item
- // otherwise we end up with a recursive operator overload such as the i32
- // operator overload trait
- TypeCheckContextItem &fn_context = context->peek_context ();
- if (fn_context.get_type () == TypeCheckContextItem::ItemType::IMPL_ITEM)
- {
- auto &impl_item = fn_context.get_impl_item ();
- HIR::ImplBlock *parent = impl_item.first;
- HIR::Function *fn = impl_item.second;
+ void visit (HIR::RangeFullExpr &expr) override;
- if (parent->has_trait_ref ()
- && fn->get_function_name ().compare (associated_item_name) == 0)
- {
- TraitReference *trait_reference
- = TraitResolver::Lookup (*parent->get_trait_ref ().get ());
- if (!trait_reference->is_error ())
- {
- TyTy::BaseType *lookup = nullptr;
- bool ok
- = context->lookup_type (fn->get_mappings ().get_hirid (),
- &lookup);
- rust_assert (ok);
- rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
-
- TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
- rust_assert (fntype->is_method ());
-
- bool is_lang_item_impl
- = trait_reference->get_mappings ().get_defid ()
- == respective_lang_item_id;
- bool self_is_lang_item_self
- = fntype->get_self_type ()->is_equal (*adjusted_self);
- bool recursive_operator_overload
- = is_lang_item_impl && self_is_lang_item_self;
-
- if (recursive_operator_overload)
- return false;
- }
- }
- }
+ void visit (HIR::RangeFromToInclExpr &expr) override;
- // store the adjustments for code-generation to know what to do
- context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
- std::move (candidate.adjustments));
-
- // now its just like a method-call-expr
- context->insert_receiver (expr.get_mappings ().get_hirid (), lhs);
-
- PathProbeCandidate &resolved_candidate = candidate.candidate;
- TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
- NodeId resolved_node_id
- = resolved_candidate.is_impl_candidate ()
- ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
- .get_nodeid ()
- : resolved_candidate.item.trait.item_ref->get_mappings ()
- .get_nodeid ();
-
- rust_assert (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF);
- TyTy::BaseType *lookup = lookup_tyty;
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
- rust_assert (fn->is_method ());
-
- auto root = lhs->get_root ();
- bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
- if (root->get_kind () == TyTy::TypeKind::ADT)
- {
- const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
- if (adt->has_substitutions () && fn->needs_substitution ())
- {
- // consider the case where we have:
- //
- // struct Foo<X,Y>(X,Y);
- //
- // impl<T> Foo<T, i32> {
- // fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
- // }
- //
- // In this case we end up with an fn type of:
- //
- // fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
- //
- // This means the instance or self we are calling this method for
- // will be substituted such that we can get the inherited type
- // arguments but then need to use the turbo fish if available or
- // infer the remaining arguments. Luckily rust does not allow for
- // default types GenericParams on impl blocks since these must
- // always be at the end of the list
-
- auto s = fn->get_self_type ()->get_root ();
- rust_assert (s->can_eq (adt, false));
- rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
- const TyTy::ADTType *self_adt
- = static_cast<const TyTy::ADTType *> (s);
-
- // we need to grab the Self substitutions as the inherit type
- // parameters for this
- if (self_adt->needs_substitution ())
- {
- rust_assert (adt->was_substituted ());
-
- TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
- = GetUsedSubstArgs::From (adt);
-
- TyTy::SubstitutionArgumentMappings inherit_type_args
- = self_adt->solve_mappings_from_receiver_for_self (
- used_args_in_prev_segment);
-
- // there may or may not be inherited type arguments
- if (!inherit_type_args.is_error ())
- {
- // need to apply the inherited type arguments to the
- // function
- lookup = fn->handle_substitions (inherit_type_args);
- }
- }
- }
- }
-
- // handle generics
- if (!receiver_is_type_param)
- {
- if (lookup->needs_generic_substitutions ())
- {
- lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
- }
- }
-
- // type check the arguments if required
- TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
- rust_assert (type->num_params () > 0);
- auto fnparam = type->param_at (0);
- fnparam.second->unify (adjusted_self); // typecheck the self
- if (rhs == nullptr)
- {
- rust_assert (type->num_params () == 1);
- }
- else
- {
- rust_assert (type->num_params () == 2);
- auto fnparam = type->param_at (1);
- fnparam.second->unify (rhs); // typecheck the rhs
- }
-
- // get the return type
- TyTy::BaseType *function_ret_tyty = type->get_return_type ()->clone ();
-
- // store the expected fntype
- context->insert_operator_overload (expr.get_mappings ().get_hirid (), type);
-
- // set up the resolved name on the path
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
-
- // return the result of the function back
- infered = function_ret_tyty;
-
- return true;
- }
+protected:
+ bool
+ resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type,
+ HIR::OperatorExprMeta expr, TyTy::BaseType *lhs,
+ TyTy::BaseType *rhs);
private:
TypeCheckExpr (bool inside_loop)
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 4ea4762..0d48bd2 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -124,6 +124,7 @@ public:
void visit (TyTy::TupleType &) override { gcc_unreachable (); }
void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
void visit (TyTy::ArrayType &) override { gcc_unreachable (); }
+ void visit (TyTy::SliceType &) override { gcc_unreachable (); }
void visit (TyTy::BoolType &) override { gcc_unreachable (); }
void visit (TyTy::IntType &) override { gcc_unreachable (); }
void visit (TyTy::UintType &) override { gcc_unreachable (); }
@@ -224,6 +225,7 @@ public:
void visit (TyTy::InferType &) override { gcc_unreachable (); }
void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
void visit (TyTy::ArrayType &) override { gcc_unreachable (); }
+ void visit (TyTy::SliceType &) override { gcc_unreachable (); }
void visit (TyTy::BoolType &) override { gcc_unreachable (); }
void visit (TyTy::IntType &) override { gcc_unreachable (); }
void visit (TyTy::UintType &) override { gcc_unreachable (); }
@@ -286,6 +288,7 @@ public:
void visit (TyTy::TupleType &) override { gcc_unreachable (); }
void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
void visit (TyTy::ArrayType &) override { gcc_unreachable (); }
+ void visit (TyTy::SliceType &) override { gcc_unreachable (); }
void visit (TyTy::BoolType &) override { gcc_unreachable (); }
void visit (TyTy::IntType &) override { gcc_unreachable (); }
void visit (TyTy::UintType &) override { gcc_unreachable (); }
@@ -343,6 +346,7 @@ public:
void visit (const TyTy::TupleType &) override {}
void visit (const TyTy::FnPtr &) override {}
void visit (const TyTy::ArrayType &) override {}
+ void visit (const TyTy::SliceType &) override {}
void visit (const TyTy::BoolType &) override {}
void visit (const TyTy::IntType &) override {}
void visit (const TyTy::UintType &) override {}
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index b238d476f..51817e6 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -43,6 +43,7 @@ public:
void visit (InferType &) override { gcc_unreachable (); }
void visit (TupleType &) override { gcc_unreachable (); }
void visit (ArrayType &) override { gcc_unreachable (); }
+ void visit (SliceType &) override { gcc_unreachable (); }
void visit (BoolType &) override { gcc_unreachable (); }
void visit (IntType &) override { gcc_unreachable (); }
void visit (UintType &) override { gcc_unreachable (); }
@@ -99,6 +100,7 @@ public:
void visit (InferType &) override { gcc_unreachable (); }
void visit (TupleType &) override { gcc_unreachable (); }
void visit (ArrayType &) override { gcc_unreachable (); }
+ void visit (SliceType &) override { gcc_unreachable (); }
void visit (BoolType &) override { gcc_unreachable (); }
void visit (IntType &) override { gcc_unreachable (); }
void visit (UintType &) override { gcc_unreachable (); }
diff --git a/gcc/rust/typecheck/rust-tyty-cast.h b/gcc/rust/typecheck/rust-tyty-cast.h
index b9f4e14..0e0e7b0 100644
--- a/gcc/rust/typecheck/rust-tyty-cast.h
+++ b/gcc/rust/typecheck/rust-tyty-cast.h
@@ -153,6 +153,17 @@ public:
type.as_string ().c_str ());
}
+ virtual void visit (SliceType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
virtual void visit (BoolType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
@@ -468,6 +479,19 @@ public:
BaseCastRules::visit (type);
}
+ void visit (SliceType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
void visit (ADTType &type) override
{
bool is_valid
@@ -818,6 +842,35 @@ private:
ArrayType *base;
};
+class SliceCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ SliceCastRules (SliceType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (SliceType &type) override
+ {
+ // check base type
+ auto base_resolved
+ = base->get_element_type ()->unify (type.get_element_type ());
+ if (base_resolved == nullptr)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = new SliceType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ TyVar (base_resolved->get_ref ()));
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ SliceType *base;
+};
+
class BoolCastRules : public BaseCastRules
{
using Rust::TyTy::BaseCastRules::visit;
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index bd568be..436bde9 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -155,6 +155,22 @@ public:
}
}
+ virtual void visit (const SliceType &type) override
+ {
+ ok = false;
+ if (emit_error_flag)
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus
+ = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+ }
+
virtual void visit (const BoolType &type) override
{
ok = false;
@@ -544,6 +560,19 @@ public:
BaseCmp::visit (type);
}
+ void visit (const SliceType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ ok = true;
+ return;
+ }
+
+ BaseCmp::visit (type);
+ }
+
void visit (const ADTType &type) override
{
bool is_valid
@@ -864,6 +893,36 @@ private:
const ArrayType *base;
};
+class SliceCmp : public BaseCmp
+{
+ using Rust::TyTy::BaseCmp::visit;
+
+public:
+ SliceCmp (const SliceType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
+ {}
+
+ void visit (const SliceType &type) override
+ {
+ // check base type
+ const BaseType *base_element = base->get_element_type ();
+ const BaseType *other_element = type.get_element_type ();
+ if (!base_element->can_eq (other_element, emit_error_flag))
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
+ void visit (const ParamType &type) override { ok = true; }
+
+private:
+ const BaseType *get_base () const override { return base; }
+ const SliceType *base;
+};
+
class BoolCmp : public BaseCmp
{
using Rust::TyTy::BaseCmp::visit;
@@ -1258,6 +1317,8 @@ public:
void visit (const ArrayType &) override { ok = true; }
+ void visit (const SliceType &) override { ok = true; }
+
void visit (const BoolType &) override { ok = true; }
void visit (const IntType &) override { ok = true; }
diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h
index 75913f0..4deed55 100644
--- a/gcc/rust/typecheck/rust-tyty-coercion.h
+++ b/gcc/rust/typecheck/rust-tyty-coercion.h
@@ -167,6 +167,17 @@ public:
type.as_string ().c_str ());
}
+ virtual void visit (SliceType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
virtual void visit (BoolType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
@@ -483,6 +494,19 @@ public:
BaseCoercionRules::visit (type);
}
+ void visit (SliceType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCoercionRules::visit (type);
+ }
+
void visit (ADTType &type) override
{
bool is_valid
@@ -836,6 +860,36 @@ private:
ArrayType *base;
};
+class SliceCoercionRules : public BaseCoercionRules
+{
+ using Rust::TyTy::BaseCoercionRules::visit;
+
+public:
+ SliceCoercionRules (SliceType *base) : BaseCoercionRules (base), base (base)
+ {}
+
+ void visit (SliceType &type) override
+ {
+ // check base type
+ auto base_resolved
+ = base->get_element_type ()->unify (type.get_element_type ());
+ if (base_resolved == nullptr)
+ {
+ BaseCoercionRules::visit (type);
+ return;
+ }
+
+ resolved = new SliceType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ TyVar (base_resolved->get_ref ()));
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ SliceType *base;
+};
+
class BoolCoercionRules : public BaseCoercionRules
{
using Rust::TyTy::BaseCoercionRules::visit;
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 906e33d..c1fc2cd 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -185,6 +185,17 @@ public:
type.as_string ().c_str ());
}
+ virtual void visit (SliceType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
virtual void visit (BoolType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
@@ -500,6 +511,19 @@ public:
BaseRules::visit (type);
}
+ void visit (SliceType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
void visit (ADTType &type) override
{
bool is_valid
@@ -850,6 +874,35 @@ private:
ArrayType *base;
};
+class SliceRules : public BaseRules
+{
+ using Rust::TyTy::BaseRules::visit;
+
+public:
+ SliceRules (SliceType *base) : BaseRules (base), base (base) {}
+
+ void visit (SliceType &type) override
+ {
+ // check base type
+ auto base_resolved
+ = base->get_element_type ()->unify (type.get_element_type ());
+ if (base_resolved == nullptr)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = new SliceType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ TyVar (base_resolved->get_ref ()));
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ SliceType *base;
+};
+
class BoolRules : public BaseRules
{
using Rust::TyTy::BaseRules::visit;
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index fa01a71..464e70d 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -33,6 +33,7 @@ public:
virtual void visit (FnType &type) = 0;
virtual void visit (FnPtr &type) = 0;
virtual void visit (ArrayType &type) = 0;
+ virtual void visit (SliceType &type) = 0;
virtual void visit (BoolType &type) = 0;
virtual void visit (IntType &type) = 0;
virtual void visit (UintType &type) = 0;
@@ -61,6 +62,7 @@ public:
virtual void visit (const FnType &type) = 0;
virtual void visit (const FnPtr &type) = 0;
virtual void visit (const ArrayType &type) = 0;
+ virtual void visit (const SliceType &type) = 0;
virtual void visit (const BoolType &type) = 0;
virtual void visit (const IntType &type) = 0;
virtual void visit (const UintType &type) = 0;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 0dde299..fa5dcfb 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -59,6 +59,9 @@ TypeKindFormat::to_string (TypeKind kind)
case TypeKind::ARRAY:
return "ARRAY";
+ case TypeKind::SLICE:
+ return "SLICE";
+
case TypeKind::FNDEF:
return "FnDef";
@@ -840,16 +843,14 @@ ADTType::is_equal (const BaseType &other) const
return false;
}
}
- else
+
+ for (size_t i = 0; i < number_of_variants (); i++)
{
- for (size_t i = 0; i < number_of_variants (); i++)
- {
- const TyTy::VariantDef *a = get_variants ().at (i);
- const TyTy::VariantDef *b = other2.get_variants ().at (i);
+ const TyTy::VariantDef *a = get_variants ().at (i);
+ const TyTy::VariantDef *b = other2.get_variants ().at (i);
- if (!a->is_equal (*b))
- return false;
- }
+ if (!a->is_equal (*b))
+ return false;
}
return true;
@@ -1505,6 +1506,79 @@ ArrayType::clone () const
}
void
+SliceType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+SliceType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+std::string
+SliceType::as_string () const
+{
+ return "[" + get_element_type ()->as_string () + "]";
+}
+
+BaseType *
+SliceType::unify (BaseType *other)
+{
+ SliceRules r (this);
+ return r.unify (other);
+}
+
+BaseType *
+SliceType::coerce (BaseType *other)
+{
+ SliceCoercionRules r (this);
+ return r.coerce (other);
+}
+
+BaseType *
+SliceType::cast (BaseType *other)
+{
+ SliceCastRules r (this);
+ return r.cast (other);
+}
+
+bool
+SliceType::can_eq (const BaseType *other, bool emit_errors) const
+{
+ SliceCmp r (this, emit_errors);
+ return r.can_eq (other);
+}
+
+bool
+SliceType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ return false;
+
+ auto other2 = static_cast<const SliceType &> (other);
+
+ auto this_element_type = get_element_type ();
+ auto other_element_type = other2.get_element_type ();
+
+ return this_element_type->is_equal (*other_element_type);
+}
+
+BaseType *
+SliceType::get_element_type () const
+{
+ return element_type.get_tyty ();
+}
+
+BaseType *
+SliceType::clone () const
+{
+ return new SliceType (get_ref (), get_ty_ref (), ident.locus, element_type,
+ get_combined_refs ());
+}
+
+void
BoolType::accept_vis (TyVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 036d772..85948b2 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -47,6 +47,7 @@ enum TypeKind
POINTER,
PARAM,
ARRAY,
+ SLICE,
FNDEF,
FNPTR,
TUPLE,
@@ -1666,6 +1667,50 @@ private:
HIR::Expr &capacity_expr;
};
+class SliceType : public BaseType
+{
+public:
+ SliceType (HirId ref, Location locus, TyVar base,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ref, TypeKind::SLICE,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ element_type (base)
+ {}
+
+ SliceType (HirId ref, HirId ty_ref, Location locus, TyVar base,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ty_ref, TypeKind::SLICE,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ element_type (base)
+ {}
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ std::string as_string () const override;
+
+ std::string get_name () const override final { return as_string (); }
+
+ BaseType *unify (BaseType *other) override;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
+ BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
+
+ bool is_equal (const BaseType &other) const override;
+
+ BaseType *get_element_type () const;
+
+ BaseType *clone () const final override;
+
+ bool is_concrete () const final override
+ {
+ return get_element_type ()->is_concrete ();
+ }
+
+private:
+ TyVar element_type;
+};
+
class BoolType : public BaseType
{
public:
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index da200e7..cade09d 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -56,6 +56,10 @@ public:
DEREF,
DEREF_MUT,
+ // https://github.com/rust-lang/rust/blob/master/library/core/src/ops/index.rs
+ INDEX,
+ INDEX_MUT,
+
// https://github.com/rust-lang/rust/blob/master/library/core/src/ops/range.rs
RANGE_FULL,
RANGE,
@@ -165,6 +169,18 @@ public:
{
return ItemType::DEREF_MUT;
}
+ else if (item.compare ("index") == 0)
+ {
+ return ItemType::INDEX;
+ }
+ else if (item.compare ("index_mut") == 0)
+ {
+ return ItemType::INDEX_MUT;
+ }
+ else if (item.compare ("RangeFull") == 0)
+ {
+ return ItemType::RANGE_FULL;
+ }
else if (item.compare ("Range") == 0)
{
return ItemType::RANGE;
@@ -241,6 +257,10 @@ public:
return "deref";
case DEREF_MUT:
return "deref_mut";
+ case INDEX:
+ return "index";
+ case INDEX_MUT:
+ return "index_mut";
case RANGE_FULL:
return "RangeFull";
case RANGE:
diff --git a/gcc/testsuite/rust/compile/torture/range-lang-item1.rs b/gcc/testsuite/rust/compile/torture/range-lang-item1.rs
new file mode 100644
index 0000000..8694616
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/range-lang-item1.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w" }
+#[lang = "RangeFull"]
+pub struct RangeFull;
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "RangeFrom"]
+pub struct RangeFrom<Idx> {
+ pub start: Idx,
+}
+
+#[lang = "RangeTo"]
+pub struct RangeTo<Idx> {
+ pub end: Idx,
+}
+
+#[lang = "RangeInclusive"]
+pub struct RangeInclusive<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+fn test() {
+ let a = 1..2; // range
+ let b = 1..; // range from
+ let c = ..3; // range to
+ let d = 0..=2; // range inclusive
+}
diff --git a/gcc/testsuite/rust/compile/usize1.rs b/gcc/testsuite/rust/compile/usize1.rs
index 8c12789..c7e746b 100644
--- a/gcc/testsuite/rust/compile/usize1.rs
+++ b/gcc/testsuite/rust/compile/usize1.rs
@@ -2,4 +2,5 @@ fn main() {
let a = [1, 2, 3];
let b: u32 = 1;
let c = a[b]; // { dg-error "expected .usize. got .u32." }
+ // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/rust/execute/torture/index1.rs b/gcc/testsuite/rust/execute/torture/index1.rs
new file mode 100644
index 0000000..4682978
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/index1.rs
@@ -0,0 +1,28 @@
+// { dg-additional-options "-w" }
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+struct Foo(i32, i32);
+impl Index<isize> for Foo {
+ type Output = i32;
+
+ fn index(&self, index: isize) -> &i32 {
+ if index == 0 {
+ &self.0
+ } else {
+ &self.1
+ }
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo(1, 2);
+ let b = a[0];
+ let c = a[1];
+
+ c - b - 1
+}