diff options
Diffstat (limited to 'gcc')
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 +} |