Skip to content

Commit

Permalink
PHP: use $this as default $_root only in top-level types
Browse files Browse the repository at this point in the history
See the same change in Python: e776c98

This commit by itself doesn't fix any observable issue because this
fallback behavior is also performed in the runtime library:
https://github.com/kaitai-io/kaitai_struct_php_runtime/blob/e21bc2a3/lib/Kaitai/Struct/Struct.php#L12

However, this poses a problem because using `$this` as a fallback for
`$_root` should be done **only** in the top-level type. This is why it
can actually only be done here in KSC and not in the runtime library,
because the runtime library has no way of knowing whether it's dealing
with a top-level type or not. Therefore, this commit adds the fallback
in KSC so that it can be removed from the runtime library.

The fact that the runtime library does it in every type is the reason
why the NestedTypesImport test currently fails (see
https://github.com/kaitai-io/ci_artifacts/blob/f82e17355f/test_out/php/ci.json#L719-L729).
The scenario is that `nested_types_import.ksy` contains `type:
nested_types3::subtype_b` (see
[`nested_types_import.ksy:15`](https://github.com/kaitai-io/kaitai_struct_tests/blob/ec0fafac31/formats/nested_types_import.ksy#L15)),
which is an external type from the perspective of `nested_types_import`,
so `_root` is not passed to it and remains `null`. The fact that
`$_root` is `null` is noticed by the runtime library, which replaces it
with `$this`. This is wrong, because the type of `$_root` in
`NestedTypes3\SubtypeB` is supposed to be `NestedTypes3`, not
`NestedTypes3\SubtypeB`. However, this turns into an actual error once
`NestedTypes3\SubtypeB::_read()` creates an instance of
`NestedTypes3\SubtypeA\SubtypeCc` on this line -
[`NestedTypes3.php:88`](https://github.com/kaitai-io/ci_targets/blob/24ec7d3efd/compiled/php/NestedTypes3.php#L88):

```php
            $this->_m_aCc = new \Kaitai\Struct\Tests\NestedTypes3\SubtypeA\SubtypeCc($this->_io, $this, $this->_root);
```

`$this->_root` is a `NestedTypes3\SubtypeB` object, but
`NestedTypes3\SubtypeA\SubtypeCc` requires that the `$_root` argument
type is `NestedTypes3`. Since this is not the case, a `TypeError` is
thrown.
  • Loading branch information
generalmimon committed Apr 4, 2024
1 parent 7fd4402 commit 9b8dda2
Showing 1 changed file with 13 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,26 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig)
val tParent = kaitaiType2NativeType(parentType)
val tRoot = translator.types2classAbs(rootClassName)

val pRootValue = if (name == rootClassName) {
// We could technically use the [null coalescing operator
// (`??`)](https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.null-coalesce-op)
// available since PHP 7 (that's OK, we don't support any lower version
// than that), which does approximately this, but also has an additional
// feature of suppressing the error if the left-hand side is an undefined
// variable, which we don't need here.
s"$pRoot === null ? $$this : $pRoot"
} else {
pRoot
}

out.puts(
s"public function __construct($paramsArg" +
s"$tIo $pIo, " +
s"$tParent $pParent = null, " +
s"$tRoot $pRoot = null" + endianAdd + ") {"
)
out.inc
out.puts(s"parent::__construct($pIo, $pParent, $pRoot);")
out.puts(s"parent::__construct($pIo, $pParent, $pRootValue);")

if (isHybrid)
handleAssignmentSimple(EndianIdentifier, "$is_le")
Expand Down

0 comments on commit 9b8dda2

Please sign in to comment.