compiler-errors - 将内联与显式成员约束结合时出现奇怪的错误

标签 compiler-errors f# type-parameter

(更新:我添加了一个重现示例)

代码如下所示:

type Lib =
    static member inline tryMe (a: ^a) = 
        let name = (^a: (static member name: string) ())
        name

type Test =
    struct 
        val Value: string
        new v = {Value = v}
    end
    static member inline name with get() = "HiThere"
    static member works(a:Test) = Lib.tryMe a

这将“正常工作”并编译。但是,如果您稍微扩展一下,例如如下所示:
/// Does a bounds check and raises an error if bounds check is not met
let inline checkBounds f (g: 'b -> ^c) (tp: ^a) = 
    let convertFrom = (^a: (static member name: string) ())
    let convertTo = (^c: (static member name : string) ())
    let value =  (^a: (member Value: 'b) tp)
    if f value then
        g value
    else 
        failwithf "Cannot convert from %s to %s." convertFrom convertTo


type ConverterA =
    struct 
        val Value: sbyte
        new v = { Value = v }
    end

    static member inline name with get() = "converter-a"
    static member inline convert (x: ConverterA) : ConverterB = 
        checkBounds ((>=) 0y) (byte >> ConverterB) x

and ConverterB =
    struct 
        val Value: byte
        new v = { Value = v }
    end
    static member inline name with get() = "converter-b"

它会引发一大堆虚假的 FSharp 编译器错误。

error FS1114: The value 'Foo.Bar.name' was marked inline but was not bound in the optimization environment

error FS1113:The value 'name' was marked inline but its implementation makes use of an internal or private function which is not sufficiently accessible

warning FS1116: A value marked as 'inline' has an unexpected value

error FS1118: Failed to inline the value 'name' marked 'inline', perhaps because a recursive value was marked 'inline'



我还没有看到其他内联函数发生这种情况。我不确定这里会发生什么。如果我稍微改变一下,例如删除 convertTo行及其依赖项,它编译得很好。

在 FSI 中运行代码时也不会出现错误,即使 FSI 设置为 --optimize .

我可以通过删除 inline 来解决它.对于这种类型的字段,无论如何都无关紧要,即使 F# 没有内联,JIT 也会内联它们。

这是编译器错误吗?或者我的代码中是否有错误,或者我没有意识到对显式成员约束的一些限制?

最佳答案

您需要重新排序,以便您使用的函数在您使用它们的地方是已知的,否则 F# 编译器似乎不知道要内联什么。正如您在此答案下方的评论中所说,如果您问我,这是一个错误。

/// Does a bounds check and raises an error if bounds check is not met
let inline checkBounds f (g: 'b -> ^c) (tp: ^a) = 
    let convertFrom = (^a: (static member name: string) ())
    let convertTo = (^c: (static member name : string) ())
    let value =  (^a: (member Value: 'b) tp)
    if f value then
        g value
    else 
        failwithf "Cannot convert from %s to %s." convertFrom convertTo

type ConverterB =
    struct 
        val Value: byte
        new v = { Value = v }
    end
    static member inline name with get() = "converter-b"

and ConverterA =
    struct 
        val Value: sbyte
        new v = { Value = v }
    end

    static member inline name with get() = "converter-a"
    static member inline convert (x: ConverterA) : ConverterB = 
        checkBounds ((>=) 0y) (byte >> ConverterB) x

关于compiler-errors - 将内联与显式成员约束结合时出现奇怪的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39440568/

相关文章:

java - 在Java中,匿名类可以声明自己的类型参数吗?

java - 我可以创建一个作为泛型类型参数的成员变量吗?

c++ - 错误CC2061 : syntax error: identifier 'GLUquadric'

f# - 调用 F# 异步工作流程时,我可以避免定义临时标签吗?

f# - 为什么在 F# 中将数组类型写成一个列表?

F# 无限阿姆斯特朗数流

c# - 调用类型参数的方法

visual-c++ - Ogre3d错误: cannot open file OgreMain_d.lib

c++ - 最简单的template-template为什么编译不出来?

c++ - C: 错误使用: "Compound Assignment"和 "Prefix Decrement"在一起