(更新:我添加了一个repro示例)
代码如下所示:
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编译器错误。
错误FS1114:标记了值'Foo.Bar.name' 内联但未在优化环境中绑定
错误FS1113:值'name'被标记为内联但是它 实现使用内部或私有函数,而不是 容易获得
警告FS1116:标记为“内联”的值具有意外值
错误FS1118:无法内联值'name' 标记为“内联”,可能是因为递归值标记为“内联”
我还没有看到其他内联函数发生这种情况。我不确定这里发生了什么。如果我稍微更改一下,例如删除convertTo
行及其依赖项,它就可以很好地编译。
在FSI中运行代码时,即使FSI设置为--optimize
,也不会出现错误。
我可以通过删除inline
来解决这个问题。对于这种领域而言,无论如何,JIT都会内联它们,即使F#没有。
这是编译器错误吗?或者我的代码中是否有错误,或者对我没有意识到的显式成员约束有一些限制?
答案 0 :(得分:1)
您需要重新排序,以便在您使用它们时知道您使用的函数,否则F#编译器似乎不知道要内联的内容。正如你在下面的评论中所说,这个答案如果你问我这是一个错误。
<setdynvars sourcetype="eval"
code='fun({Pid,DynVars})->
case string:tokens(atom_to_list(node()),"@") of
["tsung_controller_"++ID,_] -> list_to_integer(ID);
_ -> 0 end end.'>
<var name="controller_id" />
</setdynvars>