Skip to content

Commit b49a958

Browse files
committed
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 <[email protected]>
1 parent cfc51d4 commit b49a958

File tree

4 files changed

+57
-14
lines changed

4 files changed

+57
-14
lines changed

gcc/rust/typecheck/rust-tyty-bounds.cc

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -227,22 +227,26 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path,
227227
std::vector<std::unique_ptr<HIR::Type>> inputs;
228228
inputs.push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
229229

230+
// resolve the fn_once_output type which assumes there must be an output
231+
// set
232+
rust_assert (fn.has_return_type ());
233+
TypeCheckType::Resolve (fn.get_return_type ().get ());
234+
235+
HIR::TraitItem *trait_item = mappings->lookup_trait_item_lang_item (
236+
Analysis::RustLangItem::ItemType::FN_ONCE_OUTPUT);
237+
238+
std::vector<HIR::GenericArgsBinding> bindings;
239+
Location output_locus = fn.get_return_type ()->get_locus ();
240+
HIR::GenericArgsBinding binding (Identifier (
241+
trait_item->trait_identifier ()),
242+
fn.get_return_type ()->clone_type (),
243+
output_locus);
244+
bindings.push_back (std::move (binding));
245+
230246
args = HIR::GenericArgs ({} /* lifetimes */,
231247
std::move (inputs) /* type_args*/,
232-
{} /* binding_args*/, {} /* const_args */,
233-
final_seg->get_locus ());
234-
235-
// resolve the fn_once_output type
236-
TyTy::BaseType *fn_once_output_ty
237-
= fn.has_return_type ()
238-
? TypeCheckType::Resolve (fn.get_return_type ().get ())
239-
: TyTy::TupleType::get_unit_type (
240-
final_seg->get_mappings ().get_hirid ());
241-
context->insert_implicit_type (final_seg->get_mappings ().get_hirid (),
242-
fn_once_output_ty);
243-
244-
// setup the associated type.. ??
245-
// fn_once_output_ty->debug ();
248+
std::move (bindings) /* binding_args*/,
249+
{} /* const_args */, final_seg->get_locus ());
246250
}
247251
break;
248252

gcc/rust/util/rust-hir-map.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,5 +1137,18 @@ Mappings::lookup_builtin_marker ()
11371137
return builtinMarker;
11381138
}
11391139

1140+
HIR::TraitItem *
1141+
Mappings::lookup_trait_item_lang_item (Analysis::RustLangItem::ItemType item)
1142+
{
1143+
DefId trait_item_id = UNKNOWN_DEFID;
1144+
bool trait_item_lang_item_defined = lookup_lang_item (item, &trait_item_id);
1145+
1146+
// FIXME
1147+
// make this an error? what does rustc do when a lang item is not defined?
1148+
rust_assert (trait_item_lang_item_defined);
1149+
1150+
return lookup_trait_item_defid (trait_item_id);
1151+
}
1152+
11401153
} // namespace Analysis
11411154
} // namespace Rust

gcc/rust/util/rust-hir-map.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,9 @@ class Mappings
321321

322322
HIR::ImplBlock *lookup_builtin_marker ();
323323

324+
HIR::TraitItem *
325+
lookup_trait_item_lang_item (Analysis::RustLangItem::ItemType item);
326+
324327
private:
325328
Mappings ();
326329

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
pub enum Option<T> {
2+
Some(T),
3+
None,
4+
}
5+
6+
pub use Option::{None, Some};
7+
8+
#[lang = "fn_once"]
9+
pub trait FnOnce<Args> {
10+
#[lang = "fn_once_output"]
11+
type Output;
12+
13+
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
14+
}
15+
16+
impl<T> Option<T> {
17+
pub fn map<R, F: FnOnce(T) -> R>(self, f: F) -> Option<R> {
18+
match self {
19+
Some(value) => Some(f(value)),
20+
None => None,
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)