aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-02-25 11:14:37 +0000
committerGitHub <noreply@github.com>2022-02-25 11:14:37 +0000
commitd3a4cf93b73fb32ab8d18541cc4fa5ff7b74c8e8 (patch)
tree188edbabfaa677bf7971b44a2450f83f4ba0cfba
parentbf92a1012264f2544e73a7a8dd0ac1e473c7f658 (diff)
parent22c6bca60a9bc80c043e4da9a94cb80023dde04c (diff)
downloadgcc-d3a4cf93b73fb32ab8d18541cc4fa5ff7b74c8e8.zip
gcc-d3a4cf93b73fb32ab8d18541cc4fa5ff7b74c8e8.tar.gz
gcc-d3a4cf93b73fb32ab8d18541cc4fa5ff7b74c8e8.tar.bz2
Merge #974
974: Add support for ranges and index lang items along with the TyTy::SliceType r=philberty a=philberty This PR contains more code to begin supporting Slices which requires support for more intrinsic, range and index lang items. More work is needed to support slices such as the const_ptr lang item and the offset intrinsic but this is a big PR already and adds support for more lang items along the way. Fixes #975 Addresses #849 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-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
+}