(Cập nhật: Tôi đã thêm một ví dụ repro)lỗi Tò mò khi kết hợp nội tuyến với các ràng buộc thành viên rõ ràng
Với mã tìm kiếm như sau:
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
này sẽ "chỉ làm việc" và biên dịch . Tuy nhiên, nếu bạn mở rộng nó một chút, ví dụ như sau:
/// 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"
Nó sẽ tăng toàn bộ các lỗi trình biên dịch FSharp giả mạo.
lỗi FS1114: Giá trị 'Foo.Bar.name' được đánh dấu inline nhưng đã không bị ràng buộc trong môi trường tối ưu hóa
FS1113lỗi: Giá trị 'tên' được đánh dấu inline nhưng làm cho việc thực hiện sử dụng một chức năng nội bộ hoặc tư nhân mà không phải là đủ truy cập FS1116
cảnh báo: một giá trị đánh dấu là 'inline' có giá trị bất ngờ FS1118
lỗi: không thể inline t ông đánh giá 'name' được đánh dấu 'nội tuyến', có lẽ vì giá trị đệ quy đã được đánh dấu 'nội dòng'
Tôi chưa thấy điều này xảy ra với các hàm nội tuyến khác. Tôi không chắc điều gì xảy ra ở đây. Nếu tôi thay đổi một chút, ví dụ, loại bỏ đường dây convertTo
và các phụ thuộc của nó, nó sẽ biên dịch tốt.
Các lỗi cũng không xuất hiện khi chạy mã trong FSI, ngay cả khi FSI được thiết lập với --optimize
.
Tôi có thể giải quyết vấn đề này bằng cách xóa inline
. Đối với các trường thuộc loại này thì dù sao đi chăng nữa thì JIT cũng sẽ không đưa chúng vào, ngay cả khi F # không có.
Đây có phải là lỗi trình biên dịch không? Hoặc là có một lỗi trong mã của tôi, hoặc một số hạn chế về ràng buộc thành viên rõ ràng tôi đã không được nhận thức?
Thực sự với câu hỏi khác, điều này giải quyết nó như một giải pháp, nhưng không loại bỏ thực tế rằng nó (có thể) một lỗi trong F # như thứ tự được cho là không có liên quan ở đây: [báo cáo lỗi của tôi từ hôm qua] (https://github.com/Microsoft/visualfsharp/issues/1565). – Abel
Điều đó đúng, cảm ơn bạn đã báo cáo. Giống như tôi đã nói trong bình luận khác tôi nghĩ rằng trình biên dịch không biết những gì để inline tại điểm mà ông cố gắng để nội tuyến. – CodeMonkey