Inline plus operator in struct throws an exception (F #)

Why does fail throw an exception? fine works. If I remove inline or if I don't convert to float then it will work.

 [<Struct>] type Test<'t> = val x: 't val y: 't new (x,y) = { x = x; y = y } static member inline (+) ((x,y), a: _ Test) = 0 static member inline (-) ((x,y), a: _ Test) = 0 let a = 1.,2. let b = Test(1.,2.) let fine = a - b let fail = a + b 

error message:

Unhandled exception: System.TypeInitializationException: initializer of type fo r 'AdditionDynamicImplTable 3' threw an exception. ---> System.NotSupportedExcep tion: Dynamic invocation of op_Addition involving coercions is not supported. at Microsoft.FSharp.Core.LanguagePrimitives.dyn@2445 [a,b,c](Type aty, Type bt y, Unit unitVar0) at Microsoft.FSharp.Core.LanguagePrimitives.AdditionDynamicImplTable 3' threw an exception. ---> System.NotSupportedExcep tion: Dynamic invocation of op_Addition involving coercions is not supported. at Microsoft.FSharp.Core.LanguagePrimitives.dyn@2445 [a,b,c](Type aty, Type bt y, Unit unitVar0) at Microsoft.FSharp.Core.LanguagePrimitives.AdditionDynamicImplTable 3' threw an exception. ---> System.NotSupportedExcep tion: Dynamic invocation of op_Addition involving coercions is not supported. at Microsoft.FSharp.Core.LanguagePrimitives.dyn@2445 [a,b,c](Type aty, Type bt y, Unit unitVar0) at Microsoft.FSharp.Core.LanguagePrimitives.AdditionDynamicImplTable 3..cctor () --- End of internal check for exception stack --- at Microsoft.FSharp.Core.LanguagePrimitives.AdditionDynamic [T1, T2, TResult] (T1 x, T2 y) at. $ Program.main @ () in C: \ Users \ olsv \ Docume nts \ Visual Studio 2012 \ Projects \ ConsoleApplication1 \ ConsoleApplication1 \ Program. fs: line 14 Press any key to continue.,.

+7
source share
1 answer

This seems like a bug in the compiler - or am I missing something (report it to fsbugs on microsoft dot com ). For some reason, the compiler does not make a built-in call to the + operator (it works for - and / and for custom operators such as +. , But does not work for + and * ).

This means that the compiler really generates something like:

 // Inlined - returns zero directly fine = 0; // Failed to inline - calls a version which used dynamic lookup fail = LanguagePrimitives.AdditionDynamic <Tuple<double, double>, Test.Test<double>, double>(a, b); 

The AdditionDynamic method uses some internal table to search for + implementation for two types at runtime. Although you could register your type there, that would not be very useful, because the call would be slow.

I actually don’t have a good workaround - if you need an operator only for some basic numeric types ( float , int , etc.), then the easiest option would be to simply avoid using inline here and define an (overloaded) operator for specific types:

  static member (+) ((x:float,y:float), a: float Test) = x + y + ax + ay 

You can also try a trick with a global operator and helper type that implements various overloads, but I'm not sure if this will help: see, for example, this past question .

+5
source

All Articles