Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
--FILE--
<?php

#[DelayedTargetValidation]
#[Deprecated]
interface DemoInterface {}

#[DelayedTargetValidation]
#[Deprecated]
class DemoClass {}
Expand All @@ -16,7 +12,6 @@ class DemoClass {}
enum DemoEnum {}

$cases = [
new ReflectionClass('DemoInterface'),
new ReflectionClass('DemoClass'),
new ReflectionClass('DemoEnum'),
];
Expand All @@ -35,39 +30,6 @@ foreach ($cases as $r) {
?>
--EXPECTF--
********************
Interface [ <user> interface DemoInterface ] {
@@ %s %d-%d

- Constants [0] {
}

- Static properties [0] {
}

- Static methods [0] {
}

- Properties [0] {
}

- Methods [0] {
}
}

array(2) {
[0]=>
object(ReflectionAttribute)#%d (1) {
["name"]=>
string(23) "DelayedTargetValidation"
}
[1]=>
object(ReflectionAttribute)#%d (1) {
["name"]=>
string(10) "Deprecated"
}
}
Error: Cannot apply #[\Deprecated] to interface DemoInterface
********************
Class [ <user> class DemoClass ] {
@@ %s %d-%d

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ class WithDeprecatedTrait {
use DeprecatedTrait;
}

#[DelayedTargetValidation]
#[Deprecated] // Does something here
interface DeprecatedInterface {}

class ImplementsDeprecatedInterface implements DeprecatedInterface {}

#[DelayedTargetValidation]
#[Deprecated] // Does something here
function demoFn() {
Expand All @@ -70,6 +76,8 @@ var_dump(GLOBAL_CONST);
?>
--EXPECTF--
Deprecated: Trait DeprecatedTrait used by WithDeprecatedTrait is deprecated in %s on line %d

Deprecated: Interface DeprecatedInterface implemented by ImplementsDeprecatedInterface is deprecated in %s on line %d
Got: example

Deprecated: Method DemoClass::printVal() is deprecated in %s on line %d
Expand Down
11 changes: 0 additions & 11 deletions Zend/tests/attributes/deprecated/error_on_interface.phpt

This file was deleted.

34 changes: 34 additions & 0 deletions Zend/tests/attributes/deprecated/interfaces/basic.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
--TEST--
#[\Deprecated]: Basic interface deprecation
--FILE--
<?php

#[\Deprecated("please do not use")]
interface DemoInterface1 {}

#[\Deprecated("will be removed in 3.0", since: "2.7")]
interface DemoInterface2 {}

#[\Deprecated(message: "going away")]
interface DemoInterface3 {}

#[\Deprecated(since: "3.5")]
interface DemoInterface4 {}

class DemoClass implements
DemoInterface1,
DemoInterface2,
DemoInterface3,
DemoInterface4
{
}

?>
--EXPECTF--
Deprecated: Interface DemoInterface1 implemented by DemoClass is deprecated, please do not use in %s on line %d

Deprecated: Interface DemoInterface2 implemented by DemoClass is deprecated since 2.7, will be removed in 3.0 in %s on line %d

Deprecated: Interface DemoInterface3 implemented by DemoClass is deprecated, going away in %s on line %d

Deprecated: Interface DemoInterface4 implemented by DemoClass is deprecated since 3.5 in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--TEST--
#[\Deprecated]: Interfaces extending deprecated interfaces trigger warnings
--FILE--
<?php

#[\Deprecated("please do not use")]
interface DemoInterface1 {}

#[\Deprecated("will be removed in 3.0", since: "2.7")]
interface DemoInterface2 {}

#[\Deprecated(message: "going away")]
interface DemoInterface3 {}

#[\Deprecated(since: "3.5")]
interface DemoInterface4 {}

interface ExtendsDemo1 extends DemoInterface1 {}
interface ExtendsDemo2 extends DemoInterface2 {}
interface ExtendsDemo3 extends DemoInterface3 {}
interface ExtendsDemo4 extends DemoInterface4 {}

?>
--EXPECTF--
Deprecated: Interface DemoInterface1 extended by ExtendsDemo1 is deprecated, please do not use in %s on line %d

Deprecated: Interface DemoInterface2 extended by ExtendsDemo2 is deprecated since 2.7, will be removed in 3.0 in %s on line %d

Deprecated: Interface DemoInterface3 extended by ExtendsDemo3 is deprecated, going away in %s on line %d

Deprecated: Interface DemoInterface4 extended by ExtendsDemo4 is deprecated since 3.5 in %s on line %d
15 changes: 15 additions & 0 deletions Zend/tests/attributes/deprecated/interfaces/implements_child.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
#[\Deprecated]: Implementing a child of a deprecated interface
--FILE--
<?php

#[\Deprecated("please do not use")]
interface BaseInterface {}

interface ChildInterface extends BaseInterface {}

class DemoClass implements ChildInterface {}

?>
--EXPECTF--
Deprecated: Interface BaseInterface extended by ChildInterface is deprecated, please do not use in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
#[\Deprecated]: Implementing a deprecated interface and a child of it
--FILE--
<?php

#[\Deprecated("please do not use")]
interface BaseInterface {}

interface ChildInterface extends BaseInterface {}

class DemoClass implements BaseInterface, ChildInterface {}

?>
--EXPECTF--
Deprecated: Interface BaseInterface extended by ChildInterface is deprecated, please do not use in %s on line %d

Deprecated: Interface BaseInterface implemented by DemoClass is deprecated, please do not use in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
#[\Deprecated]: Parent class implements deprecated interface, child class inherits
--FILE--
<?php

#[\Deprecated("please do not use")]
interface DemoInterface {}

class Base implements DemoInterface {}

class Child extends Base {}

?>
--EXPECTF--
Deprecated: Interface DemoInterface implemented by Base is deprecated, please do not use in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
#[\Deprecated]: Parent class implements deprecated interface, child class inherits and also implements
--FILE--
<?php

#[\Deprecated("please do not use")]
interface DemoInterface {}

class Base implements DemoInterface {}

class Child extends Base implements DemoInterface {}

?>
--EXPECTF--
Deprecated: Interface DemoInterface implemented by Base is deprecated, please do not use in %s on line %d

Deprecated: Interface DemoInterface implemented by Child is deprecated, please do not use in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
#[\Deprecated]: Deprecation converted to ErrorException does not break
--FILE--
<?php

function my_error_handler(int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) {
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
}

set_error_handler('my_error_handler');

#[\Deprecated]
interface DemoInterface {}

class DemoClass implements DemoInterface {}

?>
--EXPECTF--
Fatal error: Uncaught ErrorException: Interface DemoInterface implemented by DemoClass is deprecated in %s:%d
Stack trace:
#0 %s(%d): my_error_handler(16384, 'Interface DemoI...', '%s', 12)
#1 {main}
thrown in %s on line %d
25 changes: 25 additions & 0 deletions Zend/tests/attributes/deprecated/interfaces/tool_comparison.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
#[\Deprecated]: Interface deprecation RFC example
--FILE--
<?php

#[\Deprecated]
interface BaseInterface {}

interface ChildInterface extends BaseInterface {}

class ImplementsBase implements BaseInterface {}

class ImplementsBoth implements BaseInterface, ChildInterface {}

class ImplementsChild implements ChildInterface {}

class ExtendsBaseImplementor extends ImplementsBase {}

?>
--EXPECTF--
Deprecated: Interface BaseInterface extended by ChildInterface is deprecated in %s on line %d

Deprecated: Interface BaseInterface implemented by ImplementsBase is deprecated in %s on line %d

Deprecated: Interface BaseInterface implemented by ImplementsBoth is deprecated in %s on line %d
35 changes: 35 additions & 0 deletions Zend/tests/attributes/deprecated/interfaces/type_okay.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
#[\Deprecated]: Instanceof, type checking, etc. for deprecated interfaces are okay
--FILE--
<?php

#[\Deprecated("please do not use")]
interface DemoInterface {}

class Identity {
public static function identity(
DemoInterface $in
): DemoInterface {
return $in;
}
}

class ImplementsDemo implements DemoInterface {};

$instance = new ImplementsDemo();

var_dump(is_a(ImplementsDemo::class, DemoInterface::class, true));
var_dump(is_a($instance, DemoInterface::class));
var_dump(is_subclass_of(Implementsdemo::class, DemoInterface::class, true));
var_dump(is_subclass_of($instance, DemoInterface::class));
var_dump($instance === Identity::identity($instance));
var_dump($instance instanceof DemoInterface);
?>
--EXPECTF--
Deprecated: Interface DemoInterface implemented by ImplementsDemo is deprecated, please do not use in %s on line %d
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
2 changes: 1 addition & 1 deletion Zend/zend_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ static zend_string *validate_deprecated(
/* Being used for a method or something, validation does not apply */
return NULL;
}
if (!(scope->ce_flags & ZEND_ACC_TRAIT)) {
if (!(scope->ce_flags & (ZEND_ACC_TRAIT|ZEND_ACC_INTERFACE))) {
const char *type = zend_get_object_type_case(scope, false);
return zend_strpprintf(0, "Cannot apply #[\\Deprecated] to %s %s", type, ZSTR_VAL(scope->name));
}
Expand Down
37 changes: 37 additions & 0 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -2032,6 +2032,43 @@ ZEND_API ZEND_COLD void zend_use_of_deprecated_trait(
zend_string_release(message_suffix);
}

static ZEND_COLD void zend_deprecated_interface_action(
zend_class_entry *iface,
const zend_string *by,
const char *action
) {
zend_string *message_suffix = ZSTR_EMPTY_ALLOC();

if (get_deprecation_suffix_from_attribute(iface->attributes, iface, &message_suffix) == FAILURE) {
return;
}

int code = iface->type == ZEND_INTERNAL_CLASS ? E_DEPRECATED : E_USER_DEPRECATED;

zend_error_unchecked(code, "Interface %s %s by %s is deprecated%S",
ZSTR_VAL(iface->name),
action,
ZSTR_VAL(by),
message_suffix
);

zend_string_release(message_suffix);
}

ZEND_API ZEND_COLD void zend_implementation_of_deprecated_interface(
zend_class_entry *iface,
const zend_string *implemented_by
) {
zend_deprecated_interface_action(iface, implemented_by, "implemented");
}

ZEND_API ZEND_COLD void zend_extending_deprecated_interface(
zend_class_entry *iface,
const zend_string *extended_by
) {
zend_deprecated_interface_action(iface, extended_by, "extended");
}

ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void)
{
zend_error(E_DEPRECATED, "Automatic conversion of false to array is deprecated");
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_functio
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name);
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_constant(const zend_constant *c, const zend_string *constant_name);
ZEND_API ZEND_COLD void zend_use_of_deprecated_trait(zend_class_entry *trait, const zend_string *used_by);
ZEND_API ZEND_COLD void zend_implementation_of_deprecated_interface(zend_class_entry *iface, const zend_string *implemented_by);
ZEND_API ZEND_COLD void zend_extending_deprecated_interface(zend_class_entry *iface, const zend_string *extended_by);
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void);
ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num);
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim);
Expand Down
11 changes: 11 additions & 0 deletions Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -3557,6 +3557,17 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
free_alloca(traits_and_interfaces, use_heap);
return NULL;
}
if (UNEXPECTED(iface->ce_flags & ZEND_ACC_DEPRECATED)) {
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
zend_extending_deprecated_interface(iface, ce->name);
} else {
zend_implementation_of_deprecated_interface(iface, ce->name);
}
if (UNEXPECTED(EG(exception))) {
free_alloca(traits_and_interfaces, use_heap);
return NULL;
}
}
traits_and_interfaces[ce->num_traits + i] = iface;
if (iface) {
UPDATE_IS_CACHEABLE(iface);
Expand Down
Loading