fsharp / fslang-suggestions

The place to make suggestions, discuss and vote on F# language and core library features
344 stars 21 forks source link

Autoboxing arguments involved in type tests and runtime casts on generic types #837

Closed NinoFloris closed 2 years ago

NinoFloris commented 4 years ago

I propose we allow type tests like x :? 'T or casts like x :?> 'T, which would then autobox. Today doing tests or casts like this requires manually boxing x before doing the test/cast, C# does this for you which saves some noise around an already noisy operation.

Today many of the errors that can be returned when you try to do so without boxing are fairly poor and do not help the user understand an explicit box might be what they need.

error FS0016: The type 'string' does not have any proper subtypes and cannot be used as the source of a type test or runtime coercion.

Or

error FS0008: This runtime coercion or type test from type 'T
to 'U
involves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed.

For inheritable types it does work but you get a compiler warning

A type parameter is missing a constraint 'T :> Foo

This should also naturally extend to tests and casts that involve a generic value and a type parameter, again as in C#.

let foo<'T, 'U> (x: 'T) = x :? 'U

C# expanded their spec in 7.1 for pattern matching to allow anything they already allowed in x as T https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.1/generics-pattern-match.md

Pros and Cons

The advantages of making this adjustment to F# are: Type tests and casts that are easier to use and have less sharp edges.

The disadvantages of making this adjustment to F# are: It may cause people to use them more?

Extra information

Estimated cost (XS, S, M, L, XL, XXL): S

Related suggestions: https://github.com/fsharp/fslang-suggestions/issues/828

Affidavit (please submit!)

Please tick this by placing a cross in the box:

Please tick all that apply:

Tarmil commented 4 years ago

So you want to be able to freely do x :?> 'T when the type of variable x is not a supertype of 'T? That sounds quite dodgy to me 😕 I agree that the error messages could be better, but I don't think that letting people do it willy-nilly is the correct fix.

NinoFloris commented 4 years ago

@Tarmil nothing but obj is a super type of a generic parameter, and that's not by virtue of that fact being obvious or 'more principled'. Hence why it's allowed in C# too, needing to box first has unnecessary friction while adding zero conceptual clarity.

Tarmil commented 4 years ago

nothing but obj is a super type of a generic parameter, and that's not by virtue of that fact being obvious or 'more principled'.

That's exactly what it is though... You don't know anything about a generic parameter except maybe the constraints you put on it. When a function takes unconstrained 'T, it means "I don't care what type you give me, I'll treat them all the same". I'd rather not make it easier to break this principle.

dsyme commented 2 years ago

I agree with @Tarmil's analysis here. I feel extending the range of things that can be used as input for the type tests leads to weaker code. I'd prefer to stick to the F# 1.0 decisions here.