title: Release build fails when types leak from transitive dependency, Debug is fine
body: <p>I'm trying to explain a weird F# compiler behavior between Release and Debug configurations regarding transitive dependencies. I will use <code>Newtonsoft.Json</code> package as the base dependency here, because that's the furthest I managed to get in pinpointing the issue, and it makes the example a bit less abstract.</p>
  
  <p>Let's create a library project called <code>SerializerProject</code>, referencing <code>Newtonsoft.Json</code> via paket. In this project there is only one module:</p>
  
  <pre><code>module Serializer =
    open System.IO
    open System.Text
    open Newtonsoft.Json
  
    type OptionConverter() =
      inherit JsonConverter()
  
      (* only the signature is important, the implementation
         and other methods are not interesting *)
      override x.WriteJson(writer: JsonWriter, value: obj, serializer: JsonSerializer) =
        (* ... *)
  
    let fromJson&lt;'a&gt; (bytes: byte []): 'a =
        let s = Encoding.UTF8.GetString(bytes)
        use sr = new StringReader(s)
        use jr = new JsonTextReader(sr)
        let serializer = JsonSerializer()
        serializer.Converters.Add(OptionConverter())
        serializer.Deserialize&lt;'a&gt;(jr)
  </code></pre>
  
  <p>Now let's create a second project in the same solution and reference <code>SerializerProject</code> via project reference. I'd like to use <code>fromJson</code> in my new project, that's why I referenced <code>SerializerProject</code> in the first place.</p>
  
  <pre><code>module MyModule =
    open Serializer
  
    (* This is here just so we reference the fromJson function *)
    let deserializer bytes = fromJson bytes
  </code></pre>
  
  <p>This is the minimal example to reproduce the behavior.</p>
  
  <p>Now when I build the solution in Debug configuration, everything compiles and works fine. But when I switch to Release, the compilation fails in the second project, in MyModule in the <code>deserializer</code> definition. The exact error message is this:</p>
  
  <blockquote>
    <p>The type referenced through 'Newtonsoft.Json.JsonWriter' is defined in an assembly that is not referenced. You must add a reference to assembly 'Newtonsoft.Json'</p>
  </blockquote>
  
  <p>I'm using Visual Studio 2015 Update 3, F# tools (fsc, fsi) show version 14.0.23413.0.</p>
  
  <p>It kind of makes sense, because it's reading metadata of the <code>SerializerProject</code> and finds that public <code>OptionConverter</code> type leaks the type <code>JsonWriter</code> on its public <code>WriteJson</code> method (as well as other types and other methods, but this one is encountered first), but what makes me wonder is why this works in Debug mode and is only a problem in the Release mode. </p>
  
  <ul>
  <li>What kind of extra operations does the compiler do that affect this?</li>
  <li>Why is this not a problem in Debug build when the type defined in <code>Newtonsoft.Json</code> really leaks transitively into the second project?</li>
  </ul>
  
  <p>As suggested in the comments I tried referencing <code>Newtonsoft.Json</code> and decompiling the second assembly with ILSpy to see whether inlining turned on by compiler optimizations is to blame here, but even in Release configuration the second assembly looks like this:</p>
  
  <pre><code>call !!0 [SerializerProject]Serializer::fromJson&lt;!a&gt;(uint8[])
  </code></pre>
  
  <p>The <code>fromJson</code> function has not been inlined to expose the <code>JsonWriter</code> type directly, so there seem to be something more subtle going on.</p>
  
  <p>This isn't a blocking issue, I just made the converter types private as I don't want to use them from the outside anyway, but I'd like to dig deeper in F# compiler inner workings.</p>