Description
I was refactoring some old code, replacing x.ToString()
with string x
for readability and, let's face it, best practices. But much to my surprise, this didn't work in a number of cases, though I always thought the two were interchangeable (with the exception of null
, which is treated as ""
for string null
and as NRE for null.ToString()
, hence the preference for string
vs .ToString()
).
It can lead to this:
But I don't think anything is "escaping its scope" here...
Repro steps
It is thrown by this code:
type Foo<'T> =
| Bar of 'T
override this.ToString() = // FS0670
match this with
| Bar x -> string x
Expected behavior
It should compile. The string
function is so basic to the language, it should be used whenever x.ToString()
can be used.
Actual behavior
Using string
can raise the following compile error:
FS0670 This code is not sufficiently generic. The type variable ^T could not be generalized because it would escape its scope.
Known workarounds
I found two workarounds:
- Don't use
string
and stick toToString()
, but that's a PITA - Write your own function (inline or not) that doesn't expose this problem:
/// Shadowing Core.string function. /// Uses obj.ReferenceEquals instead of isNull to prevent null-constraint let string x = if obj.ReferenceEquals(x, null) then "" else x.ToString()
Related information
Seen on any recent F# version. I did not (yet) test whether this is a regression.