-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix GH-19044: Protected properties are not scoped according to their prototype #19046
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: PHP-8.4
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype (protected(set) on non-hooked property) | ||
--FILE-- | ||
<?php | ||
|
||
class P { | ||
public mixed $foo { get => 42; } | ||
} | ||
|
||
class C1 extends P { | ||
public protected(set) mixed $foo = 1; | ||
} | ||
|
||
class C2 extends P { | ||
public protected(set) mixed $foo; | ||
|
||
static function foo($c) { return $c->foo += 1; } | ||
} | ||
|
||
var_dump(C2::foo(new C1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(43) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype | ||
--FILE-- | ||
<?php | ||
|
||
abstract class P { | ||
protected $foo; | ||
} | ||
|
||
class C1 extends P { | ||
protected $foo = 1; | ||
} | ||
|
||
class C2 extends P { | ||
protected $foo = 2; | ||
|
||
static function foo($c) { return $c->foo; } | ||
} | ||
|
||
var_dump(C2::foo(new C2)); | ||
var_dump(C2::foo(new C1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(2) | ||
int(1) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype (common ancestor has a protected setter) | ||
--FILE-- | ||
<?php | ||
|
||
abstract class P { | ||
abstract public mixed $foo { get; } | ||
} | ||
|
||
class C1 extends P { | ||
public protected(set) mixed $foo { get => 1; set {} } | ||
} | ||
|
||
class GrandC1 extends C1 { | ||
public protected(set) mixed $foo { get => 2; set {} } | ||
} | ||
|
||
class C2 extends C1 { | ||
static function foo($c) { return $c->foo += 1; } | ||
} | ||
|
||
var_dump(C2::foo(new GrandC1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(3) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype (common ancestor does not have a setter) | ||
--FILE-- | ||
<?php | ||
|
||
abstract class P { | ||
abstract public mixed $foo { get; } | ||
} | ||
|
||
class C1 extends P { | ||
public mixed $foo { get => 1; } | ||
} | ||
|
||
class GrandC1 extends C1 { | ||
public protected(set) mixed $foo { get => 2; set {} } | ||
} | ||
|
||
class C2 extends C1 { | ||
static function foo($c) { return $c->foo += 1; } | ||
} | ||
|
||
var_dump(C2::foo(new GrandC1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(3) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype (abstract parent defining visibility only takes precedence) | ||
--FILE-- | ||
<?php | ||
|
||
abstract class P { | ||
abstract protected(set) mixed $foo { get; set; } | ||
} | ||
|
||
class C1 extends P { | ||
public protected(set) mixed $foo { get => 2; set {} } | ||
} | ||
|
||
class C2 extends P { | ||
public mixed $foo = 1; | ||
|
||
static function foo($c) { return $c->foo += 1; } | ||
} | ||
|
||
var_dump(C2::foo(new C1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(3) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype (abstract parent sets protected(set) with not having grandparent a setter - both inherit from parent) | ||
--FILE-- | ||
<?php | ||
|
||
abstract class GP { | ||
abstract mixed $foo { get; } | ||
} | ||
|
||
abstract class P extends GP { | ||
abstract protected(set) mixed $foo { get; set; } | ||
} | ||
|
||
class C1 extends P { | ||
public protected(set) mixed $foo { get => 2; set {} } | ||
} | ||
|
||
class C2 extends P { | ||
public mixed $foo = 1; | ||
|
||
static function foo($c) { return $c->foo += 1; } | ||
} | ||
|
||
var_dump(C2::foo(new C1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(3) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype (abstract parent sets protected(set) with not having grandparent a setter - one inherits from grandparent) | ||
--FILE-- | ||
<?php | ||
|
||
abstract class GP { | ||
abstract mixed $foo { get; } | ||
} | ||
|
||
abstract class P extends GP { | ||
abstract protected(set) mixed $foo { get; set; } | ||
} | ||
|
||
class C1 extends P { | ||
public protected(set) mixed $foo { get => 2; set {} } | ||
} | ||
|
||
class C2 extends GP { | ||
public mixed $foo = 1; | ||
|
||
static function foo($c) { return $c->foo += 1; } | ||
} | ||
|
||
var_dump(C2::foo(new C1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(3) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype (abstract parent has implicit set hook) | ||
--FILE-- | ||
<?php | ||
|
||
abstract class GP { | ||
public abstract mixed $foo { get; } | ||
} | ||
|
||
class P extends GP { | ||
public protected(set) mixed $foo { get => $this->foo; } | ||
} | ||
|
||
class C1 extends P { | ||
public protected(set) mixed $foo = 1; | ||
} | ||
|
||
class C2 extends P { | ||
public protected(set) mixed $foo; | ||
|
||
static function foo($c) { return $c->foo += 1; } | ||
} | ||
|
||
var_dump(C2::foo(new C1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(2) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
GH-19044: Protected properties must be scoped according to their prototype (hooks variation) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: We have gh19044.phpt and gh19044-1.phpt (along with other gh19044.phpt's), which is a bit confusing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you'd rather have attached a number to them all? I thought first one without number and the extras get one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, or bump all the other ones by one so we don't have one with without prefix and one with
Or:
I prefer the latter, but either works. |
||
--FILE-- | ||
<?php | ||
|
||
abstract class P { | ||
abstract protected $foo { get; } | ||
} | ||
|
||
class C1 extends P { | ||
protected $foo = 1; | ||
} | ||
|
||
class C2 extends P { | ||
protected $foo = 2; | ||
|
||
static function foo($c) { return $c->foo; } | ||
} | ||
|
||
var_dump(C2::foo(new C2)); | ||
var_dump(C2::foo(new C1)); | ||
|
||
?> | ||
--EXPECT-- | ||
int(2) | ||
int(1) |
Uh oh!
There was an error while loading. Please reload this page.