Following #17519, we should see if it is possible for the F# compiler to emit a call to the System.Diagnostics.Debug.Assert overload that takes a message defaulting to CallerArgumentExpression for all usages of the assert keyword.
I.e., an expression like this
would be translated to
System.Diagnostics.Debug.Assert (not true, "not true")
Likewise:
→
System.Diagnostics.Debug.Assert ((x = 3), "(x = 3)")
etc.
The C# compiler now does this for System.Diagnostics.Debug.Assert(booleanExpr) by means of the OverloadResolutionPriorityAttribute, which F# does not currently support: #16967 (comment)
dotnet/csharplang#7906: developers can add weight to which methods are better in overload resolution. This seems unlikely to impact F# as much.
Want to point out one place this will intersect with F#. Consider that very likely Debug will end up looking like the following:
public static class Debug
{
[OverloadResolutionPriority(-1)]
public static void Assert(bool condition) { ... }
public static void Assert(bool condition, [CallerArgumentExpression] string? message = "") { ... }
}
Nothing will break for F# here when this happens, code will still compile as it used to. The experience for C# though will improve from a lot of Debug.Assert failed messages to the actual expression that passed into the assert. This is one part I thought might be interesting to F# .
See the BCL source:
[Conditional("DEBUG")]
[OverloadResolutionPriority(-1)] // lower priority than (bool, string) overload so that the compiler prefers using CallerArgumentExpression
public static void Assert([DoesNotReturnIf(false)] bool condition) =>
Assert(condition, string.Empty, string.Empty);
[Conditional("DEBUG")]
public static void Assert([DoesNotReturnIf(false)] bool condition, [CallerArgumentExpression(nameof(condition))] string? message = null) =>
Assert(condition, message, string.Empty);
SharpLab F#
SharpLab C#
We could in theory do this in the F# compiler specifically for the assert keyword, without needing to support OverloadResolutionPriorityAttribute in general, by emitting a call to the new overload when it is available here:
|
// Check an 'assert x' expression. |
|
and TcAssertExpr cenv overallTy env (m: range) tpenv x = |
|
let synm = m.MakeSynthetic() // Mark as synthetic so the language service won't pick it up. |
|
let callDiagnosticsExpr = SynExpr.App (ExprAtomicFlag.Atomic, false, mkSynLidGet synm ["System";"Diagnostics";"Debug"] "Assert", |
|
// wrap an extra parentheses so 'assert(x=1) isn't considered a named argument to a method call |
|
SynExpr.Paren (x, range0, None, synm), synm) |
|
|
|
TcExpr cenv overallTy env tpenv callDiagnosticsExpr |
Following #17519, we should see if it is possible for the F# compiler to emit a call to the
System.Diagnostics.Debug.Assertoverload that takes a message defaulting toCallerArgumentExpressionfor all usages of theassertkeyword.I.e., an expression like this
would be translated to
Likewise:
→
etc.
The C# compiler now does this for
System.Diagnostics.Debug.Assert(booleanExpr)by means of theOverloadResolutionPriorityAttribute, which F# does not currently support: #16967 (comment)See the BCL source:
SharpLab F#
SharpLab C#
We could in theory do this in the F# compiler specifically for the
assertkeyword, without needing to supportOverloadResolutionPriorityAttributein general, by emitting a call to the new overload when it is available here:fsharp/src/Compiler/Checking/Expressions/CheckExpressions.fs
Lines 7699 to 7706 in 69be2cd