Type mismatch on active pattern with ReadOnlySpan<char> parameters and (expected) implicit argument conversion

54 Views Asked by At

I am confused as to why this bit of F# code fails to compile:

open System

[<RequireQualifiedAccess>]
module Al =

    [<return: Struct>]
    let inline (|EquivalentName|_|) (name1: string) (name2: string) : unit voption = 
        ValueNone // irrelevant

    [<return: Struct>]
    let inline (|EquivalentNameSpans|_|) (name1: ReadOnlySpan<char>) (name2: ReadOnlySpan<char>) : unit voption = 
        ValueNone // irrelevant

    let inline EquivalentNameSpans' (name1: ReadOnlySpan<char>, name2: ReadOnlySpan<char>) : unit voption = 
        ValueNone // irrelevant
        
let test() =
    // Ok
    match "foo" with
    | Al.EquivalentName "foo" -> ()
    | _ -> ()
    
    // Ok
    match "foo".AsSpan() with
    | Al.EquivalentNameSpans "foo" -> () // Warning 3391 on second "foo" literal
    | _ -> ()
    
    // Ok
    match "foo" : ReadOnlySpan<char> with
    | Al.EquivalentNameSpans "foo" -> () // Warning 3391 on both "foo" literals
    | _ -> ()
    
    // Ok
    match Al.EquivalentNameSpans'("foo", "foo") with
    | ValueNone -> ()
    | ValueSome _ -> ()
    
    //error FS0001: Type mismatch. Expecting a
    //    'string -> 'a voption'    
    //but given a
    //    'ReadOnlySpan<char> -> unit voption'    
    //The type 'string' does not match the type 'ReadOnlySpan<char>'
    //error FS0001: Type mismatch. Expecting a
    //    'string -> 'a voption'    
    //but given a
    //    'ReadOnlySpan<char> -> unit voption'    
    //The type 'string' does not match the type 'ReadOnlySpan<char>'
    match "foo" with
    | Al.EquivalentNameSpans "foo" -> () // error on this line
    | _ -> ()

Generally, the F# compiler seems perfectly able to implicitly convert string to ReadOnlySpan<char>, albeit with a warning, but here, in the context of an active pattern, it fails to convert - what gives?

Open in sharplab.

0

There are 0 best solutions below