Skip to content
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

[server] Type name X redefined from module X #8368

Closed
Antriel opened this issue Jun 4, 2019 · 24 comments · Fixed by #8571
Closed

[server] Type name X redefined from module X #8368

Antriel opened this issue Jun 4, 2019 · 24 comments · Fixed by #8571
Assignees
Labels
strong-belgian-ale Issue is legit - solution probably requires achieving Ballmer Peak
Milestone

Comments

@Antriel
Copy link
Contributor

Antriel commented Jun 4, 2019

There's been a lot of talk about this type of error. I'm not sure if it's one issue or multiple, but I managed to make a minimal example for my current one. Interestingly it's very similar to #8043 (comment) from my previous issue.
hxml

-lib hxnodejs #this isn't really used, but without it, it works
-cp src
-main Main
-js build.js

Main.hx

class Main {
    public static function main():Void {
        MyMacro.foo();
    }
}

MyMacro.hx

class MyMacro {
    #if macro
    static var issue = haxe.macro.ComplexTypeTools.toType(macro :js.lib.Uint8Array);
    // ^ this causes the issue
    #end
    public static macro function foo() return macro { };
}

Compiling this normally works. First compile via haxe --connect 6000 build.hxml works, second one will result in C:\HaxeToolkit\std/js/lib/Uint8Array.hx:28: characters 36-51 : Type name js.lib.Uint8Array is redefined from module js.lib.Uint8Array.

It's the combination of the ComplexTypeTools.toType and the hxnodejs library (tested with haxelib latest, 6.9.1).
Haxe version 877addc.

Possibly related to #6993, #4234, #5725. Maybe also related to #7279, I'm not sure as that seems to complain more about the error reporting than the error being false.

@RealyUniqueName RealyUniqueName self-assigned this Jun 4, 2019
@RealyUniqueName RealyUniqueName added this to the Release 4.0 milestone Jun 4, 2019
@kLabz
Copy link
Contributor

kLabz commented Jun 4, 2019

-lib hxnodejs #this isn't really used, but without it, it works

You can replace it with --macro define('nodejs')

@Antriel
Copy link
Contributor Author

Antriel commented Jun 4, 2019

--macro define('nodejs')

Indeed that works (i.e. causes the issue) too.

@kLabz
Copy link
Contributor

kLabz commented Jun 4, 2019

A variant of the exact same issue:

build.hxml

# Just need any --macro call
--macro define('whatever')
-main Main
-D no-compilation

Main.hx

class Main {
	public static function main():Void {
		MyMacro.foo();
	}
}

MyMacro.hx

class MyMacro {
	#if macro
	static var issue = haxe.macro.ComplexTypeTools.toType(macro :Type1);
	// ^ this causes the issue
	#end

	public static macro function foo() return macro { };
}

Type1.hx

class Type1 {
	public function new() {
		trace(Type2);
	}
}

Type2.hx

class Type2 {
	public function new() {
		trace(Type1);
	}
}

@Antriel
Copy link
Contributor Author

Antriel commented Jun 5, 2019

#8371 seems to have fixed this issue in my project.

@RealyUniqueName
Copy link
Member

Some logs from my investigation (based on this sample):

Issue is reproducible if ComplexTypeTools.toType(macro:Type1) is used as an init expr for a static var (1).
If that expr is invoked in a body of a macro function, then everything works fine (2).

In (1) the module "Type1" is loaded with macro and eval defined and then loaded again as a dependency of "Type2" without eval and macro defined, which leads to two different cache signatures for module "Type1". That makes "Type1" to be loaded twice.

While in (2) the module "Type1" is always loaded without macro and eval defined.

So, I assume that for init expressions of static fields in macros the context is not properly set up.

Also, In the sample "Type1" is always loaded with ctx.m.curmod being null_module.
But if I move ComplexTypeTools.toType(macro:Type1) from static field init expr to the body of a macro function, then "Type1" is loaded with ctx.m.curmod being Main, and everything works fine.
That could happen because function execution is delayed more than execution of static init expressions.

@lublak
Copy link
Contributor

lublak commented Jun 25, 2019

The same problem apears if i use Context.defineType.
With: https://gist.github.com/nadako/2ad4246f257e627a5833
I also use "@:persistent" at this var.
But it shows not everytime. I don't know. How to reproduce it.
With defineModule the "error" shows more often.
For me i use Context.getType(path) == null to check if the type is defined before. (But i think it is not the best solution)

@kLabz
Copy link
Contributor

kLabz commented Jun 25, 2019

Yeah in my project too it's the combo Context.defineType + Context.getType that triggers this.

@RealyUniqueName
Copy link
Member

#8571 fixes samples provided in this issue.
But a more generic fix could only be done after #7871
I suggest to close this issue regardless the destiny of #8571 and focus on #7871

@RealyUniqueName
Copy link
Member

RealyUniqueName commented Aug 27, 2019

I'm reverting the fix, because it makes us to add more and more hacks. We will look for a better solution.

RealyUniqueName added a commit that referenced this issue Aug 27, 2019
@Simn Simn added the strong-belgian-ale Issue is legit - solution probably requires achieving Ballmer Peak label Aug 27, 2019
@Simn
Copy link
Member

Simn commented Aug 27, 2019

Here's my preliminary conclusion on what goes wrong in general:

Compilation 1

signature A

  • An init macro causes a type to be loaded in typing context, let's call that type Ref[A].
  • An init macro calls Compiler.define, which causes a signature change (hxnodejs does this).

signature B

  • Typing continues, a type Type[B] is loaded and references Ref[A], which causes Ref[A] to become one of its dependencies.
  • Typing finishes, both Type[B] and Ref[A] are stored in the cache.

Compilation 2

signature A

  • For whatever reason, Ref is not loaded into the typing context immediately, so there is no ref[A] there.
  • The signature changes again, from an init macro or through -D.

signature B

  • Now Ref is loaded and becomes Ref[B].
  • Type[B] is retrieved from the cache.
  • Its dependencies are also retrieved from the cache. But Type[B] has Ref[A] as its dependency.
  • Ref[B] vs. Ref[A]: "Type name Ref is redefined from module Ref"

@stnguyen
Copy link

stnguyen commented Nov 7, 2019

Is this fixed in Haxe 4.0.0?

@RealyUniqueName
Copy link
Member

No

@Gama11

This comment has been minimized.

@RealyUniqueName
Copy link
Member

I still don't know how to fix this properly.
I don't think we can do anything here. Instead we should focus on #7871 and then this issue will become irrelevant.

@RealyUniqueName RealyUniqueName modified the milestones: Release 4.1, Bugs Mar 20, 2020
@joelmo
Copy link

joelmo commented Apr 29, 2021

It seems to be possible to trigger this bug or one thats related. The error message is abit different:
[Error - 16:03:31] Request textDocument/hover failed. Message: Type name haxe.display.JsonTodo is redefined from module haxe.display.JsonModuleTypes Code: -32603

Steps to reproduce:

  1. Create a autoBuild for a interface
  2. Define new class by reification and also implement the interface (the one that calls the macro):
var klass = Context.getLocalClass().get();
// Guard against redefining
if (Context.defined("display") || !klass.isInterface || klass.name == "Client")
	return null;
var client = macro class Client {
        public function new() {}
};
switch client.kind {
	case TDClass(superClass, interfaces, isInterface, isFinal, isAbstract):
		interfaces.push({pack: klass.pack, name: klass.name});
	default:
}
client.pack = ["nocollisionspls"];
Context.defineType(client);
  1. Try to use autocomplete in vscode. Compiling this works just fine. But if you type x in another line (loads completion suggestions), then remove x and recompile this error appears: JsonTodo is redefined. Another issue is that its fields doesnt show up in the suggestions.
var x = new nocollisionpls.Client();
x.

Offtopic: it would be nice to also have "interpolation" for interfaces in class reification like this macro class Client implements $klassInterface {}.

@kLabz
Copy link
Contributor

kLabz commented Apr 29, 2021

// Guard against redefining

But you're not guarding against redefining, in case of compilation server (which is used for completion but can be used for compilation too) this code can run several times.

@joelmo
Copy link

joelmo commented Apr 29, 2021

Since I'm not in control of the compliation server. Is that a valid scenario you would need to guard against and is it possible in a feasible way? I added a static boolean outside the build function in a attempt to make the build macro only run once, this doesnt work. In this example there should only be one interface that extend the @:autoBuild one.

@back2dos
Copy link
Member

If you want static bools to persist between compilations, you will need to annotate them with @:persistent (although this is not 100% guaranteed to work). As for guarding against redeclaration, you check against the existence of a type with var exists = try { haxe.macro.Context.getType(name); true; } cache (e:Dynamic) false;. That said, if JsonTodo is the offending type here, there's probably something else going wrong.

@joelmo
Copy link

joelmo commented Apr 29, 2021

After adding @:persistent boolean run once check. And a try/catch guard. And one additional "@:persistent types already built array check". Problem still occurs.

@shealyrd
Copy link

In my case, this was being caused by the use of -macro include() in the .hxml. Removing those calls fixed the issue.

This error was being quietly spit by the completion server and wasn't showing up in compilation. While the completion server was outputting this error, it shut down all completion in the IDE, effectively making the entire project unworkable.

I know that the vscode extension has its own repo to post in, but while I'm here: I think some priority should be given to stabilizing the IDE, as in my experience it randomly stops functioning for weird, untraceable reasons, which causes big timesinks. Errors in the project will cause the intellisense to stop working, but that's when you would need intellisense the most.

@Simn
Copy link
Member

Simn commented Apr 18, 2023

@shealyrd What Haxe version is that in your case?

@shealyrd
Copy link

@shealyrd What Haxe version is that in your case?

4.2.5, I'll try updating to 4.3 and see if it helps

@kLabz
Copy link
Contributor

kLabz commented Apr 18, 2023

Yeah this exact issue should be solved with 4.3.0. There are other ways to have the issue, though.

@Simn
Copy link
Member

Simn commented Feb 6, 2024

I think the original issue has been addressed, but the history here is a mess so I can't really tell. I'll close regardless because I don't want everyone who runs into this particular error to come here.

@Simn Simn closed this as completed Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
strong-belgian-ale Issue is legit - solution probably requires achieving Ballmer Peak
Projects
None yet
10 participants