fsharp icon indicating copy to clipboard operation
fsharp copied to clipboard

Module import is considered unused if it used only for an extension method used in a CE

Open Thecentury opened this issue 4 years ago • 2 comments

Repro steps Consider the following code:

open System.Threading.Tasks

module Builder =

    type AsyncBuilder with
        // allows to bind to the result of Tasks
        member _.Bind (task : Task<'a>, cont : 'a -> Async<'b>) =
            async.Bind (Async.AwaitTask task, cont)

open Builder

let task = Task.FromResult 1
let x = async {
    let! i = task
    return i + 1
}

Here the Builder module contains an extension method for an AsyncBuilder that enables the former to bind to the results of usual .Net tasks.

Expected behavior

No compiler warnings or errors.

Actual behavior

F# compiler considers this import to be not required: Warning "IDE0005: Open declaration can be removed".

image

But it is required as without it the compiler generates an error:

  X.fs(16, 14): [FS0001] This expression was expected to have type
    'Async<'a>'    
but here has type
    'Task<int>'

Related information

  • Operating system — Windows 10
  • .NET Framework 4.7.2
  • Visual Studio 16.10.0

Thecentury avatar Jun 03 '21 15:06 Thecentury

The type checker records resolved symbols for future use in features like identifier highlighting and Find Usages. IIRC the results of resolving of builders members are not recorded in any way.

The analyzer goes over the resolved symbols and tries to find and mark an open that a symbol could come from, and since symbols used in let! are not recorded, they don't mark the corresponding opens as used.

Ideally, opens should be marked during the type check (it could also fix some corner cases related to shadowing of imported symbols), but that's not how it's currently done and would probably require a big refactoring of the symbols import/resolve logic.

A somewhat hacky fix could be recording the builder members like let! usages with some special occurrence kind, so they could be used in open analysis while not being highlighted as methods, thanks to a special occurrence kind check. This would add a small overhead, since we'll keep more resolved symbols, but it'll likely be really small compared to all the rest symbols in files we already keep.

auduchinok avatar Jun 04 '21 08:06 auduchinok

A related issue is the build methods are also considered unused, even though that's not really the case. The builder method stuff could get fixed pretty easily, I had a hacky approach for dealing with that here: https://github.com/dotnet/fsharp/pull/9736 it can probably be re-opened.

I like @auduchinok's idea for the builder open.

cartermp avatar Jun 04 '21 15:06 cartermp