-
Notifications
You must be signed in to change notification settings - Fork 786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
F# exceptions should be formatted properly in stack traces #3327
Comments
A "workaround" is to override `ToString": exception Foo of string with override this.Message = this.Data0 :) |
To be honest the |
I should add that code generation for |
On a positive note, code generation for exceptions should be quite isolated in the codebase and safe to adjust (just thinking aloud). |
The link for this issue is here: #878. A related issue is whether serialization of exceptions is supported or configurable in .NET Core https://github.com/dotnet/coreclr/issues/2715.
I'd be interested for someone to advocate the more radical solution: simply deprecating F#-style exception declarations. I'm not necessarily pushing for that, but I've often considered whether we should just be asking people to write the class declaration. How much is the feature buying us if we have to codegen our way out of trouble all the time? |
Automatic code gen is nice - if it works properly ;-) I think biggest user is compiler itself. From what I can see sometimes only to pattern match on it ;-) |
Unless there is intention of radically overhauling their design, I'd favor deprecation. That said, writing class-based exceptions in F# is very painful boilerplate and hard to get right. A properly written exception must consume two different constructors of its base class (the regular one and the ISerializable one) which means that it cannot be defined using default constructor syntax. There's certainly something missing in this space. Also. FWIW F# exceptions cannot be generic |
BTW I think "unusable" is too strong - and it's best to avoid hyperbole in technical discussions. F#-defined exceptions are used in compiler and elsewhere and have long been usable for that purpose. But I agree they are far from perfect. |
I guess that really depends on the personal opinion on where your point of no return is.
Tbh. the compiler is probably not a good example on how to do exceptions. The compiler-API is especially painful to use when some internal stuff fails. The compiler will not tell you what's wrong (only "internal-error") and will hide internal error details pretty hard from you. In my FAKE netcore update this really did cost countless hours of debugging and custom FCS builds providing more debugging information. But that is a different discussion. Imho we can deprecate |
I agree with this.
The normal technique is to turn on first-chance exception debugging in the debugger (e.g. Visual Studio) to show the exception at the point of it being raised. At least that works well for me. By it's nature a compiler tends to have catch-all exception handlers at its entry point But yes, it can be painful, I agree
Yes, debugging FAKE is particularly brutal. I think the problem there was much more that the FCS API for scripting was not initially well-designed for reporting exceptions - more than the "exception" definitions in F#
We would only deprecate if class-based exception declarations were deemed a suitable replacement (which they aren't, as Eirik has pointed out). And we would only do it as a permanent solution. We can follow up on fsharp/fslang-suggestions#591, which I basically agree with. |
We should just keep in mind that there are environments where this is just not possible. At that early point in time this was not possible in netcore and it even is not by now for F# (but I could help myself with a C# app I guess). And there always will be platforms and early adopters where this is not an option at all.
They are hard to get right either way so I don't understand the point there. One could argue that using So, to get back to this issue: I think it would be a small step into the correct direction to change the message to default to the same string as a union-case would generate? Or allow to mark fields as the message or make it by convention?
@vasily-kirichenko What would be the expected behavior or the "bugfix" you suggest? |
Do you know what the technical issue is there? Do you mean with VS 2017? Always populating "Message" with the sprintf %A sounds totally reasonable |
👍 it can always be overridden if something different is required |
This is now marked "feature request", but really also is a bug ;), see below. I'm very glad this discussion is being held. I don't think the DU-style exceptions should be taken out or deprecated, I use them a lot and I'd argue that I won't be the only one. Some of the comments made here (like @matthid _"would automatically set the Message property?") suggest that it is possible to create a I raised a bug 9 months ago about that, it is currently broken and raises pretty weird errors by the compiler, or none when it should (it totally confuses the system, but that was VS2015, not sure about 2017), see #1602. To summarize:
Current workaroundsWhat I needed for my project was:
I eventually did this for each exception, which makes it exportable and still usable in pattern matching try/with:
My preferenceAny solution that can seamlessly cast to and fro
Of course, there is much more that can be done, but this would solve the issue raised here and adds a lot of usability to the exception types. |
Being new to F#, poor printing of F# exceptions was one of my biggest disappointments. None of the literature mentioned how awkward it would be when debugging F# exceptions. I expected them to simply work. |
A possible fix for the original problem reported here is in #12736. It adds a Message override if none has been provided, using %A to format all the data in the exception object. This seems reasonable. We will likely gate it by language version since it could be a breaking change (people doing silly things like searching inside the text of an exception message) |
Fixed up above |
Neat! So this fixes the shadowing of the
|
Oh wait, you already mentioned that above, cool!
|
F# exceptions are awkward and printed by just listing all data. See: dotnet/fsharp#3327
"message one" is not shown in the stack trace, which is awful.
Compare to an ordinary exception:
It makes F#-style exceptions basically unusable.
The text was updated successfully, but these errors were encountered: