diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-07-16 16:50:26 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-08-05 19:07:11 +0100 |
commit | 65ef30eb84314ae7525be4a4d7dd79d2868e3e3c (patch) | |
tree | bb7172a61dc354681743d86f708e021b4613cc9f /gcc/rust/backend/rust-compile.cc | |
parent | 0db1c804562aff23344cd5882db6fc65596e0966 (diff) | |
download | gcc-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/rust-compile.cc')
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 118 |
1 files changed, 97 insertions, 21 deletions
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; + } } } |