dotnet / dotnet/fsharp

"Unused open" is reported for a module when a provided type abbreviation constructor is used from it

Open
#11,058 0 comments 0 reactions 0 assignees View on GitHub
Area-FCS Bug Impact-Low
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

**Repro steps**

1. Create module A with abbreviated provided type
2. Create module B with opened module A
3. Сall the abbreviation constructor inside the module B

**Expected behavior**

Open is used, similar to non-provided abbreviations

**Actual behavior**

Opened module A with a provided type is reported as unused

Screenshots example:

![image](https://user-images.githubusercontent.com/26364714/107267974-98505580-6a58-11eb-9e57-6268c887dfb4.png)

And here really open is not redundant

![image](https://user-images.githubusercontent.com/26364714/107268007-a605db00-6a58-11eb-83eb-c2def21f33f6.png)

**Known workarounds**

Module revealed symbols are stored in a HashSet, and when the UnusedOpens analyzer tries to find called abbreviation constructor among them using ``ItemsAreEffectivelyEqual``/``ItemsAreEffectivelyEqualHash``, it maps the constructor to its ``ApparentEnclosingType``, which will compare against the module revealed symbols.
https://github.com/dotnet/fsharp/blob/main/src/fsharp/NameResolution.fs#L1683

Here is the root cause I think: ``ApparentEnclosingType`` from provided method/constructor returns its declaring type, when for non-provided -- true abbreviation, which symbol contains in the opened module. https://github.com/dotnet/fsharp/blob/main/src/fsharp/infos.fs#L930

One easy way to solve the problem is to add the abbreviated provided type symbol to the revealed symbols of the open module in https://github.com/dotnet/fsharp/blob/main/src/fsharp/service/ServiceAnalysis.fs#L23
```F#
if ent.IsFSharpAbbreviation then
let abbrType = ent.AbbreviatedType
if abbrType.HasTypeDefinition then
let typeDefinition = abbrType.TypeDefinition
if typeDefinition.IsProvided then
yield typeDefinition :> FSharpSymbol
```
However, this solution only applies to ``UnusedOpens`` analyzer and is probably hiding some problems.

Repro project:
[UnusedOpenRepro.zip](https://github.com/dotnet/fsharp/files/5946132/UnusedOpenRepro.zip)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.