View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000838 | LDMud | LPC Compiler/Preprocessor | public | 2015-01-08 23:10 | 2020-08-23 22:19 |
Reporter | Gnomi | Assigned To | Gnomi | ||
Priority | normal | Severity | major | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Summary | 0000838: Struct reactivation fails when used in complex types | ||||
Description | When a program is recompiled (destroyed and loaded again) the compiler tries to match struct definitions. It does this by comparing the new definitions in the new program with old ones still present in the memory that have the same name (program name + struct name). If they're the same it replaces the new struct type with the old one in: other struct definitions, variable definition, function return types and function arguments. In the end if no struct definitions have changed they should be the same as before (remember that struct definitions are inherited, so they may be inheritors that have inherited the old ond some the new program, they should still be able to exchange structs). This approach has several drawbacks: 1. The replacement only looks at plain struct types, not at arrays of this struct or union types with this struct (or arrays of unions with the struct or unions with the array of struct, or array of array of structs and so on...) Therefore functions returning such complex types or structs containing complex types with a to-be-reactivated struct still refer to the new struct that shouldn't exist anymore. 2. Self referencing structs won't get reactivated. A struct like struct list { struct list next; }; will never be regarded as the same definition, because its member type is different (it references -of course - the new struct list, not the old one), therefore it's a change in the definition. 3. Deliberate changes of the definition of structs breaks LPC code. If I add a member to a struct, this struct logically can still be accessed by every object that expects the old struct definition (it has all the old members), but the LPC runtime regards them as entirely different types and thus throws RTTC errors. This might also be true when I remove a member (I might do a carefully planned transition where at the end I remove deprecated members), but it is not possible during runtime, because the types change. 1. is a regressions introduced by the union type system: Before that there were no complex types except arrays of structs and these were handled. Now replacing them within complex types is computationally expensive. 2. is also a regression, originally members that are structs themselves were compared by their definition. This can be fixed. But note that this in-depth comparision needs also be done for complex types (arrays and unions containing structs). 3. is a conceptual problem. To solve 3 (and thus solve 1 and 2), I propose that structs should be treated as equal (for type check purposes) when they have the same name and the same defining program. When Code accesses a struct that has another definition then the code was compiled with: Do a lookup by member name. If the member does not exist, then read-access shall return 0 and write access shall throw an error. | ||||
Steps To Reproduce | Testcase (another testcase is attached) ======================================= master.c -------- #include "/inc/base.inc" void run_test() { int errors; object ob; msg("\nRunning test for #0000xxx:\n" "--------------------------\n"); load_object("a1"); destruct(find_object("i")); ob = load_object("a2"); shutdown(catch(ob->test()) && 1); } string *epilog(int eflag) { run_test(); return 0; } a1.c ---- inherit "i"; a2.c ---- inherit "i"; i.c --- #pragma save_types, strong_types, rtt_checks struct abc {}; struct abc* fun() { return ({ (<abc>) }); } void test() { fun(); } | ||||
Tags | No tags attached. | ||||
Attached Files | |||||
External Data (URL) | |||||
|
With the proposed solution the struct reactivation becomes an optimization and not a necessary language feature. |
|
Fix committed in revision 44445fee9d845a46e3c2814bb3c0f86e7615b7ba to master branch (see changeset 988 for details). Thank you for reporting! |
|
Fix committed in revision c15f41739f5e7fbcbac7b10eddd1f3d5df3ffff5 to 3.5.0 branch (see changeset 1046 for details). Thank you for reporting! |
|
Fix committed in revision 44445fee9d845a46e3c2814bb3c0f86e7615b7ba to master branch (see changeset 1405 for details). Thank you for reporting! |
|
Fix committed in revision 44445fee9d845a46e3c2814bb3c0f86e7615b7ba to master branch (see changeset 2732 for details). Thank you for reporting! |
|
Fix committed in revision 44445fee9d845a46e3c2814bb3c0f86e7615b7ba to master branch (see changeset 3818 for details). Thank you for reporting! |
Date Modified | Username | Field | Change |
---|---|---|---|
2015-01-08 23:10 | Gnomi | New Issue | |
2015-01-08 23:10 | Gnomi | Status | new => assigned |
2015-01-08 23:10 | Gnomi | Assigned To | => Gnomi |
2015-01-08 23:10 | Gnomi | File Added: tests.tgz | |
2015-01-08 23:13 | Gnomi | Description Updated | |
2015-01-08 23:14 | Gnomi | Note Added: 0002243 | |
2015-02-12 11:59 | Source_changeset_attached | => ldmud.git master 44445fee | |
2015-02-12 11:59 | guest | Note Added: 0002249 | |
2015-02-12 11:59 | guest | Status | assigned => resolved |
2015-02-12 11:59 | guest | Resolution | open => fixed |
2016-01-20 16:31 | Source_changeset_attached | => ldmud.git 3.5.0 c15f4173 | |
2016-01-20 16:31 | guest | Note Added: 0002274 | |
2018-01-29 18:59 | Gnomi | Source_changeset_attached | => ldmud.git master 44445fee |
2018-01-29 18:59 | Gnomi | Note Added: 0002310 | |
2018-01-29 21:57 | Gnomi | Source_changeset_attached | => ldmud.git master 44445fee |
2018-01-29 21:57 | Gnomi | Note Added: 0002361 | |
2018-01-30 03:59 | Gnomi | Source_changeset_attached | => ldmud.git master 44445fee |
2018-01-30 03:59 | Gnomi | Note Added: 0002412 | |
2020-08-23 22:19 | Gnomi | Relationship added | related to 0000884 |