aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/backend/rust-compile-base.h11
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc249
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h16
-rw-r--r--gcc/rust/backend/rust-compile-item.h3
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc22
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.h5
-rw-r--r--gcc/rust/backend/rust-compile-var-decl.h1
-rw-r--r--gcc/rust/backend/rust-compile.cc5
-rw-r--r--gcc/rust/typecheck/rust-autoderef.cc242
-rw-r--r--gcc/rust/typecheck/rust-autoderef.h98
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.h349
-rw-r--r--gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h18
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h26
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h152
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h59
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h10
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc2
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h145
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h3
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc123
-rw-r--r--gcc/rust/typecheck/rust-tyty.h72
-rw-r--r--gcc/testsuite/rust/execute/torture/method2.rs76
25 files changed, 1002 insertions, 690 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index dcb2d2c..f7f2489 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -89,6 +89,7 @@ GRS_OBJS = \
rust/rust-hir-type-check-struct.o \
rust/rust-hir-address-taken.o \
rust/rust-hir-type-check-pattern.o \
+ rust/rust-autoderef.o \
rust/rust-substitution-mapper.o \
rust/rust-lint-marklive.o \
rust/rust-hir-type-check-path.o \
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index e963176..902bedc 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -60,6 +60,17 @@ protected:
bool verify_array_capacities (tree ltype, tree rtype, Location ltype_locus,
Location rtype_locus);
+
+ tree query_compile (HirId ref, TyTy::BaseType *lookup,
+ const HIR::PathIdentSegment &final_segment,
+ const Analysis::NodeMapping &mappings,
+ Location expr_locus, bool is_qualified_path);
+
+ tree resolve_adjustements (std::vector<Resolver::Adjustment> &adjustments,
+ tree expression, Location locus);
+
+ tree resolve_deref_adjustment (Resolver::Adjustment &adjustment,
+ tree expression, Location locus);
};
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 33237e5..c58d29d 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -23,7 +23,6 @@
#include "rust-hir-trait-resolve.h"
#include "rust-hir-path-probe.h"
#include "rust-hir-type-bounds.h"
-#include "rust-hir-dot-operator.h"
#include "rust-compile-pattern.h"
#include "rust-constexpr.h"
@@ -574,25 +573,9 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
expr.get_mappings ().get_hirid (), &adjustments);
rust_assert (ok);
- for (auto &adjustment : *adjustments)
- {
- switch (adjustment.get_type ())
- {
- case Resolver::Adjustment::AdjustmentType::IMM_REF:
- case Resolver::Adjustment::AdjustmentType::MUT_REF:
- self = ctx->get_backend ()->address_expression (
- self, expr.get_receiver ()->get_locus ());
- break;
-
- case Resolver::Adjustment::AdjustmentType::DEREF_REF:
- tree expected_type
- = TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
- self = ctx->get_backend ()->indirect_expression (
- expected_type, self, true, /* known_valid*/
- expr.get_receiver ()->get_locus ());
- break;
- }
- }
+ // apply adjustments for the fn call
+ self = resolve_adjustements (*adjustments, self,
+ expr.get_receiver ()->get_locus ());
std::vector<tree> args;
args.push_back (self); // adjusted self
@@ -737,11 +720,10 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
if (resolved_item != nullptr)
{
if (!fntype->has_subsititions_defined ())
- return CompileInherentImplItem::Compile (receiver, resolved_item, ctx,
- true);
+ return CompileInherentImplItem::Compile (resolved_item, ctx, true);
- return CompileInherentImplItem::Compile (receiver, resolved_item, ctx,
- true, fntype);
+ return CompileInherentImplItem::Compile (resolved_item, ctx, true,
+ fntype);
}
// it might be resolved to a trait item
@@ -785,24 +767,20 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
}
else
{
- std::vector<Resolver::Adjustment> adjustments;
- Resolver::PathProbeCandidate *candidate
- = Resolver::MethodResolution::Select (candidates, root, adjustments);
-
// FIXME this will be a case to return error_mark_node, there is
// an error scenario where a Trait Foo has a method Bar, but this
// receiver does not implement this trait or has an incompatible
// implementation and we should just return error_mark_node
- rust_assert (candidate != nullptr);
- rust_assert (candidate->is_impl_candidate ());
- HIR::ImplItem *impl_item = candidate->item.impl.impl_item;
+ rust_assert (candidates.size () == 1);
+ auto &candidate = candidates.at (0);
+ rust_assert (candidate.is_impl_candidate ());
+
+ HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
if (!fntype->has_subsititions_defined ())
- return CompileInherentImplItem::Compile (receiver, impl_item, ctx,
- true);
+ return CompileInherentImplItem::Compile (impl_item, ctx, true);
- return CompileInherentImplItem::Compile (receiver, impl_item, ctx, true,
- fntype);
+ return CompileInherentImplItem::Compile (impl_item, ctx, true, fntype);
}
}
@@ -868,29 +846,8 @@ CompileExpr::resolve_operator_overload (
expr.get_mappings ().get_hirid (), &adjustments);
rust_assert (ok);
- // FIXME refactor this out
- tree self = lhs;
- for (auto &adjustment : *adjustments)
- {
- switch (adjustment.get_type ())
- {
- case Resolver::Adjustment::AdjustmentType::IMM_REF:
- case Resolver::Adjustment::AdjustmentType::MUT_REF:
- self
- = ctx->get_backend ()->address_expression (self,
- lhs_expr->get_locus ());
- break;
-
- case Resolver::Adjustment::AdjustmentType::DEREF_REF:
- tree expected_type
- = TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
- self
- = ctx->get_backend ()->indirect_expression (expected_type, self,
- true, /* known_valid*/
- lhs_expr->get_locus ());
- break;
- }
- }
+ // apply adjustments for the fn call
+ tree self = resolve_adjustements (*adjustments, lhs, lhs_expr->get_locus ());
std::vector<tree> args;
args.push_back (self); // adjusted self
@@ -1221,106 +1178,82 @@ CompileExpr::array_copied_expr (Location expr_locus,
expr_locus);
}
-// tree
-// CompileExpr::array_copied_expr (Location expr_locus, tree array_type,
-// HIR::ArrayElemsCopied &elems)
-// {
-// // create tmp for the result
-// fncontext fnctx = ctx->peek_fn ();
-// Location start_location = expr_locus;
-// Location end_location = expr_locus;
-// tree fndecl = fnctx.fndecl;
-// tree enclosing_scope = ctx->peek_enclosing_scope ();
-
-// bool is_address_taken = false;
-// tree result_var_stmt = nullptr;
-// Bvariable *result
-// = ctx->get_backend ()->temporary_variable (fnctx.fndecl,
-// enclosing_scope,
-// array_type, NULL,
-// is_address_taken, expr_locus,
-// &result_var_stmt);
-// ctx->add_statement (result_var_stmt);
-
-// // get the compiled value
-// tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (),
-// ctx);
-
-// // lets assign each index in the array
-// TyTy::BaseType *capacity_tyty = nullptr;
-// HirId capacity_ty_id
-// = elems.get_num_copies_expr ()->get_mappings ().get_hirid ();
-// bool ok = ctx->get_tyctx ()->lookup_type (capacity_ty_id,
-// &capacity_tyty); rust_assert (ok); tree capacity_type =
-// TyTyResolveCompile::compile (ctx, capacity_tyty); tree capacity_expr =
-// CompileExpr::Compile (elems.get_num_copies_expr (), ctx);
-
-// // create a loop for this with assignments to array_index exprs
-// tree index_type = capacity_type;
-// Bvariable *idx
-// = ctx->get_backend ()->temporary_variable (fnctx.fndecl,
-// enclosing_scope,
-// index_type, NULL,
-// is_address_taken, expr_locus,
-// &result_var_stmt);
-// ctx->add_statement (result_var_stmt);
-
-// // set index to zero
-// tree index_lvalue = error_mark_node;
-// tree zero = build_int_cst (index_type, 0);
-// tree index_assignment
-// = ctx->get_backend ()->assignment_statement (fnctx.fndecl,
-// index_lvalue,
-// zero, expr_locus);
-// ctx->add_statement (index_assignment);
-
-// // BEGIN loop block
-// tree loop_body = ctx->get_backend ()->block (fndecl, enclosing_scope, {},
-// start_location, end_location);
-// ctx->push_block (loop_body);
-
-// // loop predicate
-// tree loop_predicate
-// = fold_build2_loc (expr_locus.gcc_location (), GE_EXPR,
-// boolean_type_node,
-// ctx->get_backend ()->var_expression (idx, expr_locus),
-// capacity_expr);
-// tree exit_expr = fold_build1_loc (expr_locus.gcc_location (), EXIT_EXPR,
-// void_type_node, loop_predicate);
-// tree break_stmt
-// = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr);
-// ctx->add_statement (break_stmt);
-
-// // increment index
-// tree increment
-// = fold_build2_loc (expr_locus.gcc_location (), POSTINCREMENT_EXPR,
-// index_type,
-// ctx->get_backend ()->var_expression (idx, expr_locus),
-// build_int_cst (index_type, 1));
-
-// // create index_assess
-// tree index_access = ctx->get_backend ()->array_index_expression (
-// ctx->get_backend ()->var_expression (result, expr_locus), increment,
-// expr_locus);
-
-// // create assignment to index_access
-// tree array_assignment
-// = ctx->get_backend ()->assignment_statement (fnctx.fndecl,
-// index_access,
-// translated_expr, expr_locus);
-// ctx->add_statement (array_assignment);
-
-// // END loop block
-// ctx->pop_block ();
-
-// tree loop_expr = ctx->get_backend ()->loop_expression (loop_body,
-// expr_locus); tree loop_stmt
-// = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr);
-// ctx->add_statement (loop_stmt);
-
-// // result is the tmp
-// return ctx->get_backend ()->var_expression (result, expr_locus);
-// }
+tree
+HIRCompileBase::resolve_adjustements (
+ std::vector<Resolver::Adjustment> &adjustments, tree expression,
+ Location locus)
+{
+ tree e = expression;
+ for (auto &adjustment : adjustments)
+ {
+ switch (adjustment.get_type ())
+ {
+ case Resolver::Adjustment::AdjustmentType::ERROR:
+ return error_mark_node;
+
+ case Resolver::Adjustment::AdjustmentType::IMM_REF:
+ case Resolver::Adjustment::AdjustmentType::MUT_REF:
+ e = ctx->get_backend ()->address_expression (e, locus);
+ break;
+
+ case Resolver::Adjustment::AdjustmentType::DEREF_REF:
+ e = resolve_deref_adjustment (adjustment, e, locus);
+ break;
+ }
+ }
+
+ return e;
+}
+
+tree
+HIRCompileBase::resolve_deref_adjustment (Resolver::Adjustment &adjustment,
+ tree expression, Location locus)
+{
+ rust_assert (adjustment.is_deref_adjustment ());
+
+ tree expected_type
+ = TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
+ if (!adjustment.has_operator_overload ())
+ {
+ return ctx->get_backend ()->indirect_expression (expected_type,
+ expression,
+ true, /* known_valid*/
+ locus);
+ }
+
+ TyTy::FnType *lookup = adjustment.get_deref_operator_fn ();
+ HIR::ImplItem *resolved_item = adjustment.get_deref_hir_item ();
+
+ tree fn_address = error_mark_node;
+ if (!lookup->has_subsititions_defined ())
+ fn_address = CompileInherentImplItem::Compile (resolved_item, ctx, true,
+ nullptr, true, locus);
+ else
+ fn_address = CompileInherentImplItem::Compile (resolved_item, ctx, true,
+ lookup, true, locus);
+
+ // does it need a reference to call
+ tree adjusted_argument = expression;
+ bool needs_borrow = adjustment.get_deref_adjustment_type ()
+ != Resolver::Adjustment::AdjustmentType::ERROR;
+ if (needs_borrow)
+ {
+ adjusted_argument
+ = ctx->get_backend ()->address_expression (expression, locus);
+ }
+
+ // make the call
+ auto fncontext = ctx->peek_fn ();
+ tree deref_call
+ = ctx->get_backend ()->call_expression (fncontext.fndecl, fn_address,
+ {adjusted_argument}, nullptr,
+ locus);
+
+ // do the indirect expression
+ return ctx->get_backend ()->indirect_expression (expected_type, deref_call,
+ true, /* known_valid*/
+ locus);
+}
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index 7bef6ae..82b7c6d 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -34,14 +34,12 @@ class CompileInherentImplItem : public HIRCompileBase
using Rust::Compile::HIRCompileBase::visit;
public:
- static tree Compile (const TyTy::BaseType *self, HIR::ImplItem *item,
- Context *ctx, bool compile_fns,
+ static tree Compile (HIR::ImplItem *item, Context *ctx, bool compile_fns,
TyTy::BaseType *concrete = nullptr,
bool is_query_mode = false,
Location ref_locus = Location ())
{
- CompileInherentImplItem compiler (self, ctx, compile_fns, concrete,
- ref_locus);
+ CompileInherentImplItem compiler (ctx, compile_fns, concrete, ref_locus);
item->accept_vis (compiler);
if (is_query_mode
@@ -307,15 +305,13 @@ public:
}
private:
- CompileInherentImplItem (const TyTy::BaseType *self, Context *ctx,
- bool compile_fns, TyTy::BaseType *concrete,
- Location ref_locus)
- : HIRCompileBase (ctx), self (self), compile_fns (compile_fns),
- concrete (concrete), reference (ctx->get_backend ()->error_expression ()),
+ CompileInherentImplItem (Context *ctx, bool compile_fns,
+ TyTy::BaseType *concrete, Location ref_locus)
+ : HIRCompileBase (ctx), compile_fns (compile_fns), concrete (concrete),
+ reference (ctx->get_backend ()->error_expression ()),
ref_locus (ref_locus)
{}
- const TyTy::BaseType *self;
bool compile_fns;
TyTy::BaseType *concrete;
tree reference;
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index c35efcc..b3c5ba8 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -395,8 +395,7 @@ public:
}
for (auto &impl_item : impl_block.get_impl_items ())
- CompileInherentImplItem::Compile (self_lookup, impl_item.get (), ctx,
- compile_fns);
+ CompileInherentImplItem::Compile (impl_item.get (), ctx, compile_fns);
}
void visit (HIR::ExternBlock &extern_block) override
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index c1d0778..5c727d6 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -152,10 +152,10 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
// let the query system figure it out
return query_compile (ref, lookup, final_segment, mappings, expr_locus,
is_qualified_path);
-} // namespace Compile
+}
tree
-ResolvePathRef::query_compile (HirId ref, TyTy::BaseType *lookup,
+HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
const HIR::PathIdentSegment &final_segment,
const Analysis::NodeMapping &mappings,
Location expr_locus, bool is_qualified_path)
@@ -194,13 +194,11 @@ ResolvePathRef::query_compile (HirId ref, TyTy::BaseType *lookup,
rust_assert (ok);
if (!lookup->has_subsititions_defined ())
- return CompileInherentImplItem::Compile (self, resolved_item, ctx,
- true, nullptr, true,
- expr_locus);
+ return CompileInherentImplItem::Compile (resolved_item, ctx, true,
+ nullptr, true, expr_locus);
else
- return CompileInherentImplItem::Compile (self, resolved_item, ctx,
- true, lookup, true,
- expr_locus);
+ return CompileInherentImplItem::Compile (resolved_item, ctx, true,
+ lookup, true, expr_locus);
}
else
{
@@ -278,12 +276,12 @@ ResolvePathRef::query_compile (HirId ref, TyTy::BaseType *lookup,
rust_assert (ok);
if (!lookup->has_subsititions_defined ())
- return CompileInherentImplItem::Compile (self, impl_item, ctx,
- true, nullptr, true,
+ return CompileInherentImplItem::Compile (impl_item, ctx, true,
+ nullptr, true,
expr_locus);
else
- return CompileInherentImplItem::Compile (self, impl_item, ctx,
- true, lookup, true,
+ return CompileInherentImplItem::Compile (impl_item, ctx, true,
+ lookup, true,
expr_locus);
lookup->set_ty_ref (impl_item->get_impl_mappings ().get_hirid ());
diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h
index 56f82d1..97a79e2 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.h
+++ b/gcc/rust/backend/rust-compile-resolve-path.h
@@ -57,11 +57,6 @@ private:
const Analysis::NodeMapping &mappings, Location locus,
bool is_qualified_path);
- tree query_compile (HirId ref, TyTy::BaseType *lookup,
- const HIR::PathIdentSegment &final_segment,
- const Analysis::NodeMapping &mappings,
- Location expr_locus, bool is_qualified_path);
-
tree resolved;
};
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index 4b52dcd..51affe0 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -49,6 +49,7 @@ public:
address_taken_context->lookup_addess_taken (
stmt.get_mappings ().get_hirid (), &address_taken);
+
translated_type = TyTyResolveCompile::compile (ctx, resolved_type);
stmt.get_pattern ()->accept_vis (*this);
}
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index a97ad4d..b17c438 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -528,9 +528,8 @@ HIRCompileBase::compute_address_for_trait_item (
lookup_fntype = lookup_fntype->handle_substitions (mappings);
}
- return CompileInherentImplItem::Compile (root, associated_function, ctx,
- true, lookup_fntype, true,
- locus);
+ return CompileInherentImplItem::Compile (associated_function, ctx, true,
+ lookup_fntype, true, locus);
}
// we can only compile trait-items with a body
diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc
new file mode 100644
index 0000000..44f0906
--- /dev/null
+++ b/gcc/rust/typecheck/rust-autoderef.cc
@@ -0,0 +1,242 @@
+// Copyright (C) 2020-2021 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-autoderef.h"
+#include "rust-hir-path-probe.h"
+#include "rust-hir-dot-operator.h"
+
+namespace Rust {
+namespace Resolver {
+
+static bool
+resolve_operator_overload_fn (
+ Analysis::RustLangItem::ItemType lang_item_type, const TyTy::BaseType *ty,
+ TyTy::FnType **resolved_fn, HIR::ImplItem **impl_item,
+ Adjustment::AdjustmentType *requires_ref_adjustment);
+
+bool
+Adjuster::needs_address (const std::vector<Adjustment> &adjustments)
+{
+ for (auto &adjustment : adjustments)
+ {
+ switch (adjustment.get_type ())
+ {
+ case Adjustment::AdjustmentType::IMM_REF:
+ case Adjustment::AdjustmentType::MUT_REF:
+ case Adjustment::AdjustmentType::DEREF_REF:
+ return true;
+
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
+TyTy::BaseType *
+Adjuster::adjust_type (const std::vector<Adjustment> &adjustments)
+{
+ if (adjustments.size () == 0)
+ return base->clone ();
+
+ return adjustments.back ().get_expected ()->clone ();
+}
+
+Adjustment
+Adjuster::try_deref_type (const TyTy::BaseType *ty)
+{
+ // probe for the lang-item
+ TyTy::BaseType *resolved_base = ty->clone ();
+
+ HIR::ImplItem *impl_item = nullptr;
+ TyTy::FnType *fn = nullptr;
+ Adjustment::AdjustmentType requires_ref_adjustment
+ = Adjustment::AdjustmentType::ERROR;
+ bool operator_overloaded
+ = resolve_operator_overload_fn (Analysis::RustLangItem::ItemType::DEREF, ty,
+ &fn, &impl_item, &requires_ref_adjustment);
+ if (operator_overloaded)
+ {
+ resolved_base = fn->get_return_type ()->clone ();
+ }
+
+ bool is_valid_type = resolved_base->get_kind () == TyTy::TypeKind::REF;
+ if (!is_valid_type)
+ return Adjustment::get_error ();
+
+ TyTy::ReferenceType *ref_base
+ = static_cast<TyTy::ReferenceType *> (resolved_base);
+
+ auto infered = ref_base->get_base ()->clone ();
+
+ return Adjustment::get_op_overload_deref_adjustment (infered, fn, impl_item,
+ requires_ref_adjustment);
+}
+
+static bool
+resolve_operator_overload_fn (
+ Analysis::RustLangItem::ItemType lang_item_type, const TyTy::BaseType *ty,
+ TyTy::FnType **resolved_fn, HIR::ImplItem **impl_item,
+ Adjustment::AdjustmentType *requires_ref_adjustment)
+{
+ auto context = TypeCheckContext::get ();
+ auto mappings = Analysis::Mappings::get ();
+
+ // 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);
+
+ if (!lang_item_defined)
+ return false;
+
+ auto segment = HIR::PathIdentSegment (associated_item_name);
+ auto candidate
+ = MethodResolver::Probe (ty, HIR::PathIdentSegment (associated_item_name),
+ true);
+
+ bool have_implementation_for_lang_item = !candidate.is_error ();
+ if (!have_implementation_for_lang_item)
+ return false;
+
+ // Get the adjusted self
+ Adjuster adj (ty);
+ 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;
+ }
+ }
+ }
+
+ TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
+
+ // rust only support impl item deref operator overloading ie you must have an
+ // impl block for it
+ rust_assert (candidate.candidate.type
+ == PathProbeCandidate::CandidateType::IMPL_FUNC);
+ *impl_item = candidate.candidate.item.impl.impl_item;
+
+ 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 ());
+
+ if (fn->needs_substitution ())
+ {
+ if (ty->get_kind () == TyTy::TypeKind::ADT)
+ {
+ const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (ty);
+
+ 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);
+ }
+ }
+ }
+ else
+ {
+ rust_assert (candidate.adjustments.size () < 2);
+
+ // lets infer the params for this we could probably fix this up by
+ // actually just performing a substitution of a single param but this
+ // seems more generic i think.
+ //
+ // this is the case where we had say Foo<&Bar>> and we have derefed to
+ // the &Bar and we are trying to match a method self of Bar which
+ // requires another deref which is matched to the deref trait impl of
+ // &&T so this requires another reference and deref call
+
+ lookup = fn->infer_substitions (Location ());
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
+ fn = static_cast<TyTy::FnType *> (lookup);
+ fn->get_self_type ()->unify (adjusted_self);
+ lookup = fn;
+ }
+ }
+
+ if (candidate.adjustments.size () > 0)
+ *requires_ref_adjustment = candidate.adjustments.at (0).get_type ();
+
+ *resolved_fn = static_cast<TyTy::FnType *> (lookup);
+
+ return true;
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-autoderef.h b/gcc/rust/typecheck/rust-autoderef.h
index ef3827d..762b3e8 100644
--- a/gcc/rust/typecheck/rust-autoderef.h
+++ b/gcc/rust/typecheck/rust-autoderef.h
@@ -29,15 +29,26 @@ class Adjustment
public:
enum AdjustmentType
{
+ ERROR,
+
IMM_REF,
MUT_REF,
DEREF_REF
};
+ // ctor for all adjustments except derefs
Adjustment (AdjustmentType type, const TyTy::BaseType *expected)
- : type (type), expected (expected)
+ : Adjustment (type, expected, nullptr, nullptr, AdjustmentType::ERROR)
{}
+ static Adjustment get_op_overload_deref_adjustment (
+ const TyTy::BaseType *expected, TyTy::FnType *fn, HIR::ImplItem *deref_item,
+ Adjustment::AdjustmentType requires_ref_adjustment)
+ {
+ return Adjustment (Adjustment::DEREF_REF, expected, fn, deref_item,
+ requires_ref_adjustment);
+ }
+
AdjustmentType get_type () const { return type; }
const TyTy::BaseType *get_expected () const { return expected; }
@@ -52,6 +63,8 @@ public:
{
switch (type)
{
+ case AdjustmentType::ERROR:
+ return "ERROR";
case AdjustmentType::IMM_REF:
return "IMM_REF";
case AdjustmentType::MUT_REF:
@@ -63,9 +76,41 @@ public:
return "";
}
+ static Adjustment get_error () { return Adjustment{ERROR, nullptr}; }
+
+ bool is_error () const { return type == ERROR; }
+
+ bool is_deref_adjustment () const { return type == DEREF_REF; }
+
+ bool has_operator_overload () const { return deref_operator_fn != nullptr; }
+
+ TyTy::FnType *get_deref_operator_fn () const { return deref_operator_fn; }
+
+ AdjustmentType get_deref_adjustment_type () const
+ {
+ return requires_ref_adjustment;
+ }
+
+ HIR::ImplItem *get_deref_hir_item () const { return deref_item; }
+
private:
+ Adjustment (AdjustmentType type, const TyTy::BaseType *expected,
+ TyTy::FnType *deref_operator_fn, HIR::ImplItem *deref_item,
+ Adjustment::AdjustmentType requires_ref_adjustment)
+ : type (type), expected (expected), deref_operator_fn (deref_operator_fn),
+ deref_item (deref_item), requires_ref_adjustment (requires_ref_adjustment)
+ {}
+
AdjustmentType type;
const TyTy::BaseType *expected;
+
+ // - only used for deref operator_overloads
+ //
+ // the fn that we are calling
+ TyTy::FnType *deref_operator_fn;
+ HIR::ImplItem *deref_item;
+ // operator overloads can requre a reference
+ Adjustment::AdjustmentType requires_ref_adjustment;
};
class Adjuster
@@ -73,56 +118,11 @@ class Adjuster
public:
Adjuster (const TyTy::BaseType *ty) : base (ty) {}
- static bool needs_address (const std::vector<Adjustment> &adjustments)
- {
- for (auto &adjustment : adjustments)
- {
- switch (adjustment.get_type ())
- {
- case Adjustment::AdjustmentType::IMM_REF:
- case Adjustment::AdjustmentType::MUT_REF:
- return true;
-
- default:
- break;
- }
- }
+ TyTy::BaseType *adjust_type (const std::vector<Adjustment> &adjustments);
- return false;
- }
+ static bool needs_address (const std::vector<Adjustment> &adjustments);
- TyTy::BaseType *adjust_type (const std::vector<Adjustment> &adjustments)
- {
- TyTy::BaseType *ty = base->clone ();
- for (auto &adjustment : adjustments)
- {
- switch (adjustment.get_type ())
- {
- case Adjustment::AdjustmentType::IMM_REF:
- ty = new TyTy::ReferenceType (ty->get_ref (),
- TyTy::TyVar (ty->get_ref ()),
- Mutability::Imm);
- break;
-
- case Adjustment::AdjustmentType::MUT_REF:
- ty = new TyTy::ReferenceType (ty->get_ref (),
- TyTy::TyVar (ty->get_ref ()),
- Mutability::Mut);
- break;
-
- case Adjustment::AdjustmentType::DEREF_REF:
- // FIXME this really needs to support deref lang-item operator
- // overloads
- rust_assert (ty->get_kind () == TyTy::TypeKind::REF);
- const TyTy::ReferenceType *rr
- = static_cast<const TyTy::ReferenceType *> (ty);
- ty = rr->get_base ();
-
- break;
- }
- }
- return ty;
- }
+ static Adjustment try_deref_type (const TyTy::BaseType *ty);
private:
const TyTy::BaseType *base;
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index 067ae2c..6605902 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -20,161 +20,310 @@
#define RUST_HIR_DOT_OPERATOR
#include "rust-hir-path-probe.h"
+#include "rust-hir-trait-resolve.h"
namespace Rust {
namespace Resolver {
-// lookup if method exists for current type
-// if exists: done
-// if not: check again for auto-ref and auto-mut-ref
-// deref and start again with 1.*/
+struct MethodCandidate
+{
+ PathProbeCandidate candidate;
+ std::vector<Adjustment> adjustments;
+
+ static MethodCandidate get_error ()
+ {
+ return {PathProbeCandidate::get_error (), {}};
+ }
-// https://doc.rust-lang.org/nightly/nomicon/dot-operator.html
+ bool is_error () const { return candidate.is_error (); }
+};
-class MethodResolution
+class MethodResolver : public TypeCheckBase
{
+protected:
+ using Rust::Resolver::TypeCheckBase::visit;
+
public:
- static PathProbeCandidate *
- Select (std::vector<PathProbeCandidate> &candidates,
- const TyTy::BaseType *receiver, std::vector<Adjustment> &adjustments)
+ static MethodCandidate Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &segment_name,
+ bool autoderef_flag = false)
{
const TyTy::BaseType *r = receiver;
+ std::vector<Adjustment> adjustments;
while (true)
{
- PathProbeCandidate *c = nullptr;
+ PathProbeCandidate c = PathProbeCandidate::get_error ();
+ const std::vector<TyTy::TypeBoundPredicate> &specified_bounds
+ = r->get_specified_bounds ();
// 1. try raw
- c = Try (candidates, r);
- if (c != nullptr)
- return c;
+ MethodResolver raw (*r, segment_name, specified_bounds);
+ c = raw.select ();
+ if (!c.is_error ())
+ return MethodCandidate{c, adjustments};
// 2. try ref
TyTy::ReferenceType *r1
= new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
Mutability::Imm);
- c = Try (candidates, r1);
- if (c != nullptr)
+ MethodResolver imm_ref (*r1, segment_name, specified_bounds);
+ c = imm_ref.select ();
+ if (!c.is_error ())
{
adjustments.push_back (
Adjustment (Adjustment::AdjustmentType::IMM_REF, r1));
- return c;
+ return MethodCandidate{c, adjustments};
}
// 3. try mut ref
TyTy::ReferenceType *r2
= new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
Mutability::Mut);
- c = Try (candidates, r2);
- if (c != nullptr)
+ MethodResolver mut_ref (*r2, segment_name, specified_bounds);
+ c = mut_ref.select ();
+ if (!c.is_error ())
{
adjustments.push_back (
Adjustment (Adjustment::AdjustmentType::MUT_REF, r2));
- return c;
+ return MethodCandidate{c, adjustments};
}
// 4. deref to to 1, if cannot deref then quit
- bool can_deref = r->get_kind () == TyTy::TypeKind::REF;
- if (!can_deref)
- return nullptr;
-
- // FIXME this needs to use deref trait and fall back to unsized to
- // remove array syntax
-
- const TyTy::ReferenceType *rr
- = static_cast<const TyTy::ReferenceType *> (r);
- r = rr->get_base ();
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::DEREF_REF, r));
+ if (autoderef_flag)
+ {
+ return MethodCandidate::get_error ();
+ }
+ else
+ {
+ Adjustment deref = Adjuster::try_deref_type (r);
+ if (deref.is_error ())
+ return MethodCandidate::get_error ();
+
+ r = deref.get_expected ();
+ adjustments.push_back (deref);
+ }
}
- return nullptr;
+ return MethodCandidate::get_error ();
}
-private:
- static PathProbeCandidate *Try (std::vector<PathProbeCandidate> &candidates,
- const TyTy::BaseType *receiver)
+protected:
+ PathProbeCandidate select ()
{
- TypeCheckContext *context = TypeCheckContext::get ();
+ struct impl_item_candidate
+ {
+ HIR::Function *item;
+ HIR::ImplBlock *impl_block;
+ TyTy::FnType *ty;
+ };
+
+ // assemble inherent impl items
+ std::vector<impl_item_candidate> inherent_impl_fns;
+ mappings->iterate_impl_items ([&] (HirId id, HIR::ImplItem *item,
+ HIR::ImplBlock *impl) mutable -> bool {
+ bool is_trait_impl = impl->has_trait_ref ();
+ if (is_trait_impl)
+ return true;
+
+ bool is_fn
+ = item->get_impl_item_type () == HIR::ImplItem::ImplItemType::FUNCTION;
+ if (!is_fn)
+ return true;
+
+ HIR::Function *func = static_cast<HIR::Function *> (item);
+ if (!func->is_method ())
+ return true;
+
+ bool name_matches
+ = func->get_function_name ().compare (segment_name.as_string ()) == 0;
+ if (!name_matches)
+ return true;
+
+ TyTy::BaseType *ty = nullptr;
+ if (!context->lookup_type (func->get_mappings ().get_hirid (), &ty))
+ return true;
+ if (ty->get_kind () == TyTy::TypeKind::ERROR)
+ return true;
+
+ rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
+
+ inherent_impl_fns.push_back ({func, impl, fnty});
+
+ return true;
+ });
+
+ struct trait_item_candidate
+ {
+ const HIR::TraitItemFunc *item;
+ const HIR::Trait *trait;
+ TyTy::FnType *ty;
+ const TraitReference *reference;
+ const TraitItemReference *item_ref;
+ };
+
+ std::vector<trait_item_candidate> trait_fns;
+ mappings->iterate_impl_blocks ([&] (HirId id,
+ HIR::ImplBlock *impl) mutable -> bool {
+ bool is_trait_impl = impl->has_trait_ref ();
+ if (!is_trait_impl)
+ return true;
+
+ // look for impl implementation else lookup the associated trait item
+ for (auto &impl_item : impl->get_impl_items ())
+ {
+ bool is_fn = impl_item->get_impl_item_type ()
+ == HIR::ImplItem::ImplItemType::FUNCTION;
+ if (!is_fn)
+ continue;
+
+ HIR::Function *func = static_cast<HIR::Function *> (impl_item.get ());
+ if (!func->is_method ())
+ continue;
+
+ bool name_matches
+ = func->get_function_name ().compare (segment_name.as_string ())
+ == 0;
+ if (!name_matches)
+ continue;
- // probe impls
- for (auto &c : candidates)
+ TyTy::BaseType *ty = nullptr;
+ if (!context->lookup_type (func->get_mappings ().get_hirid (), &ty))
+ continue;
+ if (ty->get_kind () == TyTy::TypeKind::ERROR)
+ continue;
+
+ rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
+
+ inherent_impl_fns.push_back ({func, impl, fnty});
+ return true;
+ }
+
+ TraitReference *trait_ref
+ = TraitResolver::Resolve (*impl->get_trait_ref ().get ());
+ rust_assert (!trait_ref->is_error ());
+
+ auto item_ref
+ = trait_ref->lookup_trait_item (segment_name.as_string (),
+ TraitItemReference::TraitItemType::FN);
+ if (item_ref->is_error ())
+ return true;
+
+ const HIR::Trait *trait = trait_ref->get_hir_trait_ref ();
+ HIR::TraitItem *item = item_ref->get_hir_trait_item ();
+ rust_assert (item->get_item_kind ()
+ == HIR::TraitItem::TraitItemKind::FUNC);
+ HIR::TraitItemFunc *func = static_cast<HIR::TraitItemFunc *> (item);
+
+ TyTy::BaseType *ty = item_ref->get_tyty ();
+ rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
+
+ trait_item_candidate candidate{func, trait, fnty, trait_ref, item_ref};
+ trait_fns.push_back (candidate);
+
+ return true;
+ });
+
+ // lookup specified bounds for an associated item
+ struct precdicate_candidate
+ {
+ TyTy::TypeBoundPredicateItem lookup;
+ TyTy::FnType *fntype;
+ };
+
+ std::vector<precdicate_candidate> predicate_items;
+ for (auto &bound : specified_bounds)
{
- bool is_func = c.type == PathProbeCandidate::CandidateType::IMPL_FUNC;
- HIR::ImplBlock *block = c.item.impl.parent;
- if (is_func && !block->has_trait_ref ())
+ TyTy::TypeBoundPredicateItem lookup
+ = bound.lookup_associated_item (segment_name.as_string ());
+ if (lookup.is_error ())
+ continue;
+
+ bool is_fn = lookup.get_raw_item ()->get_trait_item_type ()
+ == TraitItemReference::TraitItemType::FN;
+ if (!is_fn)
+ continue;
+
+ TyTy::BaseType *ty = lookup.get_raw_item ()->get_tyty ();
+ rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
+
+ precdicate_candidate candidate{lookup, fnty};
+ predicate_items.push_back (candidate);
+ }
+
+ for (auto impl_item : inherent_impl_fns)
+ {
+ TyTy::FnType *fn = impl_item.ty;
+ rust_assert (fn->is_method ());
+
+ TyTy::BaseType *fn_self = fn->get_self_type ();
+ if (fn_self->can_eq (&receiver, false))
{
- HIR::Function *func
- = static_cast<HIR::Function *> (c.item.impl.impl_item);
-
- TyTy::BaseType *lookup = nullptr;
- bool ok = context->lookup_type (func->get_mappings ().get_hirid (),
- &lookup);
- rust_assert (ok);
- rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
-
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
- if (fn->is_method ())
- {
- TyTy::BaseType *fn_self = fn->get_self_type ();
- if (fn_self->can_eq (receiver, false, true))
- {
- return &c;
- }
- }
+ PathProbeCandidate::ImplItemCandidate c{impl_item.item,
+ impl_item.impl_block};
+ return PathProbeCandidate (
+ PathProbeCandidate::CandidateType::IMPL_FUNC, fn,
+ impl_item.item->get_locus (), c);
}
}
- // probe trait impls
- for (auto &c : candidates)
+ for (auto trait_item : trait_fns)
{
- bool is_func = c.type == PathProbeCandidate::CandidateType::IMPL_FUNC;
- HIR::ImplBlock *block = c.item.impl.parent;
- if (is_func && block->has_trait_ref ())
+ TyTy::FnType *fn = trait_item.ty;
+ rust_assert (fn->is_method ());
+
+ TyTy::BaseType *fn_self = fn->get_self_type ();
+ if (fn_self->can_eq (&receiver, false))
{
- HIR::Function *func
- = static_cast<HIR::Function *> (c.item.impl.impl_item);
-
- TyTy::BaseType *lookup = nullptr;
- bool ok = context->lookup_type (func->get_mappings ().get_hirid (),
- &lookup);
- rust_assert (ok);
- rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
-
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
- if (fn->is_method ())
- {
- TyTy::BaseType *fn_self = fn->get_self_type ();
- if (fn_self->can_eq (receiver, false, true))
- {
- return &c;
- }
- }
+ PathProbeCandidate::TraitItemCandidate c{trait_item.reference,
+ trait_item.item_ref,
+ nullptr};
+ return PathProbeCandidate (
+ PathProbeCandidate::CandidateType::TRAIT_FUNC, fn,
+ trait_item.item->get_locus (), c);
}
}
- // probe trait bounds
- for (auto &c : candidates)
+ for (auto predicate : predicate_items)
{
- bool is_func = c.type == PathProbeCandidate::CandidateType::TRAIT_FUNC;
- if (is_func)
+ TyTy::FnType *fn = predicate.fntype;
+ rust_assert (fn->is_method ());
+
+ TyTy::BaseType *fn_self = fn->get_self_type ();
+ if (fn_self->can_eq (&receiver, false))
{
- const TraitItemReference *item_ref = c.item.trait.item_ref;
- TyTy::BaseType *lookup = item_ref->get_tyty ();
- rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
-
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
- if (fn->is_method ())
- {
- TyTy::BaseType *fn_self = fn->get_self_type ();
- if (fn_self->can_eq (receiver, false, true))
- {
- return &c;
- }
- }
+ const TraitReference *trait_ref
+ = predicate.lookup.get_parent ()->get ();
+ const TraitItemReference *trait_item
+ = predicate.lookup.get_raw_item ();
+
+ TyTy::BaseType *subst = predicate.lookup.get_tyty_for_receiver (
+ receiver.get_root (),
+ predicate.lookup.get_parent ()->get_generic_args ());
+
+ PathProbeCandidate::TraitItemCandidate c{trait_ref, trait_item,
+ nullptr};
+ return PathProbeCandidate (
+ PathProbeCandidate::CandidateType::TRAIT_FUNC, subst,
+ trait_item->get_locus (), c);
}
}
- return nullptr;
+ return PathProbeCandidate::get_error ();
}
+
+ MethodResolver (const TyTy::BaseType &receiver,
+ const HIR::PathIdentSegment &segment_name,
+ const std::vector<TyTy::TypeBoundPredicate> &specified_bounds)
+ : receiver (receiver), segment_name (segment_name),
+ specified_bounds (specified_bounds)
+ {}
+
+ const TyTy::BaseType &receiver;
+ const HIR::PathIdentSegment &segment_name;
+ const std::vector<TyTy::TypeBoundPredicate> &specified_bounds;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
index 318b34b..2738f95 100644
--- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
+++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
@@ -122,7 +122,7 @@ public:
if (query == candidate)
continue;
- if (query->can_eq (candidate, false, false))
+ if (query->can_eq (candidate, false))
possible_collision (it->second, iy->second);
}
}
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 0c618d3..ae88787 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -32,6 +32,8 @@ struct PathProbeCandidate
{
enum CandidateType
{
+ ERROR,
+
ENUM_VARIANT,
IMPL_CONST,
@@ -108,6 +110,19 @@ struct PathProbeCandidate
return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
|| type == TRAIT_FUNC;
}
+
+ bool is_full_trait_item_candidate () const
+ {
+ return is_trait_candidate () && item.trait.impl == nullptr;
+ }
+
+ static PathProbeCandidate get_error ()
+ {
+ return PathProbeCandidate (ERROR, nullptr, Location (),
+ ImplItemCandidate{nullptr, nullptr});
+ }
+
+ bool is_error () const { return type == ERROR; }
};
class PathProbeType : public TypeCheckBase
@@ -268,7 +283,7 @@ protected:
bool ok = context->lookup_type (impl_ty_id, &impl_block_ty);
rust_assert (ok);
- if (!receiver->can_eq (impl_block_ty, false, false))
+ if (!receiver->can_eq (impl_block_ty, false))
return;
// lets visit the impl_item
@@ -462,6 +477,7 @@ public:
{
switch (c.type)
{
+ case PathProbeCandidate::CandidateType::ERROR:
case PathProbeCandidate::CandidateType::ENUM_VARIANT:
gcc_unreachable ();
break;
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
index 31ebf8b..3573c99 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-ref.h
@@ -234,6 +234,8 @@ public:
+ "]";
}
+ const HIR::Trait *get_hir_trait_ref () const { return hir_trait_ref; }
+
const Analysis::NodeMapping &get_mappings () const
{
return hir_trait_ref->get_mappings ();
@@ -258,6 +260,24 @@ public:
return false;
}
+ bool lookup_trait_item_by_type (const std::string &ident,
+ TraitItemReference::TraitItemType type,
+ TraitItemReference **ref)
+ {
+ for (auto &item : item_refs)
+ {
+ if (item.get_trait_item_type () != type)
+ continue;
+
+ if (ident.compare (item.get_identifier ()) == 0)
+ {
+ *ref = &item;
+ return true;
+ }
+ }
+ return false;
+ }
+
bool lookup_hir_trait_item (const HIR::TraitItem &item,
const TraitItemReference **ref) const
{
@@ -278,7 +298,7 @@ public:
return false;
}
- const TraitItemReference &
+ const TraitItemReference *
lookup_trait_item (const std::string &ident,
TraitItemReference::TraitItemType type) const
{
@@ -288,9 +308,9 @@ public:
continue;
if (ident.compare (item.get_identifier ()) == 0)
- return item;
+ return &item;
}
- return TraitItemReference::error_node ();
+ return &TraitItemReference::error_node ();
}
size_t size () const { return item_refs.size (); }
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 0ac924f..fd89953 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -251,53 +251,10 @@ public:
context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
- // in order to probe of the correct type paths we need the root type, which
- // strips any references
- const TyTy::BaseType *root = receiver_tyty->get_root ();
-
- // https://doc.rust-lang.org/reference/expressions/method-call-expr.html
- // method resolution is complex in rust once we start handling generics and
- // traits. For now we only support looking up the valid name in impl blocks
- // which is simple. There will need to be adjustments to ensure we can turn
- // the receiver into borrowed references etc
-
- bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
- bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
-
- bool receiver_is_generic = receiver_is_type_param || receiver_is_dyn;
- bool probe_bounds = true;
- bool probe_impls = !receiver_is_generic;
- bool ignore_mandatory_trait_items = !receiver_is_generic;
-
- auto probe_type = probe_impls ? receiver_tyty : root;
- auto candidates
- = PathProbeType::Probe (probe_type,
- expr.get_method_name ().get_segment (),
- probe_impls, probe_bounds,
- ignore_mandatory_trait_items);
- if (candidates.empty ())
- {
- if (probe_impls)
- {
- candidates
- = PathProbeType::Probe (root,
- expr.get_method_name ().get_segment (),
- probe_impls, probe_bounds,
- ignore_mandatory_trait_items);
- }
-
- if (candidates.empty ())
- {
- rust_error_at (expr.get_locus (),
- "failed to resolve the PathExprSegment to any item");
- return;
- }
- }
-
- std::vector<Adjustment> adjustments;
- PathProbeCandidate *resolved_candidate
- = MethodResolution::Select (candidates, receiver_tyty, adjustments);
- if (resolved_candidate == nullptr)
+ auto candidate
+ = MethodResolver::Probe (receiver_tyty,
+ expr.get_method_name ().get_segment ());
+ if (candidate.is_error ())
{
rust_error_at (
expr.get_method_name ().get_locus (),
@@ -308,28 +265,29 @@ public:
// Get the adjusted self
Adjuster adj (receiver_tyty);
- TyTy::BaseType *adjusted_self = adj.adjust_type (adjustments);
+ TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
// mark the required tree addressable
- if (Adjuster::needs_address (adjustments))
+ if (Adjuster::needs_address (candidate.adjustments))
AddressTakenResolver::SetAddressTaken (*expr.get_receiver ().get ());
// store the adjustments for code-generation to know what to do
context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
- std::move (adjustments));
+ std::move (candidate.adjustments));
- TyTy::BaseType *lookup_tyty = resolved_candidate->ty;
+ 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 ()
+ = resolved_candidate.is_impl_candidate ()
+ ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
.get_nodeid ()
- : resolved_candidate->item.trait.item_ref->get_mappings ()
+ : resolved_candidate.item.trait.item_ref->get_mappings ()
.get_nodeid ();
if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
{
RichLocation r (expr.get_method_name ().get_locus ());
- r.add_range (resolved_candidate->locus);
+ r.add_range (resolved_candidate.locus);
rust_error_at (r, "associated impl item is not a method");
return;
}
@@ -339,11 +297,13 @@ public:
if (!fn->is_method ())
{
RichLocation r (expr.get_method_name ().get_locus ());
- r.add_range (resolved_candidate->locus);
+ r.add_range (resolved_candidate.locus);
rust_error_at (r, "associated function is not a method");
return;
}
+ auto root = receiver_tyty->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);
@@ -369,7 +329,7 @@ public:
// always be at the end of the list
auto s = fn->get_self_type ()->get_root ();
- rust_assert (s->can_eq (adt, false, false));
+ 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);
@@ -419,6 +379,8 @@ public:
}
}
+ // ADT expected but got PARAM
+
TyTy::BaseType *function_ret_tyty
= TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self,
context);
@@ -1320,10 +1282,6 @@ protected:
HIR::OperatorExpr &expr, TyTy::BaseType *lhs,
TyTy::BaseType *rhs)
{
- // in order to probe of the correct type paths we need the root type, which
- // strips any references
- const TyTy::BaseType *root = lhs->get_root ();
-
// look up lang item for arithmetic type
std::string associated_item_name
= Analysis::RustLangItem::ToString (lang_item_type);
@@ -1335,48 +1293,18 @@ protected:
if (!lang_item_defined)
return false;
- bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
- bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
- bool receiver_is_generic = receiver_is_type_param || receiver_is_dyn;
- bool probe_bounds = true;
- bool probe_impls = !receiver_is_generic;
- bool ignore_mandatory_trait_items = !receiver_is_generic;
-
- auto probe_type = probe_impls ? lhs : root;
- auto candidates
- = PathProbeType::Probe (probe_type,
- HIR::PathIdentSegment (associated_item_name),
- probe_impls, probe_bounds,
- ignore_mandatory_trait_items);
- if (candidates.empty ())
- {
- if (probe_impls)
- {
- candidates = PathProbeType::Probe (
- root, HIR::PathIdentSegment (associated_item_name), probe_impls,
- probe_bounds, ignore_mandatory_trait_items);
- }
+ auto segment = HIR::PathIdentSegment (associated_item_name);
+ auto candidate
+ = MethodResolver::Probe (lhs,
+ HIR::PathIdentSegment (associated_item_name));
- if (candidates.empty ())
- return false;
- }
-
- // autoderef to find the relevant method
- std::vector<Adjustment> adjustments;
- PathProbeCandidate *resolved_candidate
- = MethodResolution::Select (candidates, lhs, adjustments);
- if (resolved_candidate == nullptr)
- return false;
-
- bool have_implementation_for_lang_item = resolved_candidate != nullptr;
+ bool have_implementation_for_lang_item = !candidate.is_error ();
if (!have_implementation_for_lang_item)
return false;
- // mark the required tree addressable
+ // Get the adjusted self
Adjuster adj (lhs);
- TyTy::BaseType *receiver_adjusted_self_ty = adj.adjust_type (adjustments);
- if (Adjuster::needs_address (adjustments))
- AddressTakenResolver::SetAddressTaken (*expr.get_expr ().get ());
+ 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
@@ -1410,8 +1338,7 @@ protected:
= trait_reference->get_mappings ().get_defid ()
== respective_lang_item_id;
bool self_is_lang_item_self
- = fntype->get_self_type ()->is_equal (
- *receiver_adjusted_self_ty);
+ = fntype->get_self_type ()->is_equal (*adjusted_self);
bool recursive_operator_overload
= is_lang_item_impl && self_is_lang_item_self;
@@ -1421,19 +1348,24 @@ protected:
}
}
- // now its just like a method-call-expr
- context->insert_receiver (expr.get_mappings ().get_hirid (), lhs);
+ // mark the required tree addressable
+ if (Adjuster::needs_address (candidate.adjustments))
+ AddressTakenResolver::SetAddressTaken (*expr.get_expr ().get ());
// store the adjustments for code-generation to know what to do
context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
- std::move (adjustments));
+ std::move (candidate.adjustments));
- TyTy::BaseType *lookup_tyty = resolved_candidate->ty;
+ // 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 ()
+ = resolved_candidate.is_impl_candidate ()
+ ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
.get_nodeid ()
- : resolved_candidate->item.trait.item_ref->get_mappings ()
+ : resolved_candidate.item.trait.item_ref->get_mappings ()
.get_nodeid ();
rust_assert (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF);
@@ -1441,6 +1373,8 @@ protected:
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);
@@ -1466,7 +1400,7 @@ protected:
// always be at the end of the list
auto s = fn->get_self_type ()->get_root ();
- rust_assert (s->can_eq (adt, false, false));
+ 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);
@@ -1508,7 +1442,7 @@ protected:
TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
rust_assert (type->num_params () > 0);
auto fnparam = type->param_at (0);
- fnparam.second->unify (receiver_adjusted_self_ty); // typecheck the self
+ fnparam.second->unify (adjusted_self); // typecheck the self
if (rhs == nullptr)
{
rust_assert (type->num_params () == 1);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index 25b592c..94d8534 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -370,7 +370,7 @@ class TypeCheckImplItemWithTrait : public TypeCheckImplItem
using Rust::Resolver::TypeCheckBase::visit;
public:
- static const TraitItemReference &
+ static const TraitItemReference *
Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self,
TraitReference &trait_reference,
std::vector<TyTy::SubstitutionParamMapping> substitutions)
@@ -383,11 +383,14 @@ public:
void visit (HIR::ConstantItem &constant) override
{
- resolved_trait_item = trait_reference.lookup_trait_item (
- constant.get_identifier (), TraitItemReference::TraitItemType::CONST);
+ // resolved_trait_item = trait_reference.lookup_trait_item (
+ // constant.get_identifier (), TraitItemReference::TraitItemType::CONST);
+ trait_reference.lookup_trait_item_by_type (
+ constant.get_identifier (), TraitItemReference::TraitItemType::CONST,
+ &resolved_trait_item);
// unknown trait item
- if (resolved_trait_item.is_error ())
+ if (resolved_trait_item->is_error ())
{
RichLocation r (constant.get_locus ());
r.add_range (trait_reference.get_locus ());
@@ -401,14 +404,14 @@ public:
TyTy::BaseType *lookup;
if (!context->lookup_type (constant.get_mappings ().get_hirid (), &lookup))
return;
- if (resolved_trait_item.is_error ())
+ if (resolved_trait_item->is_error ())
return;
// check the types are compatible
- if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true, false))
+ if (!resolved_trait_item->get_tyty ()->can_eq (lookup, true))
{
RichLocation r (constant.get_locus ());
- r.add_range (resolved_trait_item.get_locus ());
+ r.add_range (resolved_trait_item->get_locus ());
rust_error_at (
r, "constant %<%s%> has an incompatible type for trait %<%s%>",
@@ -419,11 +422,14 @@ public:
void visit (HIR::TypeAlias &type) override
{
- resolved_trait_item = trait_reference.lookup_trait_item (
- type.get_new_type_name (), TraitItemReference::TraitItemType::TYPE);
+ // resolved_trait_item = trait_reference.lookup_trait_item (
+ // type.get_new_type_name (), TraitItemReference::TraitItemType::TYPE);
+ trait_reference.lookup_trait_item_by_type (
+ type.get_new_type_name (), TraitItemReference::TraitItemType::TYPE,
+ &resolved_trait_item);
// unknown trait item
- if (resolved_trait_item.is_error ())
+ if (resolved_trait_item->is_error ())
{
RichLocation r (type.get_locus ());
r.add_range (trait_reference.get_locus ());
@@ -437,14 +443,14 @@ public:
TyTy::BaseType *lookup;
if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
return;
- if (resolved_trait_item.is_error ())
+ if (resolved_trait_item->is_error ())
return;
// check the types are compatible
- if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true, false))
+ if (!resolved_trait_item->get_tyty ()->can_eq (lookup, true))
{
RichLocation r (type.get_locus ());
- r.add_range (resolved_trait_item.get_locus ());
+ r.add_range (resolved_trait_item->get_locus ());
rust_error_at (
r, "type alias %<%s%> has an incompatible type for trait %<%s%>",
@@ -456,19 +462,22 @@ public:
// generic substitutions to the type itself
TyTy::ProjectionType *projection = new TyTy::ProjectionType (
type.get_mappings ().get_hirid (), lookup, &trait_reference,
- resolved_trait_item.get_mappings ().get_defid (), substitutions);
+ resolved_trait_item->get_mappings ().get_defid (), substitutions);
context->insert_type (type.get_mappings (), projection);
- resolved_trait_item.associated_type_set (projection);
+ resolved_trait_item->associated_type_set (projection);
}
void visit (HIR::Function &function) override
{
- resolved_trait_item = trait_reference.lookup_trait_item (
- function.get_function_name (), TraitItemReference::TraitItemType::FN);
+ // resolved_trait_item = trait_reference.lookup_trait_item (
+ // function.get_function_name (), TraitItemReference::TraitItemType::FN);
+ trait_reference.lookup_trait_item_by_type (
+ function.get_function_name (), TraitItemReference::TraitItemType::FN,
+ &resolved_trait_item);
// unknown trait item
- if (resolved_trait_item.is_error ())
+ if (resolved_trait_item->is_error ())
{
RichLocation r (function.get_locus ());
r.add_range (trait_reference.get_locus ());
@@ -482,16 +491,16 @@ public:
TyTy::BaseType *lookup;
if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
return;
- if (resolved_trait_item.is_error ())
+ if (resolved_trait_item->is_error ())
return;
rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
- rust_assert (resolved_trait_item.get_tyty ()->get_kind ()
+ rust_assert (resolved_trait_item->get_tyty ()->get_kind ()
== TyTy::TypeKind::FNDEF);
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
TyTy::FnType *trait_item_fntype
- = static_cast<TyTy::FnType *> (resolved_trait_item.get_tyty ());
+ = static_cast<TyTy::FnType *> (resolved_trait_item->get_tyty ());
// sets substitute self into the trait_item_ref->tyty
TyTy::SubstitutionParamMapping *self_mapping = nullptr;
@@ -515,10 +524,10 @@ public:
= trait_item_fntype->handle_substitions (implicit_self_substs);
// check the types are compatible
- if (!trait_item_fntype->can_eq (fntype, true, false))
+ if (!trait_item_fntype->can_eq (fntype, true))
{
RichLocation r (function.get_locus ());
- r.add_range (resolved_trait_item.get_locus ());
+ r.add_range (resolved_trait_item->get_locus ());
rust_error_at (
r, "method %<%s%> has an incompatible type for trait %<%s%>",
@@ -533,7 +542,7 @@ private:
TraitReference &trait_reference,
std::vector<TyTy::SubstitutionParamMapping> substitutions)
: TypeCheckImplItem (parent, self), trait_reference (trait_reference),
- resolved_trait_item (TraitItemReference::error_node ()),
+ resolved_trait_item (&TraitItemReference::error_node ()),
substitutions (substitutions)
{
rust_assert (is_trait_impl_block ());
@@ -542,7 +551,7 @@ private:
bool is_trait_impl_block () const { return !trait_reference.is_error (); }
TraitReference &trait_reference;
- TraitItemReference &resolved_trait_item;
+ TraitItemReference *resolved_trait_item;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index cc102df..6692bb6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -113,15 +113,14 @@ public:
bool is_trait_impl_block = !trait_reference->is_error ();
- std::vector<std::reference_wrapper<const TraitItemReference>>
- trait_item_refs;
+ std::vector<const TraitItemReference *> trait_item_refs;
for (auto &impl_item : impl_block.get_impl_items ())
{
if (!is_trait_impl_block)
TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self);
else
{
- auto &trait_item_ref
+ auto trait_item_ref
= TypeCheckImplItemWithTrait::Resolve (&impl_block,
impl_item.get (), self,
*trait_reference,
@@ -141,12 +140,11 @@ public:
for (auto &trait_item_ref : trait_reference->get_trait_items ())
{
bool found = false;
- for (const TraitItemReference &implemented_trait_item :
- trait_item_refs)
+ for (auto implemented_trait_item : trait_item_refs)
{
std::string trait_item_name = trait_item_ref.get_identifier ();
std::string impl_item_name
- = implemented_trait_item.get_identifier ();
+ = implemented_trait_item->get_identifier ();
found = trait_item_name.compare (impl_item_name) == 0;
if (found)
break;
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 1add4fa..b751bcd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -251,7 +251,7 @@ public:
for (auto &item : it->second)
{
- if (item.first->can_eq (self, false, false))
+ if (item.first->can_eq (self, false))
{
*mapping = item.second;
return true;
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index cfb96bb..478a312 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -40,7 +40,7 @@ TypeBoundsProbe::scan ()
if (!ok)
return true;
- if (!receiver->can_eq (impl_type, false, false))
+ if (!receiver->can_eq (impl_type, false))
return true;
possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl});
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index 6347530..5620b62 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -418,10 +418,10 @@ public:
}
protected:
- BaseCmp (const BaseType *base, bool emit_errors, bool autoderef_mode)
+ BaseCmp (const BaseType *base, bool emit_errors)
: mappings (Analysis::Mappings::get ()),
context (Resolver::TypeCheckContext::get ()), ok (false),
- emit_error_flag (emit_errors), autoderef_mode_flag (autoderef_mode)
+ emit_error_flag (emit_errors)
{}
Analysis::Mappings *mappings;
@@ -429,7 +429,6 @@ protected:
bool ok;
bool emit_error_flag;
- bool autoderef_mode_flag;
private:
/* Returns a pointer to the ty that created this rule. */
@@ -441,8 +440,8 @@ class InferCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- InferCmp (const InferType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ InferCmp (const InferType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const BoolType &type) override
@@ -690,8 +689,8 @@ class FnCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- FnCmp (const FnType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ FnCmp (const FnType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const InferType &type) override
@@ -712,7 +711,7 @@ public:
auto a = base->param_at (i).second;
auto b = type.param_at (i).second;
- if (!a->can_eq (b, emit_error_flag, autoderef_mode_flag))
+ if (!a->can_eq (b, emit_error_flag))
{
emit_error_flag = false;
BaseCmp::visit (type);
@@ -721,8 +720,7 @@ public:
}
if (!base->get_return_type ()->can_eq (type.get_return_type (),
- emit_error_flag,
- autoderef_mode_flag))
+ emit_error_flag))
{
emit_error_flag = false;
BaseCmp::visit (type);
@@ -742,8 +740,8 @@ class FnptrCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- FnptrCmp (const FnPtr *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ FnptrCmp (const FnPtr *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const InferType &type) override
@@ -767,8 +765,7 @@ public:
auto this_ret_type = base->get_return_type ();
auto other_ret_type = type.get_return_type ();
- if (!this_ret_type->can_eq (other_ret_type, emit_error_flag,
- autoderef_mode_flag))
+ if (!this_ret_type->can_eq (other_ret_type, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -778,8 +775,7 @@ public:
{
auto this_param = base->param_at (i);
auto other_param = type.param_at (i);
- if (!this_param->can_eq (other_param, emit_error_flag,
- autoderef_mode_flag))
+ if (!this_param->can_eq (other_param, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -799,8 +795,7 @@ public:
auto this_ret_type = base->get_return_type ();
auto other_ret_type = type.get_return_type ();
- if (!this_ret_type->can_eq (other_ret_type, emit_error_flag,
- autoderef_mode_flag))
+ if (!this_ret_type->can_eq (other_ret_type, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -810,8 +805,7 @@ public:
{
auto this_param = base->param_at (i);
auto other_param = type.param_at (i).second;
- if (!this_param->can_eq (other_param, emit_error_flag,
- autoderef_mode_flag))
+ if (!this_param->can_eq (other_param, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -831,8 +825,8 @@ class ClosureCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- ClosureCmp (const ClosureType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ ClosureCmp (const ClosureType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
private:
@@ -845,8 +839,8 @@ class ArrayCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- ArrayCmp (const ArrayType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ ArrayCmp (const ArrayType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const ArrayType &type) override
@@ -854,8 +848,7 @@ public:
// 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,
- autoderef_mode_flag))
+ if (!base_element->can_eq (other_element, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -876,8 +869,8 @@ class BoolCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- BoolCmp (const BoolType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ BoolCmp (const BoolType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const BoolType &type) override { ok = true; }
@@ -899,8 +892,8 @@ class IntCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- IntCmp (const IntType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ IntCmp (const IntType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const InferType &type) override
@@ -925,8 +918,8 @@ class UintCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- UintCmp (const UintType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ UintCmp (const UintType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const InferType &type) override
@@ -951,8 +944,8 @@ class FloatCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- FloatCmp (const FloatType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ FloatCmp (const FloatType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const InferType &type) override
@@ -977,8 +970,8 @@ class ADTCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- ADTCmp (const ADTType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ ADTCmp (const ADTType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const ADTType &type) override
@@ -1020,8 +1013,7 @@ public:
TyTy::BaseType *this_field_ty = base_field->get_field_type ();
TyTy::BaseType *other_field_ty = other_field->get_field_type ();
- if (!this_field_ty->can_eq (other_field_ty, emit_error_flag,
- autoderef_mode_flag))
+ if (!this_field_ty->can_eq (other_field_ty, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -1032,8 +1024,6 @@ public:
ok = true;
}
- void visit (const ParamType &type) override { ok = true; }
-
private:
const BaseType *get_base () const override { return base; }
const ADTType *base;
@@ -1044,8 +1034,8 @@ class TupleCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- TupleCmp (const TupleType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ TupleCmp (const TupleType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const TupleType &type) override
@@ -1061,7 +1051,7 @@ public:
BaseType *bo = base->get_field (i);
BaseType *fo = type.get_field (i);
- if (!bo->can_eq (fo, emit_error_flag, autoderef_mode_flag))
+ if (!bo->can_eq (fo, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -1083,8 +1073,8 @@ class USizeCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- USizeCmp (const USizeType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ USizeCmp (const USizeType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const InferType &type) override
@@ -1106,8 +1096,8 @@ class ISizeCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- ISizeCmp (const ISizeType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ ISizeCmp (const ISizeType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const InferType &type) override
@@ -1129,8 +1119,8 @@ class CharCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- CharCmp (const CharType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ CharCmp (const CharType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const InferType &type) override
@@ -1152,9 +1142,8 @@ class ReferenceCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- ReferenceCmp (const ReferenceType *base, bool emit_errors,
- bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ ReferenceCmp (const ReferenceType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const ReferenceType &type) override
@@ -1162,17 +1151,14 @@ public:
auto base_type = base->get_base ();
auto other_base_type = type.get_base ();
- // rust is permissive about mutablity here you can always go from mutable to
- // immutable but not the otherway round
- bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
- if (!mutability_ok)
+ bool mutability_match = base->is_mutable () == type.is_mutable ();
+ if (!mutability_match)
{
BaseCmp::visit (type);
return;
}
- if (!base_type->can_eq (other_base_type, emit_error_flag,
- autoderef_mode_flag))
+ if (!base_type->can_eq (other_base_type, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -1191,8 +1177,8 @@ class PointerCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- PointerCmp (const PointerType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ PointerCmp (const PointerType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const ReferenceType &type) override
@@ -1209,8 +1195,7 @@ public:
return;
}
- if (!base_type->can_eq (other_base_type, emit_error_flag,
- autoderef_mode_flag))
+ if (!base_type->can_eq (other_base_type, emit_error_flag))
{
BaseCmp::visit (type);
return;
@@ -1229,8 +1214,8 @@ class ParamCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- ParamCmp (const ParamType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ ParamCmp (const ParamType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
// param types are a placeholder we shouldn't have cases where we unify
@@ -1252,7 +1237,7 @@ public:
bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
rust_assert (ok);
- return lookup->can_eq (other, emit_error_flag, autoderef_mode_flag);
+ return lookup->can_eq (other, emit_error_flag);
}
// imagine the case where we have:
@@ -1263,16 +1248,14 @@ public:
// generic arguments
void visit (const ParamType &) override { ok = true; }
- void visit (const TupleType &) override { ok = true; }
-
- void visit (const ADTType &) override { ok = true; }
-
void visit (const InferType &) override { ok = true; }
void visit (const FnType &) override { ok = true; }
void visit (const FnPtr &) override { ok = true; }
+ void visit (const ADTType &) override { ok = true; }
+
void visit (const ArrayType &) override { ok = true; }
void visit (const BoolType &) override { ok = true; }
@@ -1289,9 +1272,9 @@ public:
void visit (const CharType &) override { ok = true; }
- void visit (const ReferenceType &) override { ok = !autoderef_mode_flag; }
+ void visit (const ReferenceType &) override { ok = true; }
- void visit (const PointerType &) override { ok = !autoderef_mode_flag; }
+ void visit (const PointerType &) override { ok = true; }
void visit (const StrType &) override { ok = true; }
@@ -1315,8 +1298,8 @@ class StrCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- StrCmp (const StrType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ StrCmp (const StrType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const StrType &type) override { ok = true; }
@@ -1333,8 +1316,8 @@ class NeverCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- NeverCmp (const NeverType *base, bool emit_errors, bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ NeverCmp (const NeverType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const NeverType &type) override { ok = true; }
@@ -1351,9 +1334,8 @@ class PlaceholderCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- PlaceholderCmp (const PlaceholderType *base, bool emit_errors,
- bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ PlaceholderCmp (const PlaceholderType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
bool can_eq (const BaseType *other) override
@@ -1362,7 +1344,7 @@ public:
return BaseCmp::can_eq (other);
BaseType *lookup = base->resolve ();
- return lookup->can_eq (other, emit_error_flag, autoderef_mode_flag);
+ return lookup->can_eq (other, emit_error_flag);
}
void visit (const TupleType &) override { ok = true; }
@@ -1417,9 +1399,8 @@ class DynamicCmp : public BaseCmp
using Rust::TyTy::BaseCmp::visit;
public:
- DynamicCmp (const DynamicObjectType *base, bool emit_errors,
- bool autoderef_mode)
- : BaseCmp (base, emit_errors, autoderef_mode), base (base)
+ DynamicCmp (const DynamicObjectType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
{}
void visit (const DynamicObjectType &type) override
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 450a93f..349813b 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -25,9 +25,6 @@
#include "rust-hir-map.h"
#include "rust-hir-type-check.h"
-extern ::Backend *
-rust_get_backend ();
-
namespace Rust {
namespace TyTy {
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 679187b..b5427b7 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -91,8 +91,12 @@ BaseType::bounds_compatible (const BaseType &other, Location locus,
}
if (emit_error)
- rust_error_at (r, "bounds not satisfied for %s %<%s%> is not satisfied",
- other.get_name ().c_str (), missing_preds.c_str ());
+ {
+ rust_error_at (r,
+ "bounds not satisfied for %s %<%s%> is not satisfied",
+ other.get_name ().c_str (), missing_preds.c_str ());
+ // rust_assert (!emit_error);
+ }
}
return unsatisfied_bounds.size () == 0;
@@ -201,10 +205,9 @@ InferType::unify (BaseType *other)
}
bool
-InferType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+InferType::can_eq (const BaseType *other, bool emit_errors) const
{
- InferCmp r (this, emit_errors, autoderef_mode);
+ InferCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -279,8 +282,7 @@ ErrorType::unify (BaseType *other)
}
bool
-ErrorType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+ErrorType::can_eq (const BaseType *other, bool emit_errors) const
{
return get_kind () == other->get_kind ();
}
@@ -685,10 +687,9 @@ ADTType::cast (BaseType *other)
}
bool
-ADTType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+ADTType::can_eq (const BaseType *other, bool emit_errors) const
{
- ADTCmp r (this, emit_errors, autoderef_mode);
+ ADTCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -888,10 +889,9 @@ TupleType::cast (BaseType *other)
}
bool
-TupleType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+TupleType::can_eq (const BaseType *other, bool emit_errors) const
{
- TupleCmp r (this, emit_errors, autoderef_mode);
+ TupleCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -993,10 +993,9 @@ FnType::cast (BaseType *other)
}
bool
-FnType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+FnType::can_eq (const BaseType *other, bool emit_errors) const
{
- FnCmp r (this, emit_errors, autoderef_mode);
+ FnCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1211,10 +1210,9 @@ FnPtr::cast (BaseType *other)
}
bool
-FnPtr::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+FnPtr::can_eq (const BaseType *other, bool emit_errors) const
{
- FnptrCmp r (this, emit_errors, autoderef_mode);
+ FnptrCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1278,10 +1276,9 @@ ClosureType::unify (BaseType *other)
}
bool
-ClosureType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+ClosureType::can_eq (const BaseType *other, bool emit_errors) const
{
- ClosureCmp r (this, emit_errors, autoderef_mode);
+ ClosureCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1360,10 +1357,9 @@ ArrayType::cast (BaseType *other)
}
bool
-ArrayType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+ArrayType::can_eq (const BaseType *other, bool emit_errors) const
{
- ArrayCmp r (this, emit_errors, autoderef_mode);
+ ArrayCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1434,10 +1430,9 @@ BoolType::cast (BaseType *other)
}
bool
-BoolType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+BoolType::can_eq (const BaseType *other, bool emit_errors) const
{
- BoolCmp r (this, emit_errors, autoderef_mode);
+ BoolCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1501,10 +1496,9 @@ IntType::cast (BaseType *other)
}
bool
-IntType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+IntType::can_eq (const BaseType *other, bool emit_errors) const
{
- IntCmp r (this, emit_errors, autoderef_mode);
+ IntCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1579,10 +1573,9 @@ UintType::cast (BaseType *other)
}
bool
-UintType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+UintType::can_eq (const BaseType *other, bool emit_errors) const
{
- UintCmp r (this, emit_errors, autoderef_mode);
+ UintCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1651,10 +1644,9 @@ FloatType::cast (BaseType *other)
}
bool
-FloatType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+FloatType::can_eq (const BaseType *other, bool emit_errors) const
{
- FloatCmp r (this, emit_errors, autoderef_mode);
+ FloatCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1715,10 +1707,9 @@ USizeType::cast (BaseType *other)
}
bool
-USizeType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+USizeType::can_eq (const BaseType *other, bool emit_errors) const
{
- USizeCmp r (this, emit_errors, autoderef_mode);
+ USizeCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1768,10 +1759,9 @@ ISizeType::cast (BaseType *other)
}
bool
-ISizeType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+ISizeType::can_eq (const BaseType *other, bool emit_errors) const
{
- ISizeCmp r (this, emit_errors, autoderef_mode);
+ ISizeCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1821,10 +1811,9 @@ CharType::cast (BaseType *other)
}
bool
-CharType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+CharType::can_eq (const BaseType *other, bool emit_errors) const
{
- CharCmp r (this, emit_errors, autoderef_mode);
+ CharCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1875,10 +1864,9 @@ ReferenceType::cast (BaseType *other)
}
bool
-ReferenceType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+ReferenceType::can_eq (const BaseType *other, bool emit_errors) const
{
- ReferenceCmp r (this, emit_errors, autoderef_mode);
+ ReferenceCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -1962,10 +1950,9 @@ PointerType::cast (BaseType *other)
}
bool
-PointerType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+PointerType::can_eq (const BaseType *other, bool emit_errors) const
{
- PointerCmp r (this, emit_errors, autoderef_mode);
+ PointerCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -2072,10 +2059,9 @@ ParamType::cast (BaseType *other)
}
bool
-ParamType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+ParamType::can_eq (const BaseType *other, bool emit_errors) const
{
- ParamCmp r (this, emit_errors, autoderef_mode);
+ ParamCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -2130,7 +2116,7 @@ ParamType::is_equal (const BaseType &other) const
return false;
if (can_resolve ())
- return resolve ()->can_eq (other2.resolve (), false, false);
+ return resolve ()->can_eq (other2.resolve (), false);
return get_symbol ().compare (other2.get_symbol ()) == 0;
}
@@ -2194,10 +2180,9 @@ StrType::cast (BaseType *other)
}
bool
-StrType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+StrType::can_eq (const BaseType *other, bool emit_errors) const
{
- StrCmp r (this, emit_errors, autoderef_mode);
+ StrCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -2247,10 +2232,9 @@ NeverType::cast (BaseType *other)
}
bool
-NeverType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+NeverType::can_eq (const BaseType *other, bool emit_errors) const
{
- NeverCmp r (this, emit_errors, autoderef_mode);
+ NeverCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -2303,10 +2287,9 @@ PlaceholderType::cast (BaseType *other)
}
bool
-PlaceholderType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
{
- PlaceholderCmp r (this, emit_errors, autoderef_mode);
+ PlaceholderCmp r (this, emit_errors);
return r.can_eq (other);
}
@@ -2404,10 +2387,9 @@ ProjectionType::cast (BaseType *other)
}
bool
-ProjectionType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
{
- return base->can_eq (other, emit_errors, autoderef_mode);
+ return base->can_eq (other, emit_errors);
}
BaseType *
@@ -2511,10 +2493,9 @@ DynamicObjectType::unify (BaseType *other)
}
bool
-DynamicObjectType::can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const
+DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const
{
- DynamicCmp r (this, emit_errors, autoderef_mode);
+ DynamicCmp r (this, emit_errors);
return r.can_eq (other);
}
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index f2c250f..873f5d8 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -314,8 +314,7 @@ public:
//
// It can also be used to optional emit errors for trait item compatibility
// checks
- virtual bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const = 0;
+ virtual bool can_eq (const BaseType *other, bool emit_errors) const = 0;
// this is the base coercion interface for types
virtual BaseType *coerce (BaseType *other) = 0;
@@ -460,8 +459,7 @@ public:
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -499,8 +497,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -536,8 +533,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -626,8 +622,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1252,8 +1247,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1387,8 +1381,7 @@ public:
std::string get_identifier () const { return identifier; }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1507,8 +1500,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1578,8 +1570,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1642,8 +1633,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1684,8 +1674,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1722,8 +1711,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1767,8 +1755,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1810,8 +1797,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1845,8 +1831,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1873,8 +1858,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1901,8 +1885,7 @@ public:
std::string get_name () const override final { return as_string (); }
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1936,8 +1919,7 @@ public:
}
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -1987,8 +1969,7 @@ public:
}
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -2033,8 +2014,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -2071,8 +2051,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -2106,8 +2085,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -2175,8 +2153,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
BaseType *cast (BaseType *other) override;
@@ -2233,8 +2210,7 @@ public:
std::string as_string () const override;
BaseType *unify (BaseType *other) override;
- bool can_eq (const BaseType *other, bool emit_errors,
- bool autoderef_mode) const override final;
+ 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;
diff --git a/gcc/testsuite/rust/execute/torture/method2.rs b/gcc/testsuite/rust/execute/torture/method2.rs
new file mode 100644
index 0000000..f532b44
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method2.rs
@@ -0,0 +1,76 @@
+// { dg-additional-options "-w" }
+// { dg-output "foo_deref\nimm_deref\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+struct Bar(i32);
+impl Bar {
+ fn foobar(self) -> i32 {
+ self.0
+ }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ let a = "foo_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &self.0
+ }
+}
+
+pub fn main() -> i32 {
+ let bar = Bar(123);
+ let foo: Foo<&Bar> = Foo(&bar);
+ let foobar: i32 = foo.foobar();
+
+ foobar - 123
+}