2016-09-11 14 views
6

(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

FS1113

lỗ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?

Trả lời

1

Bạn cần phải sắp xếp lại để các chức năng bạn sử dụng được biết tại điểm mà bạn sử dụng chúng, nếu không có vẻ như trình biên dịch F # không biết nội tuyến. Như bạn đã nói trong các ý kiến ​​dưới đây câu trả lời này là một lỗi nếu bạn hỏi tôi.

/// 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 
+1

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

+0

Đ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

Các vấn đề liên quan