@@ -413,3 +413,196 @@ let main _ =
413413 [ " call int32 Test::'<add>__debug@5'(int32,"
414414 " call float64 Test::'<add>__debug@6-1'(float64," ]
415415 |> shouldSucceed
416+
417+ [<Fact>]
418+ let ``SRTP 09 - Witness`` () =
419+ FSharp """
420+ let check s (b1: 'a) (b2: 'a) = if b1 = b2 then () else failwith s
421+
422+ let inline add (x: ^T) (y: ^T) = x + y
423+
424+ [<EntryPoint>]
425+ let main _ =
426+ check "int" (add 3 4) 7
427+ check "float" (add 1.0 2.0) 3.0
428+ 0
429+ """
430+ |> withDebug
431+ |> withNoOptimize
432+ |> asExe
433+ |> compileAndRun
434+ |> shouldSucceed
435+
436+ [<Fact>]
437+ let ``SRTP 10 - Witness`` () =
438+ FSharp """
439+ type MyNum =
440+ { Value: float }
441+ static member FromFloat (_: MyNum) = fun (x: float) -> { Value = x }
442+
443+ type T =
444+ static member inline Invoke(x: float) : 'Num =
445+ let inline call (a: ^a) = (^a: (static member FromFloat : _ -> _) a)
446+ call Unchecked.defaultof<'Num> x
447+
448+ [<EntryPoint>]
449+ let main _ =
450+ let result = T.Invoke<MyNum>(3.14)
451+ if result.Value = 3.14 then 0 else 1
452+ """
453+ |> withDebug
454+ |> withNoOptimize
455+ |> asExe
456+ |> compileAndRun
457+ |> verifyILContains [ " call class Test/MyNum Test::'<Invoke>__debug@13'(float64)" ]
458+ |> shouldSucceed
459+
460+ [<Fact>]
461+ let ``SRTP 11 - Witness`` () =
462+ FSharp """
463+ type MyNum =
464+ { Value: float }
465+ static member FromFloat (_: MyNum, _: T) = fun (x: float) -> { Value = x }
466+
467+ and T =
468+ { Dummy: int }
469+ static member inline Invoke(x: float) : 'Num =
470+ let inline call2 (a: ^a, b: ^b) = ((^a or ^b) : (static member FromFloat : _ * _ -> _) (b, a))
471+ let inline call (a: 'a) = fun (x: 'x) -> call2 (a, Unchecked.defaultof<'r>) x : 'r
472+ call Unchecked.defaultof<T> x
473+
474+ [<EntryPoint>]
475+ let main _ =
476+ let result = T.Invoke<MyNum>(2.71)
477+ if result.Value = 2.71 then 0 else 1
478+ """
479+ |> withDebug
480+ |> withNoOptimize
481+ |> asExe
482+ |> compileAndRun
483+ |> verifyILContains [ " call class Test/MyNum Test::'<Invoke>__debug@15'(float64)" ]
484+ |> shouldSucceed
485+
486+
487+ [<Fact>]
488+ let ``Member 01 - Non - generic`` () =
489+ FSharp """
490+ type T() =
491+ member inline _.Double(x: int) = x + x
492+
493+ [<EntryPoint>]
494+ let main _ =
495+ let t = T()
496+ let i = t.Double(5)
497+ if i = 10 then 0 else 1
498+ """
499+ |> withDebug
500+ |> withNoOptimize
501+ |> asExe
502+ |> compileAndRun
503+ |> verifyILContains [ " callvirt instance int32 Test/T::Double(int32)" ]
504+ |> shouldSucceed
505+
506+ [<Fact>]
507+ let ``Member 02 - Generic`` () =
508+ FSharp """
509+ type T() =
510+ member inline _.Apply(f: 'a -> 'b, x: 'a) : 'b = f x
511+
512+ [<EntryPoint>]
513+ let main _ =
514+ let t = T()
515+ let i = t.Apply((fun x -> x + 1), 5)
516+ if i = 6 then 0 else 1
517+ """
518+ |> withDebug
519+ |> withNoOptimize
520+ |> asExe
521+ |> compileAndRun
522+ |> verifyILContains [ " callvirt instance !!1 Test/T::Apply<int32,int32>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!!0,!!1>," ]
523+ |> shouldSucceed
524+
525+ [<Fact>]
526+ let ``Member 03 - SRTP`` () =
527+ FSharp """
528+ type T() =
529+ member inline _.Add(x: ^T, y: ^T) = x + y
530+
531+ [<EntryPoint>]
532+ let main _ =
533+ let t = T()
534+ let i = t.Add(3, 4)
535+ if i = 7 then 0 else 1
536+ """
537+ |> withDebug
538+ |> withNoOptimize
539+ |> asExe
540+ |> compileAndRun
541+ |> verifyILContains [ " call int32 Test::'<Add>__debug@8'(class Test/T," ]
542+ |> shouldSucceed
543+
544+ [<Fact>]
545+ let ``Operator 01 - Top - level`` () =
546+ FSharp """
547+ let inline (++) (x: int) (y: int) = x + y + 1
548+
549+ [<EntryPoint>]
550+ let main _ =
551+ let i = 3 ++ 4
552+ if i = 8 then 0 else 1
553+ """
554+ |> withDebug
555+ |> withNoOptimize
556+ |> asExe
557+ |> compileAndRun
558+ |> verifyILContains [ " call int32 Test::op_PlusPlus(int32," ]
559+ |> shouldSucceed
560+
561+ [<Fact>]
562+ let ``Operator 02 - Top - level SRTP`` () =
563+ FSharp """
564+ let inline (++) (x: ^T) (y: ^T) = x + y
565+
566+ [<EntryPoint>]
567+ let main _ =
568+ let i = 3 ++ 4
569+ if i = 7 then 0 else 1
570+ """
571+ |> withDebug
572+ |> withNoOptimize
573+ |> asExe
574+ |> compileAndRun
575+ |> verifyILContains [ " call int32 Test::'<op_PlusPlus>__debug@6'(int32," ]
576+ |> shouldSucceed
577+
578+ [<Fact>]
579+ let ``Operator 03 - Local`` () =
580+ FSharp """
581+ [<EntryPoint>]
582+ let main _ =
583+ let inline (++) (x: int) (y: int) = x + y + 1
584+ let i = 3 ++ 4
585+ if i = 8 then 0 else 1
586+ """
587+ |> withDebug
588+ |> withNoOptimize
589+ |> asExe
590+ |> compileAndRun
591+ |> verifyILContains [ " call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,int32>::InvokeFast<int32>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!0,class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!1,!!0>>," ]
592+ |> shouldSucceed
593+
594+ [<Fact>]
595+ let ``Operator 04 - Local SRTP`` () =
596+ FSharp """
597+ [<EntryPoint>]
598+ let main _ =
599+ let inline (++) (x: ^T) (y: ^T) = x + y
600+ let i = 3 ++ 4
601+ if i = 7 then 0 else 1
602+ """
603+ |> withDebug
604+ |> withNoOptimize
605+ |> asExe
606+ |> compileAndRun
607+ |> verifyILContains [ " call int32 Test::'<op_PlusPlus>__debug@5'(int32," ]
608+ |> shouldSucceed
0 commit comments