dotnet / runtimelab

This repo is for experimentation and exploring new ideas that may or may not make it into the main dotnet/runtime repo.
MIT License
1.36k stars 188 forks source link

Compiler failure on missing references #1363

Open kant2002 opened 2 years ago

kant2002 commented 2 years ago

Take this branch to save you a bit of time setting up https://github.com/kant2002/flips/commit/9017e74418f87f6068b47e89c69ecbcf698d8fec

dotnet tool restore
dotnet paket restore
cd Flips.Examples
dotnet publish -c Release -r linux-x64

I assume linux-x64 does not matter

EXEC : error : Failed to load assembly 'gurobi90.netstandard20' [/home/kant/d/github/flips/Flips.Examples/Flips.Examples.fsproj]
  Internal.TypeSystem.TypeSystemException+FileNotFoundException: Failed to load assembly 'gurobi90.netstandard20'
     at Internal.TypeSystem.ThrowHelper.ThrowFileNotFoundException(ExceptionStringID id, String fileName) in ILCompiler.TypeSystem.dll:token 0x6000427+0x7
     at Internal.TypeSystem.ResolutionFailure.Throw() in ILCompiler.TypeSystem.dll:token 0x6000419+0x92
     at Internal.TypeSystem.Ecma.EcmaModule.GetObject(EntityHandle handle, NotFoundBehavior notFoundBehavior) in ILCompiler.TypeSystem.dll:token 0x60007c5+0x35
     at Internal.TypeSystem.Ecma.EcmaModule.GetType(EntityHandle handle) in ILCompiler.TypeSystem.dll:token 0x60007c2+0x0
     at Internal.TypeSystem.Ecma.EcmaType.InitializeBaseType() in ILCompiler.TypeSystem.dll:token 0x60007e0+0x51
     at Internal.TypeSystem.TypeDesc.get_IsDelegate() in ILCompiler.TypeSystem.dll:token 0x6000342+0x0
     at ILCompiler.DependencyAnalysis.TypeMetadataNode.GetStaticDependencies(NodeFactory factory) in ILCompiler.Compiler.dll:token 0x600078d+0x0
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependenciesImpl(DependencyNodeCore`1 node) in ILCompiler.DependencyAnalysisFramework.dll:token 0x6000038+0x0
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependencies(DependencyNodeCore`1 node) in ILCompiler.DependencyAnalysisFramework.dll:token 0x6000039+0x8
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ProcessMarkStack() in ILCompiler.DependencyAnalysisFramework.dll:token 0x600003a+0x2c
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ComputeMarkedNodes() in ILCompiler.DependencyAnalysisFramework.dll:token 0x600003b+0x19
     at ILCompiler.ILScanner.ILCompiler.IILScanner.Scan() in ILCompiler.Compiler.dll:token 0x60002ec+0x0
     at ILCompiler.Program.Run(String[] args) in ilc.dll:token 0x600010f+0xb3e
     at ILCompiler.Program.Main(String[] args) in ilc.dll:token 0x6000115+0x5

Note, I cannot find any reference to gurobi90.netstandard20, but instead of that file gurobi91.netstandard20.dll in the bin/Release/net5.0/linux-x64/

MichalStrehovsky commented 2 years ago

The compiler tries to be tolerant to garbage input but not all codepaths do upfront validation to make sure we can abort compiling a problematic method before it puts the compiler into a state where we cannot back out.

Looks like here is a type that has a base type in an assembly that doesn't exist. We would be able to recover from that in some spots, but looks like this found a codepath that can't recover.

To troubleshoot, one could run the dependency viewer tool to see what triggered the need of this particular TypeMetadataNode. It may or may not be possible to back out there.

We can fix this if it's in a good spot, but there are some spots where the upfront validation would be so expensive (in terms of compilation throughput) that it's not worth it (e.g. I would not regress the compilation throughput by 5% just to fix compiling a particular app with broken references).

kant2002 commented 2 years ago

This particular library uses following pattern.

using extern alias gurobi90;
namespace Gurobi90;

public class GurobiSolver
{
     readonly gurobi90::GRBEnv _gurobiEnvironment; // In case readonly make difference
     IObservable<gurobi90::GRBExpr> _ev;  // In case generics make a difference
     GRBModel gurobi90::_grbModel;
}

gurobi90 is pointer to gurobi90.netstandard20, similarly exists gurobi91 and others.

And then create a lot of similar constructs to different assemblies. Even if I do not like that pattern to provide backward compatibility, it is used with relatively consistency.

Technically I may want just better reporting, because it's not easy to find such spots in 3rd party libraries.

Depending your opinion of practicality of pursuing such cases I may create small repro if needed.