From a19b626d4c2c0b4a7e1da4f344a2904fdc4a3127 Mon Sep 17 00:00:00 2001 From: ju1ius Date: Wed, 23 Nov 2022 20:31:23 +0100 Subject: [PATCH 1/2] [docs] describes restrictions on generic parameters for registered classes --- guide/src/macros/classes.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/guide/src/macros/classes.md b/guide/src/macros/classes.md index 3a423d1fad..14c352d982 100644 --- a/guide/src/macros/classes.md +++ b/guide/src/macros/classes.md @@ -32,6 +32,34 @@ You can rename the property with options: - `rename` - Allows you to rename the property, e.g. `#[prop(rename = "new_name")]` +## Restrictions + +### No lifetime parameters + +Rust lifetimes are used by the Rust compiler to reason about a program's memory safety. +They are a compile-time only concept; +there is no way to access Rust lifetimes at runtime from a dynamic language like PHP. + +As soon as Rust data is exposed to PHP, +there is no guarantee which the Rust compiler can make on how long the data will live. +PHP is a reference-counted language and those references can be held +for an arbitrarily long time which is untraceable by the Rust compiler. +The only possible way to express this correctly is to require that any `#[php_class]` +does not borrow data for any lifetime shorter than the `'static` lifetime, +i.e. the `#[php_class]` cannot have any lifetime parameters. + +When you need to share ownership of data between PHP and Rust, +instead of using borrowed references with lifetimes consider using +reference-counted smart pointers such as [Arc](https://doc.rust-lang.org/std/sync/struct.Arc.html). + +### No generic parameters + +A Rust struct `Foo` with a generic parameter `T` generates new compiled implementations +each time it is used with a different concrete type for `T`. +These new implementations are generated by the compiler at each usage site. +This is incompatible with wrapping `Foo` in PHP, +where there needs to be a single compiled implementation of `Foo` which is integrated with the PHP interpreter. + ## Example This example creates a PHP class `Human`, adding a PHP property `address`. From dd9a415014abeea4d02f2a1a3e78d3e28cf020ab Mon Sep 17 00:00:00 2001 From: Pierre Tondereau Date: Thu, 24 Nov 2022 11:10:44 +0100 Subject: [PATCH 2/2] Apply suggestions from code review --- guide/src/macros/classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guide/src/macros/classes.md b/guide/src/macros/classes.md index 14c352d982..ad62294032 100644 --- a/guide/src/macros/classes.md +++ b/guide/src/macros/classes.md @@ -43,13 +43,13 @@ there is no way to access Rust lifetimes at runtime from a dynamic language like As soon as Rust data is exposed to PHP, there is no guarantee which the Rust compiler can make on how long the data will live. PHP is a reference-counted language and those references can be held -for an arbitrarily long time which is untraceable by the Rust compiler. +for an arbitrarily long time, which is untraceable by the Rust compiler. The only possible way to express this correctly is to require that any `#[php_class]` does not borrow data for any lifetime shorter than the `'static` lifetime, i.e. the `#[php_class]` cannot have any lifetime parameters. When you need to share ownership of data between PHP and Rust, -instead of using borrowed references with lifetimes consider using +instead of using borrowed references with lifetimes, consider using reference-counted smart pointers such as [Arc](https://doc.rust-lang.org/std/sync/struct.Arc.html). ### No generic parameters