aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-07-16 16:50:26 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-08-05 19:07:11 +0100
commit65ef30eb84314ae7525be4a4d7dd79d2868e3e3c (patch)
treebb7172a61dc354681743d86f708e021b4613cc9f /gcc/rust/backend
parent0db1c804562aff23344cd5882db6fc65596e0966 (diff)
downloadgcc-65ef30eb84314ae7525be4a4d7dd79d2868e3e3c.zip
gcc-65ef30eb84314ae7525be4a4d7dd79d2868e3e3c.tar.gz
gcc-65ef30eb84314ae7525be4a4d7dd79d2868e3e3c.tar.bz2
Support TypeBounds on Generic functions
TypeBounds are what make generics useful in Rust. They act in some ways similar to interfaces in modern Java. Fixes #583
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc84
-rw-r--r--gcc/rust/backend/rust-compile.cc118
2 files changed, 172 insertions, 30 deletions
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index af8d609..c87b477 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -20,6 +20,8 @@
#include "rust-backend.h"
#include "rust-compile-resolve-path.h"
#include "rust-compile-item.h"
+#include "rust-hir-trait-resolve.h"
+#include "rust-hir-path-probe.h"
namespace Rust {
namespace Compile {
@@ -94,7 +96,76 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
HIR::ImplItem *resolved_item
= ctx->get_mappings ()->lookup_hir_implitem (
expr.get_mappings ().get_crate_num (), ref, &parent_impl_id);
- if (resolved_item != nullptr)
+
+ if (resolved_item == nullptr)
+ {
+ // it might be resolved to a trait item
+ HIR::TraitItem *trait_item
+ = ctx->get_mappings ()->lookup_hir_trait_item (
+ expr.get_mappings ().get_crate_num (), ref);
+ HIR::Trait *trait
+ = ctx->get_mappings ()->lookup_trait_item_mapping (
+ trait_item->get_mappings ().get_hirid ());
+
+ Resolver::TraitReference &trait_ref
+ = Resolver::TraitResolver::error_node ();
+ bool ok = ctx->get_tyctx ()->lookup_trait_reference (
+ trait->get_mappings ().get_defid (), trait_ref);
+ rust_assert (ok);
+
+ TyTy::BaseType *receiver = nullptr;
+ ok = ctx->get_tyctx ()->lookup_receiver (
+ expr.get_mappings ().get_hirid (), &receiver);
+ rust_assert (ok);
+
+ if (receiver->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ TyTy::ParamType *p
+ = static_cast<TyTy::ParamType *> (receiver);
+ receiver = p->resolve ();
+ }
+
+ // the type resolver can only resolve type bounds to their trait
+ // item so its up to us to figure out if this path should resolve
+ // to an trait-impl-block-item or if it can be defaulted to the
+ // trait-impl-item's definition
+ std::vector<Resolver::PathProbeCandidate> candidates
+ = Resolver::PathProbeType::Probe (
+ receiver, expr.get_final_segment ().get_segment (), true,
+ false, true);
+
+ if (candidates.size () == 0)
+ {
+ // this means we are defaulting back to the trait_item if
+ // possible
+ // TODO
+ gcc_unreachable ();
+ }
+ else
+ {
+ Resolver::PathProbeCandidate &candidate = candidates.at (0);
+ rust_assert (candidate.is_impl_candidate ());
+
+ HIR::ImplBlock *impl = candidate.item.impl.parent;
+ HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
+
+ TyTy::BaseType *self = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ impl->get_type ()->get_mappings ().get_hirid (), &self);
+ rust_assert (ok);
+
+ if (!lookup->has_subsititions_defined ())
+ CompileInherentImplItem::Compile (self, impl_item, ctx,
+ true);
+ else
+ CompileInherentImplItem::Compile (self, impl_item, ctx,
+ true, lookup);
+
+ lookup->set_ty_ref (
+ impl_item->get_impl_mappings ().get_hirid ());
+ }
+ }
+ else
{
rust_assert (parent_impl_id != UNKNOWN_HIRID);
HIR::Item *impl_ref = ctx->get_mappings ()->lookup_hir_item (
@@ -114,18 +185,13 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
CompileInherentImplItem::Compile (self, resolved_item, ctx,
true, lookup);
}
- else
- {
- rust_error_at (expr.get_locus (),
- "failed to lookup definition declaration");
- return;
- }
}
if (!ctx->lookup_function_decl (lookup->get_ty_ref (), &fn))
{
- rust_fatal_error (expr.get_locus (),
- "forward declaration was not compiled");
+ resolved = ctx->get_backend ()->error_expression ();
+ rust_error_at (expr.get_locus (),
+ "forward declaration was not compiled");
return;
}
}
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index aa9aa2d..f422572 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -20,6 +20,8 @@
#include "rust-compile-item.h"
#include "rust-compile-expr.h"
#include "rust-compile-struct-field-expr.h"
+#include "rust-hir-trait-resolve.h"
+#include "rust-hir-path-probe.h"
#include "fnv-hash.h"
namespace Rust {
@@ -141,31 +143,105 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
expr.get_mappings ().get_crate_num (), ref, nullptr);
if (resolved_item == nullptr)
{
- rust_error_at (expr.get_locus (),
- "failed to lookup forward declaration");
- return;
- }
+ // it might be resolved to a trait item
+ HIR::TraitItem *trait_item
+ = ctx->get_mappings ()->lookup_hir_trait_item (
+ expr.get_mappings ().get_crate_num (), ref);
+ HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping (
+ trait_item->get_mappings ().get_hirid ());
+
+ Resolver::TraitReference &trait_ref
+ = Resolver::TraitResolver::error_node ();
+ bool ok = ctx->get_tyctx ()->lookup_trait_reference (
+ trait->get_mappings ().get_defid (), trait_ref);
+ rust_assert (ok);
+
+ TyTy::BaseType *receiver = nullptr;
+ ok = ctx->get_tyctx ()->lookup_receiver (
+ expr.get_mappings ().get_hirid (), &receiver);
+ rust_assert (ok);
+
+ if (receiver->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver);
+ receiver = p->resolve ();
+ }
- TyTy::BaseType *self_type = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (
- expr.get_receiver ()->get_mappings ().get_hirid (), &self_type))
- {
- rust_error_at (expr.get_locus (),
- "failed to resolve type for self param");
- return;
- }
+ // the type resolver can only resolve type bounds to their trait
+ // item so its up to us to figure out if this path should resolve
+ // to an trait-impl-block-item or if it can be defaulted to the
+ // trait-impl-item's definition
+ std::vector<Resolver::PathProbeCandidate> candidates
+ = Resolver::PathProbeType::Probe (
+ receiver, expr.get_method_name ().get_segment (), true, false,
+ true);
- if (!fntype->has_subsititions_defined ())
- CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true);
+ if (candidates.size () == 0)
+ {
+ // this means we are defaulting back to the trait_item if
+ // possible
+ // TODO
+ gcc_unreachable ();
+ }
+ else
+ {
+ Resolver::PathProbeCandidate &candidate = candidates.at (0);
+ rust_assert (candidate.is_impl_candidate ());
+
+ HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
+
+ TyTy::BaseType *self_type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_receiver ()->get_mappings ().get_hirid (),
+ &self_type))
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to resolve type for self param");
+ return;
+ }
+
+ if (!fntype->has_subsititions_defined ())
+ CompileInherentImplItem::Compile (self_type, impl_item, ctx,
+ true);
+ else
+ CompileInherentImplItem::Compile (self_type, impl_item, ctx,
+ true, fntype);
+
+ if (!ctx->lookup_function_decl (
+ impl_item->get_impl_mappings ().get_hirid (), &fn))
+ {
+ translated = ctx->get_backend ()->error_expression ();
+ rust_error_at (expr.get_locus (),
+ "forward declaration was not compiled");
+ return;
+ }
+ }
+ }
else
- CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true,
- fntype);
-
- if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
{
- rust_error_at (expr.get_locus (),
- "forward declaration was not compiled");
- return;
+ TyTy::BaseType *self_type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_receiver ()->get_mappings ().get_hirid (), &self_type))
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to resolve type for self param");
+ return;
+ }
+
+ if (!fntype->has_subsititions_defined ())
+ CompileInherentImplItem::Compile (self_type, resolved_item, ctx,
+ true);
+ else
+ CompileInherentImplItem::Compile (self_type, resolved_item, ctx,
+ true, fntype);
+
+ if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
+ {
+ translated = ctx->get_backend ()->error_expression ();
+ rust_error_at (expr.get_locus (),
+ "forward declaration was not compiled");
+ return;
+ }
}
}