HaxeFoundation / HaxeFoundation/haxe
[macro] Error when (re)defining types after failed build
- Dominant language
- Haxe
- Stars
- 6.9k
- Forks
- 715
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 11
Description
I have created a large project using [Echoes](https://github.com/player-03/echoes), and often after a failed build, I get an error about a missing function body, pointing to [this line](https://github.com/player-03/echoes/blob/465e36f2b6ffb907bc58a89298d2653c3d197872/src/echoes/macro/ComponentStorageBuilder.hx#L44):
```haxe
var def:TypeDefinition = macro class $storageTypeName extends echoes.ComponentStorage<$componentComplexType> {
public static final instance:$storageType = new $storageTypePath();
//ComponentStorageBuilder.hx:44: lines 44-46 : Missing function body
private function new() {
super($v{ componentTypeName });
}
};
storageCache.set(storageTypeName, def);
if(!registered) {
registered = true;
Context.onTypeNotFound(storageCache.get);
}
```
Additional clues:
- I haven't been able to reproduce this in a small project. (So no minimal sample, sorry.)
- In my large project, I can only reproduce it if I'm running enough other programs in the background. If I close my browser and media player and restart the Haxe server, I can no longer get it to happen. (Possibly related to threads and timing?)
- If I remove the `Context.onTypeNotFound()` call and instead use `Context.defineType(def)`, the error messages tell me which type(s) are being redefined, but I'm not sure it's useful information because it causes errors in situations where `onTypeNotFound()` would lead to a successful build. I believe this is why I switched to `onTypeNotFound()` in the first place.
- Using `Context.onGenerate()` to exclude duplicates doesn't help; the error seems to happen before then.
- If I use a `Printer` to print `def.fields[1]`, I always find that the function body is there, regardless of whether the build ends up succeeding or failing. So I believe the function body is being provided to the compiler, but gets deleted/lost later.
- I've tested in Haxe 4.3.1 and 4.3.3, mainly targeting HL.
I've thought of a few features that could help work around this, or at least debug it. I can compile from source to help test these, but I don't know enough to implement them.
- A `Context.isTypeDefined()` function, so I can check if a type was preserved from the last build before calling `defineType()`. (`getType()` isn't suitable because of all the side effects.)
- A `@:noCache` metadata that prevents the compile server from trying to cache the type.
- An `overwrite` argument in `Context.defineType()` and/or `Context.defineModule()`.
- A way to check the status of the previous build, and manually clear the compile cache if it failed. (Though shouldn't this happen already? It might be a timing issue where the main thread cleared the cache after an error, but then another thread added one final incomplete class.)
Contributor guide
Research direction
Start with src/echoes/macro/ComponentStorageBuilder.hx around line 44 and trace the Context.onTypeNotFound() and Context.defineType() paths in the Haxe compiler, especially compile-server behavior for failed builds. Reproduce with the large Echoes project under Haxe 4.3.1 or 4.3.3 targeting HL, then establish why a generated constructor body is lost and verify that repeated builds no longer report a missing body.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100