Description
When a non-Exception
object is thrown (from CIL or other languages that support it), it cannot be caught in F# by default.
Repro steps
let throwobj (x:obj) = (# "throw" x #) // or any other code that throws a non-Exception instance
try
throwobj "test"
with
| e -> printf "%O" e
Expected behavior
The exception should be caught either as System.String
or System.Runtime.CompilerServices.RuntimeWrappedException
.
Actual behavior
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Exception'.
This is caused by the generated exception handler:
.try
{
ldstr "test"
throw
// ...
}
catch [netstandard]System.Object
{
castclass [System.Runtime]System.Exception // InvalidCastException
stloc.0
// ...
}
F# here catches everything, but the cast to Exception
throws another exception since the object is not an Exception
.
Known workarounds
The code above succeeds if the attribute that controls how wrapped exceptions are exposed is used explicitly:
[<assembly: System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = true)>]do()
Related information
Throwing a RuntimeWrappedException
manually does not exhibit this behaviour because the runtime does not treat it as a special case then and does not unwrap the value.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status