Module import is considered unused if it used only for an extension method used in a CE
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".

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
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.
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.