NOTE: new sections have been added to this template! Please use this template rather than copying an existing RFC.
The design suggestion has been marked "approved in principle".
This RFC covers the detailed proposal for this suggestion.
- Suggestion
- Approved in principle
- Implementation
- Design Review Meeting(s) with @dsyme and others invitees
- Discussion
The F# compiler has the ability to decide whether to inline user-defined values, functions and members (henceforth referred to collectively as 'values'). Users can enforce this behavior with the inline
keyword. Additionally, the JIT compiler can also decide to inline methods at run-time.
MethodImplAttribute(MethodImplOptions.NoInlining)
is a means of forcing both compilers not to inline. However, there is currently no way to tell the F# compiler not to inline, while leaving the JIT compiler free to do so. The proposed NoCompilerInliningAttribute
remedies this situation.
Having the F# compiler inline values can result in performance degradation in some scenarios where the JIT compiler would have produced superior machine code by inlining on its own.
We add NoCompilerInliningAttribute
to FSharp.Core. The attribute can be applied to a value, which the F# compiler then guarantees not to inline:
let functionInlined () = 3
[<NoCompilerInlining>]
let functionNotInlined () = 3
let six () = functionInlined () + functionNotInlined ()
By inspecting the emitted IL we want to see that the second function is not inlined:
.method public static int32 six() cil managed
{
.maxstack 8
IL_0000: ldc.i4.3
IL_0001: call int32 MyModule::functionNotInlined()
IL_0006: add
IL_0007: ret
}
Using both inline
and NoCompilerInliningAttribute
should result in a compilation error.
Having 2 attributes and a keyword that control inlining in different ways might be confusing, especially when NoCompilerInliningAttribute
and MethodImplAttribute(MethodImplOptions.AggressiveInlining)
are combined. However, the target audience of these attributes are advanced users and experts, so this is not a major concern. Run-of-the-mill applications will at most make use of inline
.
What other designs have been considered?
Using a keyword instead of an attribute.
What is the impact of not doing this?
Inability to speed up certain types of highly-specialized, performance-critical code.
Please address all necessary compatibility questions:
-
Is this a breaking change?
No.
-
What happens when previous versions of the F# compiler encounter this design addition as source code?
Code compiles fine, but values and functions might be inlined despite the attribute.
-
What happens when previous versions of the F# compiler encounter this design addition in compiled binaries?
Values and functions from compiled binaries might be inlined despite the attribute.
-
If this is a change or extension to FSharp.Core, what happens when previous versions of the F# compiler encounter this construct?
Code compiles fine, but values and functions might be inlined despite the attribute.
None.