-
Notifications
You must be signed in to change notification settings - Fork 156
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
Pass _root
and _parent
to all local and no external types
#283
Conversation
I correctly understand, that the 3rd commit disables passing Using your example from the first commit: # main.ksy
meta:
id: main
imports:
- imported
seq:
- id: foo
type: imported::nested_type
# imported.ksy
meta:
id: imported
types:
nested_type: {} I think, that these changes should be expected for Java target because of your fix (you mentioned that Java does not pass // Imported.java
public class Imported extends KaitaiStruct {
public static class NestedType extends KaitaiStruct {
- public NestedType(KaitaiStream _io, Main _parent, Imported _root) { /* ... */ }
+ public NestedType(KaitaiStream _io, KaitaiStruct _parent, Imported _root) { /* ... */ }
}
}
// Main.java
public class Main extends KaitaiStruct {
void _read() {
- this.foo = new Imported.NestedType(this.io);
+ this.foo = new Imported.NestedType(this.io, this, null);
}
} |
Yes.
Well, not in general. The change in 10b0588 means that cross-spec type usages don't influence the
meta:
id: main
imports:
- imported
seq:
- id: foo
type: imported::nested_type(false)
meta:
id: imported
seq:
- id: len_body
type: u1
- id: wrapper
type: nested_type(true)
types:
nested_type:
params:
- id: use_parent
type: bool
seq:
- id: body
size: _parent.len_body
if: use_parent (The As you can see, $ javac -classpath /c/temp/kaitai_struct/runtime/java/target/kaitai-struct-runtime-0.11-SNAPSHOT.jar Main.java Imported.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
Main.java:28: error: incompatible types: Main cannot be converted to Imported
this.foo = new Imported.NestedType(this._io, this, false);
^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error ... since the possible constructor signatures of class public static class NestedType extends KaitaiStruct {
public NestedType(KaitaiStream _io, boolean useParent) {
this(_io, null, null, useParent);
}
public NestedType(KaitaiStream _io, Imported _parent, boolean useParent) {
this(_io, _parent, null, useParent);
}
public NestedType(KaitaiStream _io, Imported _parent, Imported _root, boolean useParent) {
// ... In conclusion, I'm convinced we need 10b0588 because letting different .ksy specs affect the derived So, as @GreyCat pointed out in kaitai-io/kaitai_struct#71 (comment), if someone feels like they need to pass Keeping both kaitai-io/kaitai_struct#71 (comment) (@ams-tschoening)
kaitai-io/kaitai_struct#71 (comment) (@KOLANICH)
kaitai-io/kaitai_struct#275 (comment) (@ams-tschoening)
kaitai-io/kaitai_struct#275 (comment) (@GreyCat)
So I believe the consensus is clear. In the long run, I'm not completely opposed to kaitai-io/kaitai_struct#770, i.e. getting rid of |
Thanks for that so detailed explanation. Yes, falling asleep, I realized that when |
7d383af
to
cbb2527
Compare
shared/src/main/scala/io/kaitai/struct/precompile/ParentTypes.scala
Outdated
Show resolved
Hide resolved
Looks great, thanks for making this reality, @generalmimon! |
Related: * kaitai-io/kaitai_struct#703 * kaitai-io/kaitai_struct#963 Until now, using a nested type of an imported spec could affect the derived parent type of that nested type. For example: `main.ksy` ```ksy meta: id: main imports: - imported seq: - id: foo type: imported::nested_type ``` `imported.ksy` ```ksy meta: id: imported types: nested_type: {} ``` If you compile `main.ksy` for Java (`kaitai-struct-compiler -t java main.ksy`), `Imported.java` looks like this: ```java public class Imported extends KaitaiStruct { // ... public static class NestedType extends KaitaiStruct { public NestedType(KaitaiStream _io, Main _parent, Imported _root) { /* ... */ } // ^^^^^^^^^^^^ } // ... } ``` Notice the `Main _parent` parameter - the compiler saw that `imported::nested_type` is only used from the `main` type, so it decided that the `_parent` type of `nested_type` will be `main`. However, this means that the `_parent` crosses KSY spec boundaries and the generated `Imported.java` code will be different depending on whether you compile it as imported from `main.ksy` or standalone. Furthermore, you could even access fields of `main` in `imported::nested_type` via `_parent`, but that would mean that `imported.ksy` would only work when imported and compiled via `main.ksy`. From <kaitai-io/kaitai_struct#71 (comment)>, I suppose none of this should be possible: > It would be a huge mess if `_root` relied on this particular ksy being > imported from some other ksy, and only work in that case. I agree that `_root` and `_parent` arguably shouldn't cross spec boundaries at all, they should only be passed locally within one .ksy spec, and therefore also parent types should only be derived from local type usages. This commit only adjusts the parent type derivation, not invocations of imported nested types with `_parent` and `_root` still being passed (see also kaitai-io/kaitai_struct#963) - they will be fixed later.
* Fixes kaitai-io/kaitai_struct#1089 Previously, `_root` and `_parent` weren't passed to the local top-level type, which is fixed by this commit. This was demonstrated by tests NavRootRecursive and NavParentRecursive added in kaitai-io/kaitai_struct_tests@5941262e * Fixes kaitai-io/kaitai_struct#963 `_root` and `_parent` were incorrectly passed to nested types of imported specs (i.e. external types). This was demonstrated by asserts in the [KST spec of test NestedTypesImport](https://github.com/kaitai-io/kaitai_struct_tests/blob/d07deb4c/spec/ks/nested_types_import.kst#L17-L32).
8a35f13
to
e502eca
Compare
`_parent` and `_root` are `null` when you invoke an external type (i.e. a type that is not defined inside the .ksy spec from which you call it). This was implemented in <kaitai-io/kaitai_struct_compiler#283>. However, the return type `Struct` doesn't allow `null`, only its nullable variant `?Struct` does. Without this change, the NestedTypesImport test fails with: ``` $ ./docker-ci -t php -i 8.3 ... 2) Kaitai\Struct\Tests\NestedTypesImportTest::testNestedTypesImport TypeError: Kaitai\Struct\Struct::_parent(): Return value must be of type Kaitai\Struct\Struct, null returned /runtime/php/lib/Kaitai/Struct/Struct.php:31 /tests/spec/php/NestedTypesImportTest.php:15 ``` Since the nullable return types were added in PHP 7.1 (see https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.nullable-types), this increases the minimum supported PHP version from 7.0 to 7.1, but I don't think this is a big deal since PHP 7.0 is EOL for a long time (since 2019-01-10, see https://endoflife.date/php). If we wanted to keep supporting PHP 7.0, I think we would have to remove the return type hint, but I don't see a reason to do that (at this point, the oldest PHP version "supported for critical security issues only" is PHP 8.1, so we could probably even drop support for anything older than that).
Fixes
_root
/_parent
chain broken by recursive use of the top-level type kaitai_struct#1089Previously,
_root
and_parent
weren't passed to the local top-level type, which is fixed by this PR.This was demonstrated by tests NavRootRecursive and NavParentRecursive added in kaitai-io/kaitai_struct_tests@5941262e
Fixes "incompatible types" error on constructor
_root
parameter when importing type from other KSY file kaitai_struct#963_root
and_parent
were incorrectly passed to nested types of imported specs (i.e. external types).This was demonstrated by asserts in the KST spec of test NestedTypesImport.