Skip to content

Commit 6448578

Browse files
committed
add more tests and prevent usage in traits
1 parent 3fd8e14 commit 6448578

File tree

4 files changed

+59
-6
lines changed

4 files changed

+59
-6
lines changed

Zend/zend_compile.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9177,6 +9177,11 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
91779177
"\\", 1,
91789178
ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name));
91799179

9180+
if (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) {
9181+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s inside a trait",
9182+
ZSTR_VAL(name));
9183+
}
9184+
91809185
/* configure the class from the modifiers */
91819186
decl->flags |= decl->attr & ZEND_ACC_FINAL;
91829187
if (decl->attr & ZEND_ACC_ABSTRACT) {

Zend/zend_execute.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,7 @@ static zend_always_inline bool i_zend_check_property_type(const zend_property_in
10471047

10481048
static zend_result zend_check_type_visibility(const zend_class_entry *ce, const zend_property_info *info, uint32_t current_visibility)
10491049
{
1050+
check_lexical_scope:
10501051
/* public classes are always visible */
10511052
if (!ce->required_scope) {
10521053
return SUCCESS;
@@ -1065,14 +1066,19 @@ static zend_result zend_check_type_visibility(const zend_class_entry *ce, const
10651066

10661067
/* a private class is visible if it is the same class as the lexical scope and the current visibility is private */
10671068
if (ce->required_scope_absolute && ce->required_scope == info->ce) {
1068-
if (current_visibility < ZEND_ACC_PRIVATE) {
1069+
if ((current_visibility & ZEND_ACC_PPP_MASK) < ZEND_ACC_PRIVATE) {
10691070
zend_type_error("Cannot declare private class %s to a %s property in %s::%s", ZSTR_VAL(ce->name), zend_visibility_string(current_visibility), ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
10701071
return FAILURE;
10711072
}
10721073

10731074
return SUCCESS;
10741075
}
10751076

1077+
if (ce->lexical_scope != info->ce && ce->lexical_scope && (ce->lexical_scope->type == ZEND_USER_CLASS || ce->lexical_scope->type == ZEND_INTERNAL_CLASS)) {
1078+
ce = ce->lexical_scope;
1079+
goto check_lexical_scope;
1080+
}
1081+
10761082
zend_type_error("Cannot declare %s to weaker visible property %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
10771083
return FAILURE;
10781084
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
nested enums
3+
--FILE--
4+
<?php
5+
enum Status {
6+
case Active;
7+
case Inactive;
8+
9+
private enum Processing {
10+
case Pending;
11+
case Completed;
12+
}
13+
14+
public class Message {
15+
16+
private Processing $processing = Processing::Pending;
17+
18+
public function __construct(private Status $status) {}
19+
20+
public function getMessage(): string {
21+
return match ([$this->status, $this->processing]) {
22+
[Status::Active, Processing::Pending] => "Active and Pending",
23+
[Status::Active, Processing::Completed] => "Active and Completed",
24+
[Status::Inactive, Processing::Pending] => "Inactive and Pending",
25+
[Status::Inactive, Processing::Completed] => throw new LogicException('should not happen'),
26+
};
27+
}
28+
}
29+
30+
public function createMessage(): Message {
31+
return new Message($this);
32+
}
33+
}
34+
35+
var_dump(Status::Active->createMessage());
36+
echo Status::Inactive->createMessage()->getMessage() . "\n";
37+
?>
38+
--EXPECT--
39+
object(Status\Message)#3 (2) {
40+
["processing":"Status\Message":private]=>
41+
enum(Status\Processing::Pending)
42+
["status":"Status\Message":private]=>
43+
enum(Status::Active)
44+
}
45+
Inactive and Pending

tests/classes/inner_classes/trait_usage_001.phpt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,5 @@ var_dump(class_exists(Outer\Inner::class));
1717
var_dump(class_exists(Foo\Inner::class));
1818

1919
?>
20-
--EXPECT--
21-
object(Outer\Inner)#1 (0) {
22-
}
23-
bool(true)
24-
bool(false)
20+
--EXPECTF--
21+
Fatal error: Cannot declare class Outer\Inner inside a trait in %s on line %d

0 commit comments

Comments
 (0)