`Compilation.Clone` can produce an illegal compilation


Please see this discussion for a full elaboration, but the gist of it is that Compilation.Clone misbehaves when the compilation involves a custom BCL. The key element illustrating this is this code:
    var compilation1 = project.GetCompilationAsync().Result;
    INamedTypeSymbol typeType1;
    INamedTypeSymbol typeString1;
    IMethodSymbol getField1;
    INamedTypeSymbol getFieldParameter1;
    GetSymbols(compilation1, out typeType1, out typeString1, out getField1, out getFieldParameter1);
GetSymbols simply binds from the copilation all those declared symbols. This line:
    Console.WriteLine("typeString1.Equals(getFieldParameter1): " + typeString1.Equals(getFieldParameter1));
Prints "true" as you'd expect. However, if you perform this operation again on a new compilation derived from compilation1.Clone(), the new compilation has the following issues that are not present in compilation1:
  • The new compilation (compilation2) contains errors in the diagnostics that indicate it has treated the custom BCL project as not in fact a custom BCL project -- it does not recognize that my System.Object is standing-in for the built-in type.
  • Specifically the following line:
    Console.WriteLine("getFieldParameter2.Equals(typeString1): " + typeString1.Equals(getFieldParameter2)); 
    Will show that a symbol from compilation2 contains references to symbols from compilation1, which seems to clearly violate the contract of Clone().
To reproduce this issue, please download the SSCCE I included in the discussion thread referenced at the top. To avoid any versioning issues, I've included the Roslyn binaries in my .zip file, which is why it is 70mb. I would be happy to include a version without those binaries if helpful.
Closed May 7, 2014 at 1:27 AM by Kevin_H


mattwar wrote Apr 7, 2014 at 2:44 AM

It sounds like the compilation is caching/reusing the symbols for the predefined types across clones, assuming they are originating from external metadata, and not the compilation itself.

kswoll wrote Apr 9, 2014 at 1:25 AM

As I just replied to in the discussion thread, I want to make sure it's clear that ReplaceSyntaxTree also demonstrates the problem. If you replace the compilation1.Clone() line with:
var compilation2 = compilation1.ReplaceSyntaxTree(compilation1.SyntaxTrees.First(), compilation1.SyntaxTrees.First());
This will also reproduce the same problem.

VSadov wrote Apr 10, 2014 at 7:52 PM

Fixed in changeset 9f2c1635eeab3c7b62e543757cabb288c4011697