Skip to content

Introduce <<Deprecated>> attribute #11

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

Open
wants to merge 19 commits into
base: attributes_v2_rfc
Choose a base branch
from

Conversation

beberlei
Copy link
Owner

@beberlei beberlei commented May 2, 2020

This is a prototype for an attribute <<Deprecated>> that would modify the AST at compile time to include a call to trigger_error("Function %s is deprecated, %s", E_USER_DEPRECATED). You can rely on the default message or provide extra information:

<<Deprecated>>
function test() {}
// Deprecated: Function test() is deprecated in %s

<<Deprecated("use test3() instead")>>
function test2() {}
// Deprecated: Function test2() is deprecated, use test3() instead in %s

Why is this needed over just adding trigger_error yourself as a developer? It would also provide IDEs and static analysis tools the same information as the runtime.

It uses the line of the function/method declaration for the line number information. Other line numbers are not messed with by injecting the new code.

Todos:

  • Improve error message to reference methods correctly with "Method %s::%s is deprecated".
  • Evaluate if class handlers can be overwritten in an efficient way, so that property and const deprecations can be emitted at runtime on read/write.
  • Evaluate if <<Deprecated>> on a parameter could be used to trigger_error when parameter is used (or different than default).

@beberlei beberlei changed the title Introduce <<Deprecated>> attribute compiled into a method/function. Introduce <<Deprecated>> attribute May 2, 2020
@kocsismate
Copy link

Please see php#5446 for the error message improvement 😊

INIT_CLASS_ENTRY(ce, "Deprecated", NULL);
zend_ce_deprecated_attribute = zend_register_internal_class(&ce);
zend_ce_php_compiler_attribute->ce_flags |= ZEND_ACC_FINAL;

Choose a reason for hiding this comment

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

Would it be worth to disable serialization/deserialization as well?

Copy link
Owner Author

Choose a reason for hiding this comment

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

No, it would not be a problem to serialize/unserilize this class, in fact if people want to cache it for whatever reason, it makes sense to allow it.


INIT_CLASS_ENTRY(ce, "Deprecated", NULL);
zend_ce_deprecated_attribute = zend_register_internal_class(&ce);
zend_ce_php_compiler_attribute->ce_flags |= ZEND_ACC_FINAL;

Choose a reason for hiding this comment

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

Suggested change
zend_ce_php_compiler_attribute->ce_flags |= ZEND_ACC_FINAL;
zend_ce_deprecated_attribute->ce_flags |= ZEND_ACC_FINAL;

@TysonAndre
Copy link

I think there'd be some impact to opcache for the properties and class constant deprecations

  • Previously, I don't think there was a way to deprecate properties and class constants for internal classes, just functions and methods and the way they're used (I may be mistaken)
  • Opcache currently optimizes $x = new KnownClassWithoutMagic(); $x->prop = 123; return $x->prop into return 123; (e.g. if this is done from a static method of KnownClassWithoutMagic). If deprecation was implemented for properties, that would need to be checked for. (Not sure what part of the code does this, but it's doable - typed properties already turn off this optimization)
  • I'm not sure how assignments, fetches, etc will be impacted. (FETCH_OBJ_R, ASSIGN_OBJ, static equivalents, etc)
  • Will constant('SomeClass::DEPRECATED_CONST') now throw if set_error_handler converts the notice to an exception? (Reference counting may be affected if the value couldn't be figured out at compile time).

@beberlei beberlei force-pushed the attributes_v2_rfc branch 3 times, most recently from 3bf85a2 to 4cc905c Compare May 24, 2020 20:33
@beberlei beberlei force-pushed the attributes_v2_rfc branch from 20aceb5 to 8697ccf Compare June 4, 2020 09:57
beberlei pushed a commit that referenced this pull request Jun 19, 2021
The following opcodes would be generated:

  ...
  BB1:
  0003 JMP BB3

  BB2:
  0004 INIT_FCALL 1 96 string("chr")
  0005 #10.T3 [long] = SR #3.CV0($int) [long] #7.CV2($i) ...
  0006 #11.T4 [long] RANGE[0..127] = BW_AND #10.T3 [long] ...
  0007 #12.T3 [long] RANGE[128..255] = BW_OR #11.T4 [long] ...
  0008 SEND_VAL #12.T3 [long] RANGE[128..255] 1
  0009 #13.V3 [ref, rc1, rcn, any] = DO_ICALL
  0010 ASSIGN_OP (CONCAT) #6.CV1($out) [rc1, rcn, string]
  0011 ADD #7.CV2($i)... int(7) #7.CV2($i) ... -> #15.CV2($i) ...

  BB3:
  0012 #8.T4 [long] = SR #3.CV0($int) #7.CV2($i) [long, double]
  0013 #9.T3 [bool] RANGE[0..1] = IS_SMALLER int(128) #8.T4
  0014 JMPNZ #9.T3 [bool] RANGE[0..1] BB2
  ...

Main changes are:
1. SR opcode covers new path in function zend_jit_long_math_helper().
2. BW_AND and BW_OR opcodes are supported. See macro LONG_OP.
3. Function zend_jit_concat_helper() is added to support ASSIGN_OP
opcode. Speficically, CONCAT and FAST_CONCAT is supported for statements
"$out .= ...".
4. New path is covered in function zend_jit_cmp_long_long() by
IS_SMALLER opcode.
5. New path is covered in macros ZVAL_PTR_DTOR and ZVAL_DTOR_FUNC when
leaving.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants