php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #77091 Using debug_backtrace() to distinguish continuations called on the same line
Submitted: 2018-10-31 22:30 UTC Modified: 2018-10-31 23:29 UTC
From: asmqb7 at gmail dot com Assigned:
Status: Open Package: Scripting Engine problem
PHP Version: 7.2.11 OS: All
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: asmqb7 at gmail dot com
New email:
PHP Version: OS:

 

 [2018-10-31 22:30 UTC] asmqb7 at gmail dot com
Description:
------------
Hi,

While working to add some robustness to a debug helper library I stumbled on a "fun" little edge-case scenario that may arise due to the increasing popularity of continuation-passing style programming.

I unfortunately suspect it will be a bit tricky to fix in the shorter term, so I'm adding this bug to document the existence of the following in the hope that it can be factored into future design decisions.

--

Consider a scenario where the same continuation function is called multiple times. For example, a setter function:

$blah->setValue()->setValue()->setValue();

I agree that patterns using the same function name can be a tad awkward, but entirely plausible to find being used in real-world scenarios (I unfortunately have no citable examples I can list).

Now, in theory, each of those setValue() calls might be doing something appropriately contained to the scope of $blah, but nonetheless sufficiently nontrivial that I might want to inspect the state of $blah at each setValue() call site.

Here's the problem: it's not possible for me to determine which setValue() call I'm in. I have to rely on examination of function arguments or other context in order to figure things out.

--

The included test script demonstrates this.

- It generates a backtrace, stores it, and if it's the same as the last backtrace, it prints "same".

- The script prints one backtrace then prints "same" twice because the other two collected backtraces are completely identical.

I strongly argue that some mechanism other than line numbers is needed to identify which function is being executed. (Particularly considering that the line numbers PHP reports are inaccurate.)

It may sound like overkill, but something similar to token_get_all() that folds currently-executing-function annotation metadata into the returned token stream would be pretty awesome and would completely solve this and probably many other issues.

Test script:
---------------
<?php

class x {
   function z() {
      $bt = debug_backtrace();
      global $oldbt;
      if ($bt == $oldbt) {
         print "same\n";
      } else {
         print_r($bt);
      }
      $oldbt = $bt;
      return $this;
   }
}

$z = new x();

$z->z()->z()->z();


Expected result:
----------------
I'm not going to impose any specific interpretation; any solution that allows me to determine exactly which function I'm in regardless of line number will be highly appreciated.

Actual result:
--------------
Array
(
    [0] => Array
        (
            [file] => test.php
            [line] => 19
            [function] => z
            [class] => x
            [object] => x Object
                (
                )

            [type] => ->
            [args] => Array
                (
                )

        )

)
same
same


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-10-31 23:29 UTC] requinix@php.net
-Type: Bug +Type: Feature/Change Request -Package: PHP Language Specification +Package: Scripting Engine problem
 [2018-11-01 20:33 UTC] a at b dot c dot de
I suppose in the meantime a workaround could be  writing

<?php
$z->z()
  ->z()
  ->z();
?>

(P.S. What is written here is just method chaining (maybe "fluent"); I know it's just for illustration but it's not in continuation-passing style).
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sun Dec 15 20:01:28 2019 UTC