aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2023-07-02 20:24:43 +0100
committerPhilip Herron <philip.herron@embecosm.com>2023-07-02 22:13:45 +0000
commitb49a9581d559827de70196de0c1cad135e70e542 (patch)
treefabea3b2ea301fd33cb462191716e1e7c3c65132 /gcc
parentcfc51d46fcdb70bde84f030557c96866f3b18e23 (diff)
downloadgcc-b49a9581d559827de70196de0c1cad135e70e542.zip
gcc-b49a9581d559827de70196de0c1cad135e70e542.tar.gz
gcc-b49a9581d559827de70196de0c1cad135e70e542.tar.bz2
gccrs: Track fn_once output lang item properly
In order to setup the Output assoicated type we can rely on using generic argument bindings. So for example when we have the FnOnce trait: #[lang = "fn_once"] pub trait FnOnce<Args> { #[lang = "fn_once_output"] type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } Thn we might have a function such as: pub fn map<R, F: FnOnce(T) -> R>(self, f: F) -> Option<R> { ... } This trait bound predicate of FnOnce(T) -> R we setup generics for the bound as: FnOnce<(T), Output=R> This means we can reuse our generic arguments handling to get this support. Fixes #2105 gcc/rust/ChangeLog: * typecheck/rust-tyty-bounds.cc (TypeCheckBase::get_predicate_from_bound): track output * util/rust-hir-map.cc (Mappings::lookup_trait_item_lang_item): new helper * util/rust-hir-map.h: add prototype for helper gcc/testsuite/ChangeLog: * rust/compile/issue-2105.rs: New test. Signed-off-by: Philip Herron <herron.philip@googlemail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc32
-rw-r--r--gcc/rust/util/rust-hir-map.cc13
-rw-r--r--gcc/rust/util/rust-hir-map.h3
-rw-r--r--gcc/testsuite/rust/compile/issue-2105.rs23
4 files changed, 57 insertions, 14 deletions
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 12e6659..ec64aa7 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -227,22 +227,26 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path,
std::vector<std::unique_ptr<HIR::Type>> inputs;
inputs.push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
+ // resolve the fn_once_output type which assumes there must be an output
+ // set
+ rust_assert (fn.has_return_type ());
+ TypeCheckType::Resolve (fn.get_return_type ().get ());
+
+ HIR::TraitItem *trait_item = mappings->lookup_trait_item_lang_item (
+ Analysis::RustLangItem::ItemType::FN_ONCE_OUTPUT);
+
+ std::vector<HIR::GenericArgsBinding> bindings;
+ Location output_locus = fn.get_return_type ()->get_locus ();
+ HIR::GenericArgsBinding binding (Identifier (
+ trait_item->trait_identifier ()),
+ fn.get_return_type ()->clone_type (),
+ output_locus);
+ bindings.push_back (std::move (binding));
+
args = HIR::GenericArgs ({} /* lifetimes */,
std::move (inputs) /* type_args*/,
- {} /* binding_args*/, {} /* const_args */,
- final_seg->get_locus ());
-
- // resolve the fn_once_output type
- TyTy::BaseType *fn_once_output_ty
- = fn.has_return_type ()
- ? TypeCheckType::Resolve (fn.get_return_type ().get ())
- : TyTy::TupleType::get_unit_type (
- final_seg->get_mappings ().get_hirid ());
- context->insert_implicit_type (final_seg->get_mappings ().get_hirid (),
- fn_once_output_ty);
-
- // setup the associated type.. ??
- // fn_once_output_ty->debug ();
+ std::move (bindings) /* binding_args*/,
+ {} /* const_args */, final_seg->get_locus ());
}
break;
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 87a3a73..3326e7e 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -1137,5 +1137,18 @@ Mappings::lookup_builtin_marker ()
return builtinMarker;
}
+HIR::TraitItem *
+Mappings::lookup_trait_item_lang_item (Analysis::RustLangItem::ItemType item)
+{
+ DefId trait_item_id = UNKNOWN_DEFID;
+ bool trait_item_lang_item_defined = lookup_lang_item (item, &trait_item_id);
+
+ // FIXME
+ // make this an error? what does rustc do when a lang item is not defined?
+ rust_assert (trait_item_lang_item_defined);
+
+ return lookup_trait_item_defid (trait_item_id);
+}
+
} // namespace Analysis
} // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 6e6a1c8..964b626 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -321,6 +321,9 @@ public:
HIR::ImplBlock *lookup_builtin_marker ();
+ HIR::TraitItem *
+ lookup_trait_item_lang_item (Analysis::RustLangItem::ItemType item);
+
private:
Mappings ();
diff --git a/gcc/testsuite/rust/compile/issue-2105.rs b/gcc/testsuite/rust/compile/issue-2105.rs
new file mode 100644
index 0000000..7d1c9a1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2105.rs
@@ -0,0 +1,23 @@
+pub enum Option<T> {
+ Some(T),
+ None,
+}
+
+pub use Option::{None, Some};
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+impl<T> Option<T> {
+ pub fn map<R, F: FnOnce(T) -> R>(self, f: F) -> Option<R> {
+ match self {
+ Some(value) => Some(f(value)),
+ None => None,
+ }
+ }
+}