HaxeFoundation / HaxeFoundation/haxe

[macro] Error when (re)defining types after failed build

Open
#11,456 8 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.