Improve error reporting: suggest inlining when compiler constrains types to be less generic
- Dominant language
- F#
- Stars
- 4.3k
- Forks
- 876
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 131
Description
Error messages on functions with generic type constraints can be quite misleading, especially when the solution is to mark a function as inline. Three different (but related) cases of poor messages are shown below:
### Example 1
``` fsharp
let averageBy (f : 'T -> ^U) (source : seq<'T>) : ^U =
let inline acc (sum, count) el = (Checked.(+) sum (f el), count + 1)
let (sum, count) = Seq.fold acc ((LanguagePrimitives.GenericZero< (^U) >), 0) source
LanguagePrimitives.DivideByInt sum count
```
#### Expected behavior
Compiler warning: `Checked.(+)` is inferred to have default type of `int` rather than `^U` because `averageBy` is not marked as inline.
#### Actual behavior
Compiler error on `Checked.(+)`:
```
Type constraint mismatch when applying the default type 'int' for a type inference variable. The type 'int' does not support the operator 'DivideByInt' Consider adding further type constraints.
```
### Example 2
``` fsharp
let averageBy (f : 'T -> ^U) (source : seq<'T>) : ^U =
let acc (sum, count) el = (Checked.(+) sum (f el), count + 1)
let (sum, count) = Seq.fold acc ((LanguagePrimitives.GenericZero< (^U) >), 0) source
LanguagePrimitives.DivideByInt sum count
```
#### Expected behavior
Compiler warning: `Checked.(+)` is inferred to have default type of `int` rather than `^U` because `averageBy` and/or `acc`are not marked as inline
#### Actual behavior
Compiler infers type `^U` as `obj` without warnings or errors.
### Example 3
``` fsharp
let averageBy (f : 'T -> ^U) (source : seq<'T>) : ^U =
let inline acc (sum, count) el = (Checked.(+) sum (f el), count + 1)
let (sum, count) = Seq.fold acc ((LanguagePrimitives.GenericZero< (^U) >), 0) source
Unchecked.defaultof<_> // TODO: finish implementation
```
#### Expected behavior
Compiler warning: `Checked.(+)` is inferred to have default type of `int` rather than `^U` because `averageBy` and is not marked as inline
#### Actual behavior
Compiler warning on `Checked.(+)`:
```
This construct causes code to be less generic than indicated by the type annotations. The type variable 'U has been constrained to be type 'int'.
```
Contributor guide
Assessment
This issue has not been assessed yet.