Skip to content

byref analysis not working with type abbreviations #7934

Closed

Description

@pihai

Consider the following example involving a ReadOnlySpan and a type abbreviation:

open System

type Bytes = ReadOnlySpan<byte>

type Foo() =
           
    //member this.foo1 (data: ReadOnlySpan<byte>) =
    //    let x = 
    //        if false then
    //            failwith "" // Error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL
            
    //        else
    //            data
    //    x

    //member this.foo2 (data: ReadOnlySpan<byte>) =
    //    let x = 
    //        if false then
    //            failwithf "" // Error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL
    //        else
    //            data
    //    x

    member this.foo3 (data: Bytes) =
        let x = 
            if false then // true or false doesn't matter
                failwith ""
            else
                data
        x

    member this.foo4 (data: Bytes) =
        let x = 
            if false then
                failwithf ""
            else
                data
        x

[<EntryPoint>]
let main argv =
    let span = ReadOnlySpan<_>(Array.empty)
    let result = Foo().foo3(span)
    let result = Foo().foo4(span)
    0

Repro steps

As described in #5776 the functions foo1 and foo2 give a compiler error. However, if I use a type abbreviation instead of the actual name of the byref-type ReadOnlySpan the compiler errors disappear and the program can be compiled. The funtion foo3 even works despite it shouldn't, at least I suppose. foo4 raises a TypeLoadException:

System.TypeLoadException: 'The generic type 'Microsoft.FSharp.Core.PrintfFormat`5' was used with an invalid instantiation in assembly 'FSharp.Core, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.'

Expected behavior

None of the above functions should compile. I'm not sure why foo3 works at runtime anyway.

Actual behavior

A type abbreviation kind of prevents the byref analysis which leads to bad surprises at runtime.

Known workarounds

Don't use type abbreviations.

Related information

Provide any related information (optional):

  • Windows 10
  • .NET Core 3.1
  • Visual Studio 16.4

Activity

  1. added this to the Backlog milestone on Dec 4, 2019
  2. cartermp commented on Dec 4, 2019

    @cartermp
    Contributor

    link #6133

    (related, but not the same issue)

  3. TIHan commented on Dec 10, 2019

    @TIHan
    Contributor

    Yes, this should fail at compile time. Thank you for making an issue. It should be an easy fix.

    I'm not sure why foo3 works at runtime anyway.

    This is because failwith is inline and doesn't use a byref-like type as a type argument in its internals.

  4. self-assigned this
    on Dec 10, 2019
  5. cartermp commented on Dec 17, 2019

    @cartermp
    Contributor

    Fixed by #7953

  6. modified the milestones: Backlog, 16.5 on Jan 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions