Skip to content

Warn on "parent" without parent at compile-time #3404

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

Closed
wants to merge 1 commit into from

Conversation

morrisonlevi
Copy link
Contributor

This adds a compile-time warning of level E_STRICT to usages of parent in class-scope where the class does not have a parent, e.g.

class InvalidClass {
  function method() {
    echo parent::class;
  }
}

This currently has two test failures where the E_STRICT is emitted twice. I was not sure if the check was always redundant or if in some cases it isn't. I am hoping a reviewer will know better than me.

If a method definition like this is executed it generates a runtime error, so this should not be a controversial change. In PHP 8.0 we should change this from E_STRICT to an E_COMPILE_ERROR.


?>
--EXPECTF--
Strict Standards: Cannot use "parent" when no class scope is active in %s on line %d
Copy link
Contributor

Choose a reason for hiding this comment

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

This message is wrong, isn't it? Class scope is active, there is just no parent.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, I copied the wrong line. Will fix.

@morrisonlevi morrisonlevi force-pushed the parent branch 2 times, most recently from 2180d20 to 4443e98 Compare July 25, 2018 02:13
&& !CG(active_class_entry_parent_name))
{
zend_error_noreturn(
E_STRICT,
Copy link
Member

Choose a reason for hiding this comment

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

We no longer introduce E_STRICT warnings, please use E_WARNING instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

E_WARNING does not mean this will get changed in a future release. E_DEPRECATED seems odd. I think E_STRICT is the best choice, and unless my memory is failing me we never voted on not adding new E_STRICT; only to remove existing ones.

Copy link
Member

Choose a reason for hiding this comment

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

We decided to remove the E_STRICT category in https://wiki.php.net/rfc/reclassify_e_strict. If you'd like to go against this prior decision, this change is going to need an RFC.

Imho either E_DEPRECATED or E_WARNING are sensible choices.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This does not match my memory. I was pretty certain we only voted to reclassify existing ones, not remove the category entirely. I will choose E_DEPRECATED.

@@ -6453,6 +6467,10 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
}

CG(active_class_entry) = ce;
if (extends_ast) {
zend_string *extends_name = zend_ast_get_str(extends_ast);
CG(active_class_entry_parent_name) = zend_string_copy(extends_name);
Copy link
Member

Choose a reason for hiding this comment

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

This assigns the non-resolved class name. Either this should assign the correct class name, or should just be a boolean for whether it has a parent, to prevent confusion when other code wants to use this member in the future.

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 other code will need the name of the parent; for instance we reject string $parent = parent::class in parameters but there's no need to actually do this now. Will investigate resolving the class name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to check, what do you mean by "non-resolved"? I assume Bar in use Foo as Bar; class Baz extends Bar {} or something?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, that's right. You can either use zend_resolve_class_name, or try to get the already resolved name from above, though extracting it from literals might be a bit inconvenient.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Dmitry has changed this code recently; it should be easy to use now.

if (extends_ast) {
zend_string *extends_name = zend_ast_get_str(extends_ast);
CG(active_class_entry_parent_name) = zend_string_copy(extends_name);
}
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't it be NULLed out in the else case? I think it will currently not behave correctly if you have an outer class with parent and an inner (anonymous) class without.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That sounds right. Will investigate.

@morrisonlevi
Copy link
Contributor Author

morrisonlevi commented Jul 26, 2018

I've fixed a number of issues and rebased on latest master. I have supposedly enabled support for parent::class in compile-time expressions when a parent exists but need tests for this.

There is still an annoyance: for compile-time expressions that use parent::class but are invalid because there isn't a parent then there will be both an E_DEPRECATED and a compile time error. Still not sure how to fix this one.

@carusogabriel
Copy link
Contributor

carusogabriel commented Jul 30, 2018

Just a question: "Warn on "parent" without parent at compile-time"

compile-time: Do we have it here in the interpreter?

@Majkl578
Copy link
Contributor

Yes.

@morrisonlevi
Copy link
Contributor Author

The debug build failed on Travis, but it works for me locally. I adjusted a few more tests, including some for parent::class in constant expressions.

This still needs entries in NEWS/UPGRADING but aside from that can anyone spot issues, or would like more tests in certain areas?

@php-pulls
Copy link

Comment on behalf of carusogabriel at php.net:

Labelling

@morrisonlevi morrisonlevi deleted the parent branch September 28, 2018 21:12
@morrisonlevi morrisonlevi restored the parent branch September 28, 2018 21:12
@morrisonlevi morrisonlevi deleted the parent branch September 28, 2018 21:14
jrfnl added a commit to PHPCompatibility/PHPCompatibility that referenced this pull request Jun 14, 2019
> - Core
>    Using "parent" inside a class without parent is deprecated, and will throw
>    a compile-time error in the future. Currently an error will only be
>    generated if/when the parent is accessed at run-time.

Refs:
* https://github.com/php/php-src/blob/42cc58ff7b2fee1c17a00dc77a4873552ffb577f/UPGRADING#L303
* php/php-src#3404
* php/php-src#3564
* php/php-src@a9e6667 (originally committed as hard compile time error)
* php/php-src@deb44d4 (reverted back to deprecation error)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants