diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-04-10 15:31:14 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-04-12 22:39:45 +0100 |
commit | 5fe4984806be69154e2a48be58965eb67a4be300 (patch) | |
tree | 289967fff36c9247053ebb3a5b6a4aacefeb0e58 /gcc | |
parent | f98ccb3a0bcf6a49b4e1f2080f7f58fe39794fdf (diff) | |
download | gcc-5fe4984806be69154e2a48be58965eb67a4be300.zip gcc-5fe4984806be69154e2a48be58965eb67a4be300.tar.gz gcc-5fe4984806be69154e2a48be58965eb67a4be300.tar.bz2 |
Add path probe for inherent impl item candidates
When performing PathInExpression resolution we need to probe for candidates
in impl blocks which can_eq to the Self type. This could be reused to clean
up Method resolution and implement PathInExpression resolution properly.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-path-probe.h | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h new file mode 100644 index 0000000..a838565 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -0,0 +1,162 @@ +// 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_PATH_PROBE_H +#define RUST_HIR_PATH_PROBE_H + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-tyty.h" +#include "rust-substitution-mapper.h" + +namespace Rust { +namespace Resolver { + +struct PathProbeCandidate +{ + HIR::InherentImplItem *impl_item; + TyTy::BaseType *ty; +}; + +class PathProbeType : public TypeCheckBase +{ + using Rust::Resolver::TypeCheckBase::visit; + +public: + static std::vector<PathProbeCandidate> + Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name) + { + PathProbeType probe (receiver, segment_name); + probe.mappings->iterate_impl_items ( + [&] (HirId id, HIR::InherentImplItem *item, + HIR::InherentImpl *impl) mutable -> bool { + probe.process_candidate (id, item, impl); + return true; + }); + return probe.candidates; + } + + void process_candidate (HirId id, HIR::InherentImplItem *item, + HIR::InherentImpl *impl) + { + HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid (); + TyTy::BaseType *impl_block_ty = nullptr; + bool ok = context->lookup_type (impl_ty_id, &impl_block_ty); + rust_assert (ok); + + if (!receiver->can_eq (impl_block_ty)) + return; + + // lets visit the impl_item + item->accept_vis (*this); + } + + void visit (HIR::ConstantItem &constant) override + { + Identifier name = constant.get_identifier (); + if (search.as_string ().compare (name) == 0) + { + HirId tyid = constant.get_mappings ().get_hirid (); + TyTy::BaseType *ty = nullptr; + bool ok = context->lookup_type (tyid, &ty); + rust_assert (ok); + + PathProbeCandidate candidate{&constant, ty}; + candidates.push_back (std::move (candidate)); + } + } + + void visit (HIR::Function &function) override + { + Identifier name = function.get_function_name (); + if (search.as_string ().compare (name) == 0) + { + HirId tyid = function.get_mappings ().get_hirid (); + TyTy::BaseType *ty = nullptr; + bool ok = context->lookup_type (tyid, &ty); + rust_assert (ok); + + PathProbeCandidate candidate{&function, ty}; + candidates.push_back (std::move (candidate)); + } + } + + void visit (HIR::Method &method) override + { + Identifier name = method.get_method_name (); + if (search.as_string ().compare (name) == 0) + { + HirId tyid = method.get_mappings ().get_hirid (); + TyTy::BaseType *ty = nullptr; + bool ok = context->lookup_type (tyid, &ty); + rust_assert (ok); + + PathProbeCandidate candidate{&method, ty}; + candidates.push_back (std::move (candidate)); + } + } + +private: + PathProbeType (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query) + : TypeCheckBase (), receiver (receiver), search (query) + {} + + TyTy::BaseType *receiver; + const HIR::PathIdentSegment &search; + std::vector<PathProbeCandidate> candidates; +}; + +class ReportMultipleCandidateError : private TypeCheckBase +{ + using Rust::Resolver::TypeCheckBase::visit; + +public: + static void Report (std::vector<PathProbeCandidate> &candidates, + const HIR::PathIdentSegment &query, Location query_locus) + { + rust_error_at (query_locus, "multiple applicable items in scope for: %s", + query.as_string ().c_str ()); + + ReportMultipleCandidateError visitor; + for (auto &c : candidates) + c.impl_item->accept_vis (visitor); + } + + void visit (HIR::ConstantItem &constant) override + { + rust_error_at (constant.get_locus (), "possible candidate"); + } + + void visit (HIR::Function &function) override + { + rust_error_at (function.get_locus (), "possible candidate"); + } + + void visit (HIR::Method &method) override + { + rust_error_at (method.get_locus (), "possible candidate"); + } + +private: + ReportMultipleCandidateError () : TypeCheckBase () {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_PATH_PROBE_H |