Skip to content

Conversation

@brettmc
Copy link
Contributor

@brettmc brettmc commented Mar 31, 2025

avoid providing functions to defer fetching ClassEntry when extending classes and interfaces.

brettmc added 2 commits March 31, 2025 17:19
now accepts an Interface, like ClassEntry.implements() does
instead of accepting a fn to delay fetching ClassEntry, accept a String and look up
during init()
/// ```
pub fn extends(&mut self, parent: impl Fn() -> &'static ClassEntry + 'static) {
self.parent = Some(Box::new(parent));
pub fn extends(&mut self, parent_name: impl Into<String>) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be better if it accepted a ClassEntry (which could come from a just-created class or defer looking up from globals, similar to Interface::from_name), but I couldn't make it work. I think this is at least more ergonomic than the previous way?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about StateClass<()>? Add method from_name just for StateClass<()>.

Copy link
Member

@jmjoy jmjoy Mar 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter can accept StateClass<T>, which can be transmute to StateClass<()> internally. Anyway, T is just phantom data in StateClass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the pointer. Some progress, now we can either extends(StateClass<T>) or extends_name(String), the second one being useful for built-ins that we don't have a StateClass for. I could allow lazily creating a StateClass for built-ins, to unify those two methods - WDYT?

Copy link
Member

@jmjoy jmjoy Apr 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, I prefer to change it this way to be consistent with the implements method. What do you think?

master...jmjoy:phper-fork:extends

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, it's much nicer. I will try to cherry-pick this into my PR.

brettmc added 7 commits April 2, 2025 16:26
import ClassEntity::extends(StateClass) code from jmjoy:phper-fork:extends
these no longer have a use, since interfaces no longer implement based on a delaying function
@brettmc brettmc marked this pull request as ready for review April 3, 2025 00:20
@jmjoy jmjoy requested a review from Copilot April 3, 2025 01:32
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors how class and interface extension are handled by removing deferred lookup functions and switching to a StateClass-based approach for obtaining ClassEntry references. Key changes include:

  • Updating extension functions in ClassEntity and InterfaceEntity to use StateClass or Interface via name lookup.
  • Modifying tests, documentation, and examples to reflect the new API.
  • Removing closure-based deferral and replacing it with a more direct API that obtains ClassEntry from a global lookup if necessary.

Reviewed Changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/integration/src/classes.rs Updated tests to use StateClass-based extension and added a new helper for testing inheritance.
phper/src/classes.rs Refactored API for class/interface extension; replaced closure with StateClass and added unsafe transmute.
phper-doc/doc/_06_module/_07_register_interface/index.md Updated documentation examples for interface extension using Interface::from_name.
phper-doc/doc/_06_module/_06_register_class/index.md Revised class extension examples to demonstrate StateClass usage.
phper-doc/doc/_02_quick_start/_02_write_a_simple_http_client/index.md Adjusted quick start examples to reflect new exception inheritance.
examples/http-server/src/errors.rs Changed exception class extension to use StateClass::from_name.
examples/http-client/src/errors.rs Updated exception extension in client errors to use the new API.
Files not reviewed (1)
  • tests/integration/tests/php/classes.php: Language not supported

pub fn extends(&mut self, parent: impl Fn() -> &'static ClassEntry + 'static) {
self.parent = Some(Box::new(parent));
pub fn extends<S: 'static>(&mut self, parent: StateClass<S>) {
self.parent = Some(unsafe { transmute::<StateClass<S>, StateClass<()>>(parent) });
Copy link

Copilot AI Apr 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of unsafe transmute here can lead to undefined behavior if the lifetime conversion between StateClass and StateClass<()> is not guaranteed to be safe. Consider using a safer, more explicit conversion method.

Copilot uses AI. Check for mistakes.
Comment on lines +844 to +845
let entry: &'static ClassEntry =
unsafe { std::mem::transmute(interface.as_class_entry()) };
Copy link

Copilot AI Apr 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using unsafe transmute in this context may introduce subtle lifetime issues when converting interface's ClassEntry. It is recommended to explore a safer alternative to handle the conversion explicitly.

Suggested change
let entry: &'static ClassEntry =
unsafe { std::mem::transmute(interface.as_class_entry()) };
let entry: &'static ClassEntry = interface.as_class_entry();

Copilot uses AI. Check for mistakes.
@jmjoy jmjoy merged commit 477bb83 into phper-framework:master Apr 3, 2025
22 checks passed
This was referenced Apr 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants