sq / JSIL

CIL to Javascript Compiler
http://jsil.org/
Other
1.73k stars 242 forks source link

HashSet<T>.GetEnumerator exception #578

Open ephere opened 10 years ago

ephere commented 10 years ago

This just started happening after one of the recent commits, it worked before. I cannot reproduce it in a unit test, probably because of the bootstrap libraries. However, just place the following line anywhere in a production/non-test code to reproduce:

var hmm = new HashSet<string>().GetEnumerator();

Result:

The external method 'System.Collections.Generic.HashSet`1+Enumerator[System.String] GetEnumerator()' of type 'System.Collections.Generic.HashSet`1' has not been implemented.
ExternalMemberStub/getError@http://localhost:20287/Scripts/JSIL.Core.js:1260:9
ExternalMemberStub@http://localhost:20287/Scripts/JSIL.Core.js:1266:1
OverloadedMethod_InvokeDynamic@http://localhost:20287/Scripts/JSIL.Core.js:3790:11
System_Collections_Generic_HashSet$b1$lbSystem_String$rb_GetEnumerator@http://localhost:20287/Scripts/JSIL.Core.js line 3209 > Function:7:13
...
kg commented 10 years ago

Thanks, I'll look into it.

kg commented 10 years ago

This is a hairy one.

Normally, we can define types in both bootstrap and actual mscorlib, and they won't ever collide in a dangerous way. That's not true here, because of generics - we end up with two different definitions of GetEnumerator with different return types, and they're both external so there's no way to pick the 'correct' one. We also end up with two copies of types like HashSet floating around.

The solution is probably some sort of mechanism to only use the Bootstrap type definitions if no other definition is available. Sort of a 'partial type' system similar to C# partial classes...

ephere commented 10 years ago

Seems like a logical solution. Either that or automatically copying over the code generated from actual mscorlib to bootstrap, maybe if it was not copied yet, and keeping it up to date.

Can't the bootstrap definition be changed as a temporary patch meanwhile?

kg commented 10 years ago

Yes, but that will break most of the other test cases.

ephere commented 10 years ago

I see, yeah that is not good.

iskiselev commented 10 years ago

@kg, I've investigated this issue, and now I suppose, that generic types are not root cause of this issue. Real cause here, is that System.Collections.Generic.HashSet'1+Enumerator is private type, defined in System.Core assembly. As this type is private, it is not placed in JSIL.$PublicTypeAssemblies. Currently in libraries it is defined in JSIL.Core assembly. So, internally defined in JSIL.Core assembly and externaly defind in System.Core assembly types are different, so we really did not provide implementation for GetEnumerator method - as we use GetEnumerator that should return type from System.Core and have implementation for return type from JSIL.Core.