dotnet / dotnet/fsharp

Improve error message when need to annotate all record fields

Open
#5,613 6 comments 0 reactions 0 assignees View on GitHub
Area-Diagnostics Feature Improvement
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 22h
Merged PRs (30d)
144

Description

I just got a report in https://github.com/fsharp/FAKE/issues/2080
And I felt like there might be a issue for newcomers here, so I'd like to report this as bug here as I'd like to see the error message improved if possible.

Consider code like:

```fsharp
namespace Test1

type MyRecord =
{ Label1 : string
Label2 : string }

namespace Test2

module Program =
[]
let main argv =
ignore (fun _ ->
{
Test1.Label1 = ""
Label2 = ""
}
()
)
0
```

I guess most people expect this code to compile with a warning, but instead it doesn't compile and complain about `Label2`:

![image](https://user-images.githubusercontent.com/1866463/45262741-2c97d780-b41d-11e8-9eda-11665f936ce1.png)

I guess this is especially confusing if the label-name is a wide-spread identifier.

I'd assume there is enough information for the compiler to figure out what `Label2` means. In fact I think the confusion did occur because FAKE documentation only shows the following usage (which works):

```fsharp
namespace Test1

type MyRecord =
{ Label1 : string
Label2 : string }

module M =
let f (i:MyRecord) = ()

namespace Test2

module Program =
[]
let main argv =
ignore (fun _ ->
Test1.M.f
{ Label1 = ""
Label2 = "" }
()
)
0
```

So this is a pitfall for newcomers.

#### Spec

Relevant seem to be:
- 6.3.5 Record Expressions
- 14.1 Name Resolution

Which specifies that that the compiler should emit an error.

#### Expected behavior

As the error is according to spec. I'd suggest to improve the error message. My suggestion would be (in this particular scenario where one label is fully referenced):

`the record label 'Label2' is not defined. Either reference all labels with a long identifier 'Test1.MyRecord.Label2' or add a type annotation '({ ... } : Test1.MyRecord)'.`

If someone things this should compile, please feel free to open a language suggestion in a addition to this issue.

#### Actual behavior

See above.

#### Known workarounds

In order to not annotate all fields:

```fsharp
namespace Test1

type MyRecord =
{ Label1 : string
Label2 : string }

namespace Test2

module Program =
[]
let main argv =
ignore (fun _ ->
({ Label1 = ""
Label2 = "" } : Test1.MyRecord)
()
)
0
```

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.