diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index ca88c4c7b03e..4d4746e9c3d0 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -2222,6 +2222,56 @@ FnPtr::clone () const get_combined_refs ()); } +void +FnPtr::setup_fn_once_output () const +{ + // lookup the lang items + auto fn_once_lookup = mappings.lookup_lang_item (LangItem::Kind::FN_ONCE); + auto fn_once_output_lookup + = mappings.lookup_lang_item (LangItem::Kind::FN_ONCE_OUTPUT); + if (!fn_once_lookup) + { + rust_fatal_error (UNKNOWN_LOCATION, + "Missing required % lang item"); + return; + } + if (!fn_once_output_lookup) + { + rust_fatal_error (UNKNOWN_LOCATION, + "Missing required % lang item"); + return; + } + + DefId &trait_id = fn_once_lookup.value (); + DefId &trait_item_id = fn_once_output_lookup.value (); + + // resolve to the trait + HIR::Item *item = mappings.lookup_defid (trait_id).value (); + rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait); + HIR::Trait *trait = static_cast (item); + + Resolver::TraitReference *trait_ref + = Resolver::TraitResolver::Resolve (*trait); + rust_assert (!trait_ref->is_error ()); + + // resolve to trait item + HIR::TraitItem *trait_item + = mappings.lookup_trait_item_defid (trait_item_id).value (); + rust_assert (trait_item->get_item_kind () + == HIR::TraitItem::TraitItemKind::TYPE); + std::string item_identifier = trait_item->trait_identifier (); + + // setup associated types #[lang = "fn_once_output"] + Resolver::TraitItemReference *item_reference = nullptr; + bool found = trait_ref->lookup_trait_item_by_type ( + item_identifier, Resolver::TraitItemReference::TraitItemType::TYPE, + &item_reference); + rust_assert (found); + + // setup + item_reference->associated_type_set (&get_result_type ()); +} + void ClosureType::accept_vis (TyVisitor &vis) { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 163d383ac728..02d064d83bab 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -971,7 +971,9 @@ class FnPtr : public CallableTypeInterface {Resolver::CanonicalPath::create_empty (), locus}, refs), params (std::move (params)), result_type (result_type) - {} + { + setup_fn_once_output (); + } FnPtr (HirId ref, HirId ty_ref, location_t locus, std::vector params, TyVar result_type, std::set refs = std::set ()) @@ -979,7 +981,9 @@ class FnPtr : public CallableTypeInterface {Resolver::CanonicalPath::create_empty (), locus}, refs), params (params), result_type (result_type) - {} + { + setup_fn_once_output (); + } std::string get_name () const override final { return as_string (); } @@ -1000,6 +1004,7 @@ class FnPtr : public CallableTypeInterface const TyVar &get_var_return_type () const { return result_type; } + TyTy::BaseType &get_result_type () const { return *result_type.get_tyty (); } size_t num_params () const { return params.size (); } void accept_vis (TyVisitor &vis) override; @@ -1016,6 +1021,8 @@ class FnPtr : public CallableTypeInterface std::vector &get_params () { return params; } const std::vector &get_params () const { return params; } + void setup_fn_once_output () const; + private: std::vector params; TyVar result_type; diff --git a/gcc/testsuite/rust/compile/format_args_basic_expansion.rs b/gcc/testsuite/rust/compile/format_args_basic_expansion.rs index 40bcd3c1433e..97c3831660b6 100644 --- a/gcc/testsuite/rust/compile/format_args_basic_expansion.rs +++ b/gcc/testsuite/rust/compile/format_args_basic_expansion.rs @@ -8,6 +8,14 @@ macro_rules! format_args { #[lang = "sized"] trait Sized {} +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + pub mod core { pub mod fmt { pub struct Formatter; diff --git a/gcc/testsuite/rust/compile/issue-2042.rs b/gcc/testsuite/rust/compile/issue-2042.rs index 9fee13de2f93..f5ed45e7e0c5 100644 --- a/gcc/testsuite/rust/compile/issue-2042.rs +++ b/gcc/testsuite/rust/compile/issue-2042.rs @@ -1,3 +1,15 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + + fn f<'r>(p: &'r mut fn(p: &mut ())) { (*p)(()) // { dg-error "expected .&mut ()." "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/privacy6.rs b/gcc/testsuite/rust/compile/privacy6.rs index e1e0fac282b4..43a905a79282 100644 --- a/gcc/testsuite/rust/compile/privacy6.rs +++ b/gcc/testsuite/rust/compile/privacy6.rs @@ -1,3 +1,13 @@ + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + + // { dg-additional-options "-w" } #[lang = "sized"] diff --git a/gcc/testsuite/rust/compile/rust_abi.rs b/gcc/testsuite/rust/compile/rust_abi.rs index ec9dc0d419e4..3cc42e2fcba5 100644 --- a/gcc/testsuite/rust/compile/rust_abi.rs +++ b/gcc/testsuite/rust/compile/rust_abi.rs @@ -1 +1,12 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + pub fn f(_: extern "Rust" fn()) {} diff --git a/gcc/testsuite/rust/compile/torture/function_reference2.rs b/gcc/testsuite/rust/compile/torture/function_reference2.rs index 3c3e7c10910c..55706e679279 100644 --- a/gcc/testsuite/rust/compile/torture/function_reference2.rs +++ b/gcc/testsuite/rust/compile/torture/function_reference2.rs @@ -1,3 +1,14 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + fn test(a: i32) -> i32 { a + 1 } diff --git a/gcc/testsuite/rust/compile/torture/function_reference3.rs b/gcc/testsuite/rust/compile/torture/function_reference3.rs index 0cb3181f4a16..2a92277cd0b3 100644 --- a/gcc/testsuite/rust/compile/torture/function_reference3.rs +++ b/gcc/testsuite/rust/compile/torture/function_reference3.rs @@ -1,3 +1,15 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + + struct Foo { a: fn(i32) -> i32, b: i32, diff --git a/gcc/testsuite/rust/compile/torture/function_reference4.rs b/gcc/testsuite/rust/compile/torture/function_reference4.rs index 977e4c972159..70682b922aaa 100644 --- a/gcc/testsuite/rust/compile/torture/function_reference4.rs +++ b/gcc/testsuite/rust/compile/torture/function_reference4.rs @@ -1,3 +1,14 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + fn test(a: i32) -> i32 { a + 1 } diff --git a/gcc/testsuite/rust/compile/try-catch-unwind-new.rs b/gcc/testsuite/rust/compile/try-catch-unwind-new.rs index b176f7a100ba..93909bf0c49c 100644 --- a/gcc/testsuite/rust/compile/try-catch-unwind-new.rs +++ b/gcc/testsuite/rust/compile/try-catch-unwind-new.rs @@ -1,6 +1,17 @@ // { dg-options "-O2 -w -fdump-tree-optimized" } #![feature(intrinsics)] +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + extern "rust-intrinsic" { // { dg-final { scan-tree-dump-times "__builtin_eh_pointer" 1 "optimized" } } fn catch_unwind(try_fn: fn(_: *mut u8), data: *mut u8, catch_fn: fn(_: *mut u8, _: *mut u8)); diff --git a/gcc/testsuite/rust/compile/try-catch-unwind-old.rs b/gcc/testsuite/rust/compile/try-catch-unwind-old.rs index e97d52cd64e3..39c1271f5dfc 100644 --- a/gcc/testsuite/rust/compile/try-catch-unwind-old.rs +++ b/gcc/testsuite/rust/compile/try-catch-unwind-old.rs @@ -1,6 +1,17 @@ // { dg-options "-O2 -w -fdump-tree-optimized" } #![feature(intrinsics)] +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + extern "rust-intrinsic" { // { dg-final { scan-tree-dump-times "__builtin_eh_pointer" 1 "optimized" } } fn r#try(try_fn: fn(_: *mut u8), data: *mut u8, catch_fn: fn(_: *mut u8, _: *mut u8)) -> i32;