diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-09-14 15:00:47 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-14 15:00:47 +0000 |
commit | c8ffaa101c936822f5853a276d530da09c96cf52 (patch) | |
tree | d393eecd5333696158e868e907ae93f7530de8ec /gcc | |
parent | c644ee4c4351e3590f5396e94ec24ad7b828a954 (diff) | |
parent | 002313b343746f8c72b62522e48e04fa0953b2d0 (diff) | |
download | gcc-c8ffaa101c936822f5853a276d530da09c96cf52.zip gcc-c8ffaa101c936822f5853a276d530da09c96cf52.tar.gz gcc-c8ffaa101c936822f5853a276d530da09c96cf52.tar.bz2 |
Merge #672
672: Initial autoderef support for method calls r=philberty a=philberty
The commit message contains more detail but this reference is good:
https://doc.rust-lang.org/nightly/nomicon/dot-operator.html
This is not 100% complete since we do not yet support operator overloading
so we will require an update to support the Deref operator overload for
more complex types.
Fixes: #241
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 26 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower.cc | 21 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 8 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-autoderef.h | 74 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-dot-operator.h | 182 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 60 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 40 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.cc | 39 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.h | 22 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 12 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 8 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/method1.rs | 6 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/method1.rs | 27 |
13 files changed, 481 insertions, 44 deletions
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index ef2c16a..5214b1d 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -277,6 +277,32 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) // method receiver Bexpression *self = CompileExpr::Compile (expr.get_receiver ().get (), ctx); rust_assert (self != nullptr); + + // lookup the autoderef mappings + std::vector<Resolver::Adjustment> *adjustments = nullptr; + ok = ctx->get_tyctx ()->lookup_autoderef_mappings ( + 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: + Btype *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; + } + } args.push_back (self); // normal args diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index b64e1a0..5c70b2c 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -403,17 +403,26 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) HIR::SelfParam ASTLoweringBase::lower_self (AST::SelfParam &self) { - HIR::Type *type = self.has_type () - ? ASTLoweringType::translate (self.get_type ().get ()) - : nullptr; - auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, self.get_node_id (), mappings->get_next_hir_id (crate_num), mappings->get_next_localdef_id (crate_num)); - return HIR::SelfParam (mapping, std::unique_ptr<HIR::Type> (type), - self.get_is_mut (), self.get_locus ()); + if (self.has_type ()) + { + HIR::Type *type = ASTLoweringType::translate (self.get_type ().get ()); + return HIR::SelfParam (mapping, std::unique_ptr<HIR::Type> (type), + self.get_is_mut (), self.get_locus ()); + } + else if (!self.get_has_ref ()) + { + return HIR::SelfParam (mapping, std::unique_ptr<HIR::Type> (nullptr), + self.get_is_mut (), self.get_locus ()); + } + + AST::Lifetime l = self.get_lifetime (); + return HIR::SelfParam (mapping, lower_lifetime (l), self.get_is_mut (), + self.get_locus ()); } void diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 936e11f..0b2cf10 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -310,10 +310,10 @@ struct SelfParam public: enum ImplicitSelfKind { - IMM, - MUT, - IMM_REF, - MUT_REF, + IMM, // self + MUT, // mut self + IMM_REF, // &self + MUT_REF, // &mut self NONE }; diff --git a/gcc/rust/typecheck/rust-autoderef.h b/gcc/rust/typecheck/rust-autoderef.h new file mode 100644 index 0000000..7a9083d --- /dev/null +++ b/gcc/rust/typecheck/rust-autoderef.h @@ -0,0 +1,74 @@ +// Copyright (C) 2020 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/>. + +#ifndef RUST_AUTODEREF +#define RUST_AUTODEREF + +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class Adjustment +{ +public: + enum AdjustmentType + { + IMM_REF, + MUT_REF, + DEREF_REF + }; + + Adjustment (AdjustmentType type, TyTy::BaseType *expected) + : type (type), expected (expected) + {} + + AdjustmentType get_type () const { return type; } + + TyTy::BaseType *get_expected () const { return expected; } + + std::string as_string () const + { + return Adjustment::type_string (get_type ()) + "->" + + get_expected ()->debug_str (); + } + + static std::string type_string (AdjustmentType type) + { + switch (type) + { + case AdjustmentType::IMM_REF: + return "IMM_REF"; + case AdjustmentType::MUT_REF: + return "MUT_REF"; + case AdjustmentType::DEREF_REF: + return "DEREF_REF"; + } + gcc_unreachable (); + return ""; + } + +private: + AdjustmentType type; + TyTy::BaseType *expected; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AUTODEREF diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h new file mode 100644 index 0000000..6743862 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-dot-operator.h @@ -0,0 +1,182 @@ +// Copyright (C) 2020 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/>. + +#ifndef RUST_HIR_DOT_OPERATOR +#define RUST_HIR_DOT_OPERATOR + +#include "rust-hir-path-probe.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.*/ + +// https://doc.rust-lang.org/nightly/nomicon/dot-operator.html + +class MethodResolution +{ +public: + static PathProbeCandidate * + Select (std::vector<PathProbeCandidate> &candidates, TyTy::BaseType *receiver, + std::vector<Adjustment> &adjustments) + { + TyTy::BaseType *r = receiver; + while (true) + { + PathProbeCandidate *c = nullptr; + + // 1. try raw + c = Try (candidates, r); + if (c != nullptr) + return c; + + // 2. try ref + TyTy::ReferenceType *r1 + = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()), + false); + c = Try (candidates, r1); + if (c != nullptr) + { + adjustments.push_back ( + Adjustment (Adjustment::AdjustmentType::IMM_REF, r1)); + return c; + } + + // 3. try mut ref + TyTy::ReferenceType *r2 + = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()), + true); + c = Try (candidates, r2); + if (c != nullptr) + { + adjustments.push_back ( + Adjustment (Adjustment::AdjustmentType::MUT_REF, r2)); + return c; + } + + // 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 + + TyTy::ReferenceType *rr = static_cast<TyTy::ReferenceType *> (r); + r = rr->get_base (); + adjustments.push_back ( + Adjustment (Adjustment::AdjustmentType::DEREF_REF, r)); + } + return nullptr; + } + +private: + static PathProbeCandidate *Try (std::vector<PathProbeCandidate> &candidates, + const TyTy::BaseType *receiver) + { + TypeCheckContext *context = TypeCheckContext::get (); + + // probe impls + for (auto &c : candidates) + { + bool is_func = c.type == PathProbeCandidate::CandidateType::IMPL_FUNC; + HIR::ImplBlock *block = c.item.impl.parent; + if (is_func && !block->has_trait_ref ()) + { + 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 (receiver->can_eq (fn_self, false)) + { + return &c; + } + } + } + } + + // probe trait impls + for (auto &c : candidates) + { + bool is_func = c.type == PathProbeCandidate::CandidateType::IMPL_FUNC; + HIR::ImplBlock *block = c.item.impl.parent; + if (is_func && block->has_trait_ref ()) + { + 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 (receiver->can_eq (fn_self, false)) + { + return &c; + } + } + } + } + + // probe trait bounds + for (auto &c : candidates) + { + bool is_func = c.type == PathProbeCandidate::CandidateType::TRAIT_FUNC; + if (is_func) + { + 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 (receiver->can_eq (fn_self, false)) + { + return &c; + } + } + } + } + + return nullptr; + } +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_DOT_OPERATOR diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 31c8909..07d4f90 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -30,6 +30,7 @@ #include "rust-hir-const-fold.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-type-bounds.h" +#include "rust-hir-dot-operator.h" namespace Rust { namespace Resolver { @@ -207,7 +208,7 @@ public: { auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get (), false); - if (receiver_tyty == nullptr) + if (receiver_tyty->get_kind () == TyTy::TypeKind::ERROR) { rust_error_at (expr.get_receiver ()->get_locus (), "failed to resolve receiver in MethodCallExpr"); @@ -216,50 +217,67 @@ 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 + 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 reciever_is_generic - = receiver_tyty->get_kind () == TyTy::TypeKind::PARAM; + bool reciever_is_generic = root->get_kind () == TyTy::TypeKind::PARAM; bool probe_bounds = true; bool probe_impls = !reciever_is_generic; bool ignore_mandatory_trait_items = !reciever_is_generic; auto candidates - = PathProbeType::Probe (receiver_tyty, - expr.get_method_name ().get_segment (), + = PathProbeType::Probe (root, expr.get_method_name ().get_segment (), probe_impls, probe_bounds, ignore_mandatory_trait_items); - if (candidates.size () == 0) + if (candidates.empty ()) { rust_error_at (expr.get_locus (), - "failed to resolve the PathExprSegment to any Method"); + "failed to resolve the PathExprSegment to any item"); return; } - else if (candidates.size () > 1) + + std::vector<Adjustment> adjustments; + PathProbeCandidate *resolved_candidate + = MethodResolution::Select (candidates, receiver_tyty, adjustments); + if (resolved_candidate == nullptr) { - ReportMultipleCandidateError::Report ( - candidates, expr.get_method_name ().get_segment (), - expr.get_method_name ().get_locus ()); + if (candidates.size () > 1) + { + // not sure if this is the correct error here + ReportMultipleCandidateError::Report ( + candidates, expr.get_method_name ().get_segment (), + expr.get_method_name ().get_locus ()); + } + else + { + rust_error_at (expr.get_locus (), "failed to resolve method"); + } return; } - auto resolved_candidate = candidates.at (0); - TyTy::BaseType *lookup_tyty = resolved_candidate.ty; + // store the adjustments for code-generation to know what to do + context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (), + std::move (adjustments)); + + TyTy::BaseType *lookup_tyty = resolved_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; } @@ -269,14 +287,14 @@ 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; } - if (receiver_tyty->get_kind () == TyTy::TypeKind::ADT) + if (root->get_kind () == TyTy::TypeKind::ADT) { - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver_tyty); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (root); if (adt->has_substitutions () && fn->needs_substitution ()) { // consider the case where we have: @@ -298,7 +316,7 @@ public: // default types GenericParams on impl blocks since these must // always be at the end of the list - auto s = fn->get_self_type (); + auto s = fn->get_self_type ()->get_root (); rust_assert (s->can_eq (adt, false)); rust_assert (s->get_kind () == TyTy::TypeKind::ADT); TyTy::ADTType *self_adt = static_cast<TyTy::ADTType *> (s); diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index d3977c3..94674ad 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -220,10 +220,45 @@ public: HIR::IdentifierPattern *self_pattern = new HIR::IdentifierPattern ( "self", self_param.get_locus (), self_param.is_ref (), self_param.is_mut (), std::unique_ptr<HIR::Pattern> (nullptr)); - context->insert_type (self_param.get_mappings (), self->clone ()); + + // might have a specified type + TyTy::BaseType *self_type = nullptr; + if (self_param.has_type ()) + { + std::unique_ptr<HIR::Type> &specified_type = self_param.get_type (); + self_type = TypeCheckType::Resolve (specified_type.get ()); + } + else + { + switch (self_param.get_self_kind ()) + { + case HIR::SelfParam::IMM: + case HIR::SelfParam::MUT: + self_type = self->clone (); + break; + + case HIR::SelfParam::IMM_REF: + self_type = new TyTy::ReferenceType ( + self_param.get_mappings ().get_hirid (), + TyTy::TyVar (self->get_ref ()), false); + break; + + case HIR::SelfParam::MUT_REF: + self_type = new TyTy::ReferenceType ( + self_param.get_mappings ().get_hirid (), + TyTy::TyVar (self->get_ref ()), true); + break; + + default: + gcc_unreachable (); + return; + } + } + + context->insert_type (self_param.get_mappings (), self_type); params.push_back ( std::pair<HIR::Pattern *, TyTy::BaseType *> (self_pattern, - self->clone ())); + self_type)); } for (auto ¶m : function.get_function_params ()) @@ -242,6 +277,7 @@ public: function.get_mappings ().get_defid (), function.get_function_name (), function.is_method () ? FNTYPE_IS_METHOD_FLAG : FNTYPE_DEFAULT_FLAGS, ABI::RUST, std::move (params), ret_type, std::move (substitutions)); + context->insert_type (function.get_mappings (), fnType); } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index f960f77..0cd6883 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -529,10 +529,43 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const self_param.is_ref (), self_param.is_mut (), std::unique_ptr<HIR::Pattern> (nullptr)); - context->insert_type (self_param.get_mappings (), self->clone ()); + // might have a specified type + TyTy::BaseType *self_type = nullptr; + if (self_param.has_type ()) + { + std::unique_ptr<HIR::Type> &specified_type = self_param.get_type (); + self_type = TypeCheckType::Resolve (specified_type.get ()); + } + else + { + switch (self_param.get_self_kind ()) + { + case HIR::SelfParam::IMM: + case HIR::SelfParam::MUT: + self_type = self->clone (); + break; + + case HIR::SelfParam::IMM_REF: + self_type = new TyTy::ReferenceType ( + self_param.get_mappings ().get_hirid (), + TyTy::TyVar (self->get_ref ()), false); + break; + + case HIR::SelfParam::MUT_REF: + self_type = new TyTy::ReferenceType ( + self_param.get_mappings ().get_hirid (), + TyTy::TyVar (self->get_ref ()), true); + break; + + default: + gcc_unreachable (); + return nullptr; + } + } + + context->insert_type (self_param.get_mappings (), self_type); params.push_back ( - std::pair<HIR::Pattern *, TyTy::BaseType *> (self_pattern, - self->clone ())); + std::pair<HIR::Pattern *, TyTy::BaseType *> (self_pattern, self_type)); } for (auto ¶m : function.get_function_params ()) diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 491de85..bcad5db 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -23,6 +23,7 @@ #include "rust-hir-map.h" #include "rust-tyty.h" #include "rust-hir-trait-ref.h" +#include "rust-autoderef.h" namespace Rust { namespace Resolver { @@ -183,6 +184,24 @@ public: return UNKNOWN_HIRID; } + void insert_autoderef_mappings (HirId id, + std::vector<Adjustment> &&adjustments) + { + rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ()); + autoderef_mappings.emplace (id, std::move (adjustments)); + } + + bool lookup_autoderef_mappings (HirId id, + std::vector<Adjustment> **adjustments) + { + auto it = autoderef_mappings.find (id); + if (it == autoderef_mappings.end ()) + return false; + + *adjustments = &it->second; + return true; + } + private: TypeCheckContext (); @@ -200,6 +219,9 @@ private: associated_traits_to_impls; std::map<HirId, HirId> associated_type_mappings; + + // adjustment mappings + std::map<HirId, std::vector<Adjustment>> autoderef_mappings; }; class TypeResolution diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 398b531..ef981cc 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -112,6 +112,18 @@ BaseType::inherit_bounds ( } } +BaseType * +BaseType::get_root () +{ + BaseType *root = this; + while (root->get_kind () == TyTy::REF) + { + ReferenceType *r = static_cast<ReferenceType *> (root); + root = r->get_base (); + } + return root; +} + TyVar::TyVar (HirId ref) : ref (ref) { // ensure this reference is defined within the context diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index d3d4afd..a7eb132 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -221,8 +221,7 @@ public: // Unify two types. Returns a pointer to the newly-created unified ty, or // nullptr if the two ty cannot be unified. The caller is responsible for - // releasing the memory of the returned ty. using ignore_errors alows for a - // can_eq style unification + // releasing the memory of the returned ty. virtual BaseType *unify (BaseType *other) = 0; // similar to unify but does not actually perform type unification but @@ -312,6 +311,8 @@ public: debug_str ().c_str ()); } + BaseType *get_root (); + protected: BaseType (HirId ref, HirId ty_ref, TypeKind kind, std::set<HirId> refs = std::set<HirId> ()) @@ -1146,8 +1147,7 @@ public: BaseType *get_self_type () const { rust_assert (is_method ()); - // FIXME this will need updated when we support coercion for & mut self etc - return get_params ().at (0).second; + return param_at (0).second; } std::vector<std::pair<HIR::Pattern *, BaseType *>> &get_params () diff --git a/gcc/testsuite/rust/compile/method1.rs b/gcc/testsuite/rust/compile/method1.rs index 0597671..cce4ecf 100644 --- a/gcc/testsuite/rust/compile/method1.rs +++ b/gcc/testsuite/rust/compile/method1.rs @@ -1,15 +1,13 @@ struct Foo(i32); - impl Foo { fn test() {} } pub fn main() { - // { dg-error {expected \[\(\)\] got \[<tyty::error>\]} "" { target *-*-* } .-1 } let a; a = Foo(123); - a.test() - // { dg-error "associated function is not a method" "" { target *-*-* } .-1 } + a.test(); + // { dg-error "failed to resolve method" "" { target *-*-* } .-1 } // { dg-error {failed to type resolve expression} "" { target *-*-* } .-2 } } diff --git a/gcc/testsuite/rust/execute/torture/method1.rs b/gcc/testsuite/rust/execute/torture/method1.rs new file mode 100644 index 0000000..6af6133 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/method1.rs @@ -0,0 +1,27 @@ +/* { dg-output "124\n458" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +struct Foo(i32); +impl Foo { + fn bar(&self, i: i32) { + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, self.0 + i); + } + } +} + +fn main() -> i32 { + let a = Foo(123); + a.bar(1); + + let b = &Foo(456); + b.bar(2); + + 0 +} |