Skip to content

#[implements] doesn't generate the right stubs #326

@faassen

Description

@faassen

The docs here:

https://davidcole1340.github.io/ext-php-rs/macros/classes.html#implementing-an-interface

tell me I can use #[implements()] to implement an interface.

And indeed using this test code:

use ext_php_rs::prelude::*;
use ext_php_rs::{exception::PhpResult, types::Zval, zend::ce};

#[php_class]
#[implements(ce::arrayaccess())]
#[implements(ce::countable())]
#[derive(Default)]
pub struct EvenNumbersArray;

/// Returns `true` if the array offset is an even number.
/// Usage:
/// ```php
/// $arr = new EvenNumbersArray();
/// var_dump($arr[0]); // true
/// var_dump($arr[1]); // false
/// var_dump($arr[2]); // true
/// var_dump($arr[3]); // false
/// var_dump($arr[4]); // true
/// var_dump($arr[5] = true); // Fatal error:  Uncaught Exception: Setting values is not supported
/// ```
#[php_impl]
impl EvenNumbersArray {
    pub fn __construct() -> EvenNumbersArray {
        EvenNumbersArray {}
    }
    pub fn count(&self) -> i64 {
        10
    }

    // We need to use `Zval` because ArrayAccess needs $offset to be a `mixed`
    pub fn offset_exists(&self, offset: &'_ Zval) -> bool {
        offset.is_long()
    }
    pub fn offset_get(&self, offset: &'_ Zval) -> PhpResult<bool> {
        let integer_offset = offset.long().ok_or("Expected integer offset")?;
        Ok(integer_offset % 2 == 0)
    }
    pub fn offset_set(&mut self, _offset: &'_ Zval, _value: &'_ Zval) -> PhpResult {
        Err("Setting values is not supported".into())
    }
    pub fn offset_unset(&mut self, _offset: &'_ Zval) -> PhpResult {
        Err("Setting values is not supported".into())
    }
}

#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
    module
}

array access and use of the count function both work as I expect when I execute things:

<?php

$a = new EvenNumbersArray();

$even = $a[0];
$uneven = $a[1];
$c = count($a);

var_dump($even);
var_dump($uneven);
var_dump($c);

But my editor tooling (PHP Intelephense in vs code) claims I can't use the count function as "Expected type 'Countable|array'. Found 'EvenNumbersArray'.".

Looking at the generated PHP stubs, something seems to be wrong with the interface declaration - it's as if the Rust strings are directly inserted:

  class EvenNumbersArray implements ce :: arrayaccess(), ce :: countable() {

and at least Intelephense says that :: is a syntax error.

I think it should be:

   class EvenNumberArray implements ArrayAccess, Countable {

Strangely enough I don't get a complaint about array accesses here, even though the proper array access isn't declared.

PS. In non-example code I also am having trouble convincing not only stubs but also the PHP runtime that something is an array or countable, but that does work in this minimal example so I'm still looking at what could have caused this.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions