当类型从传递依赖性泄漏时,发布构建失败,Debug很好

Hon*_*tan 7 f#

我试图解释有关传递依赖性的Release和Debug配置之间奇怪的F#编译器行为.我将Newtonsoft.Json在这里使用package作为基本依赖,因为这是我设法找到问题的最远,并且它使示例有点不那么抽象.

让我们创建一个名为的文库项目SerializerProject,Newtonsoft.Json通过paket 引用.在这个项目中只有一个模块:

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<'a> (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<'a>(jr)
Run Code Online (Sandbox Code Playgroud)

现在让我们SerializerProject通过项目参考在同一个解决方案和参考中创建第二个项目.我想fromJson在我的新项目中使用,这就是我SerializerProject首先引用的原因.

module MyModule =
  open Serializer

  (* This is here just so we reference the fromJson function *)
  let deserializer bytes = fromJson bytes
Run Code Online (Sandbox Code Playgroud)

这是重现行为的最小示例.

现在,当我在Debug配置中构建解决方案时,一切都编译并正常工作.但是当我切换到Release时,编译在第二个项目中失败,在deserializer定义中的MyModule中.确切的错误消息是这样的:

通过'Newtonsoft.Json.JsonWriter'引用的类型在未引用的程序集中定义.您必须添加对程序集'Newtonsoft.Json'的引用

我正在使用Visual Studio 2015 Update 3,F#工具(fsc,fsi)显示版本14.0.23413.0.

这有点意义,因为它正在读取元数据,SerializerProject并发现公共OptionConverter类型泄漏了JsonWriter它的公共WriteJson方法的类型(以及其他类型和其他方法,但首先遇到这个),但是让我想知道的是为什么这个在调试模式下工作,这只是发布模式中的一个问题.

  • 编译器做了哪些额外的操作会影响这个?
  • 当实际定义的类型Newtonsoft.Json传递到第二个项目时,为什么这不是Debug构建中的问题?

正如评论中所建议的那样,我尝试Newtonsoft.Json使用ILSpy 引用和反编译第二个程序集,以查看编译器优化启用的内联是否应该归咎于此,但即使在Release配置中,第二个程序集如下所示:

call !!0 [SerializerProject]Serializer::fromJson<!a>(uint8[])
Run Code Online (Sandbox Code Playgroud)

fromJson函数尚未内联JsonWriter直接公开类型,因此似乎有更微妙的事情发生.

这不是阻塞问题,我只是将转换器类型设为私有,因为我不想从外部使用它们,但我想深入挖掘F#编译器内部工作.