Skip to content

Conversation

@Numpsy
Copy link
Contributor

@Numpsy Numpsy commented Jul 21, 2024

…rings

refs #498

I tried stubbing out the DVar/Logging bits that are described in #498 and then running the I am (should fail) example test from the Expecto project template in an AOT build, and it crashed with

[E] 2024-07-21T22:25:59.0322420+00:00: samples.I am (should fail) errored in 00:00:00 [Expecto]
 - errors: [System.NotSupportedException: 'Microsoft.FSharp.Core.PrintfImpl+Specializations`3[Microsoft.FSharp.Core.Unit,System.String,System.String].CaptureFinal2[System.Char,System.String](Microsoft.FSharp.Core.PrintfImpl+Step[])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility
   at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2f
   at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.MakeGenericMethod(Type[]) + 0x189
   at Microsoft.FSharp.Core.PrintfImpl.FormatParser`4.buildCaptureFunc[a](PrintfImpl.FormatSpecifier, a, Type[], Type, Tuple`5) + 0x21b
   at Microsoft.FSharp.Core.PrintfImpl.FormatParser`4.parseAndCreateFuncFactoryAux(FSharpList`1, String, Type, Int32&) + 0x22c
   at Microsoft.FSharp.Core.PrintfImpl.FormatParser`4.parseAndCreateFuncFactoryAux(FSharpList`1, String, Type, Int32&) + 0x1ea
   at Microsoft.FSharp.Core.PrintfImpl.FormatParser`4.parseAndCreateFunctionFactory() + 0x78
   at Microsoft.FSharp.Core.PrintfImpl.FormatParser`4.GetCurriedPrinterFactory() + 0x1f
   at Microsoft.FSharp.Core.PrintfImpl.FormatParser`4.GetCurriedStringPrinter() + 0x20
   at Expecto.Expect.printVerses[a,b](String, a, String, b) + 0x197
   at Expecto.Expect.defaultDiffPrinter@404.Invoke(Object, Object) + 0x26
   at Expecto.Expect.equalWithDiffPrinter$cont@383[a](FSharpFunc`2, a, a, String, Object, Object, Unit) + 0x405
   at Expecto.Expect.equalWithDiffPrinter[a](FSharpFunc`2, a, a, String) + 0x71
   at Tests.f@1() + 0x32
   at Tests.tests@12-3.Invoke(ResumableStateMachine`1& sm) + 0xd
   at <StartupCode$FSharp-Core>.$Tasks.resumptionInfo@171.MoveNext(ResumableStateMachine`1&) + 0x37
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x20
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xb2
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task, ConfigureAwaitOptions) + 0x4b
   at Microsoft.FSharp.Control.TaskBuilderExtensions.HighPriority.cont@405-8.Invoke(ResumableStateMachine`1& sm) + 0x30
   at <StartupCode$FSharp-Core>.$Tasks.resumptionInfo@171.MoveNext(ResumableStateMachine`1&) + 0x37]

and replacing these two sprintfs with interpolated strings allows it to run, and print out a failure message.
This is basically the simplest possible test case, but it at least shows that it can execute tests and process the results in AOT builds.

@Numpsy
Copy link
Contributor Author

Numpsy commented Jul 22, 2024

I wasn't sure whether to change the sprintf "%A"'s as well, but lets just keep the change to things where I've actually seen an exception happen for simplicity.

@Numpsy Numpsy marked this pull request as ready for review July 22, 2024 17:14
@farlee2121
Copy link
Collaborator

Were you planning to replace more sprintf calls?

@Numpsy
Copy link
Contributor Author

Numpsy commented Aug 18, 2024

I haven't had time to look at it more since I opened this :-(

There are a number of other warnings from AOT builds in this area, e.g.

expecto\Expecto\Expect.fs(383,0): Warning IL2072: Expecto.Expect.equalWithDiffPrinter$cont@383<a>(FSharpFunc`2<Object,FSharpFunc`2<Object,String>>,a,a,String,Object,Object,Unit): 'typ' argument does not satisfy 'DynamicallyAccessedMemberTypes.All' in call to 'Microsoft.FSharp.Reflection.FSharpType.IsRecord(Type,FSharpOption`1<BindingFlags>)'. The return value of method 'System.Object.GetType()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

So there would be more work there to fix that as well.

@farlee2121
Copy link
Collaborator

No worries. Just wanted to make sure I wasn't neglecting your work

@Numpsy
Copy link
Contributor Author

Numpsy commented Dec 16, 2025

I'd forgotten about this one.
What's the general opinion on using interpolation rather than sprintf in general these days where possible?

Current versions of the compiler can compile interpolations that only involve strings into calls to string.Concat and avoid formatting altogether so they can also be more efficient, though maybe that's less important in tests.

@farlee2121
Copy link
Collaborator

I generally use interpolation instead of sprintf. I find interpolation easier to read.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants