Skip to content

update compiler directives page of FSharp reference #47130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 62 additions & 25 deletions docs/fsharp/language-reference/compiler-directives.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,58 @@
---
title: Compiler Directives
description: Learn about F# language preprocessor directives, conditional compilation directives, line directives, and compiler directives.
description: Learn about F# language conditional compilation directives, line directives, and warn directives.
ms.date: 12/10/2018
f1_keywords:
- "#endif_FS"
---
# Compiler Directives

This topic describes processor directives and compiler directives.
This topic describes compiler directives, for F# Interactive (`dotnet fsi`) directives, see [Interactive Programming with F#](../tools/fsharp-interactive/index.md).

For F# Interactive (`dotnet fsi`) directives, see [Interactive Programming with F#](../tools/fsharp-interactive/index.md).
A compiler directive is prefixed with the # symbol and appears on a line by itself.

## Preprocessor Directives

A preprocessor directive is prefixed with the # symbol and appears on a line by itself. It is interpreted by the preprocessor, which runs before the compiler itself.

The following table lists the preprocessor directives that are available in F#.
The following table lists the compiler directives that are available in F#.

|Directive|Description|
|---------|-----------|
|`#if` *symbol*|Supports conditional compilation. Code in the section after the `#if` is included if the *symbol* is defined. The symbol can also be negated with `!`.|
|`#else`|Supports conditional compilation. Marks a section of code to include if the symbol used with the previous `#if` is not defined.|
|`#if` *if-expression*|Supports conditional compilation. Code in the section after the `#if` is included if the *if-expression* evaluates to `defined` (see below).|
|`#else`|Supports conditional compilation. Marks a section of code to include if the symbol used with the previous `#if` does not evaluate to `defined`.|
|`#endif`|Supports conditional compilation. Marks the end of a conditional section of code.|
|`#`[line] *int*,<br/>`#`[line] *int* *string*,<br/>`#`[line] *int* *verbatim-string*|Indicates the original source code line and file name, for debugging. This feature is provided for tools that generate F# source code.|
|`#nowarn` *warningcode*|Disables a compiler warning or warnings. To disable multiple warning numbers on the same line, separate each string by a space. <br/> For example: `#nowarn 9 42`|

The effect of disabling a warning applies to the entire file, including portions of the file that precede the directive.|
|`#nowarn` *warningcodes*|Disables one or more compiler warnings as specified by *warningcodes* (see below).|
|`#warnon` *warningcodes*|Enables one or more compiler warnings as specified by *warningcodes* (see below).|

## Conditional Compilation Directives

Code that is deactivated by one of these directives appears dimmed in the Visual Studio Code Editor.

> [!NOTE]
> The behavior of the conditional compilation directives is not the same as it is in other languages. For example, you cannot use Boolean expressions involving symbols, and `true` and `false` have no special meaning. Symbols that you use in the `if` directive must be defined by the command line or in the project settings; there is no `define` preprocessor directive.

The following code illustrates the use of the `#if`, `#else`, and `#endif` directives. In this example, the code contains two versions of the definition of `function1`. When `VERSION1` is defined by using the [-define compiler option](./compiler-options.md), the code between the `#if` directive and the `#else` directive is activated. Otherwise, the code between `#else` and `#endif` is activated.

[!code-fsharp[Main](~/samples/snippets/fsharp/lang-ref-2/snippet7301.fs)]

There is no `#define` preprocessor directive in F#. You must use the compiler option or project settings to define the symbols used by the `#if` directive.

Conditional compilation directives can be nested. Indentation is not significant for preprocessor directives.

You can also negate a symbol with `!`. In this example, a string's value is something only when _not_ debugging:
The `#if` directive also accepts logical expressions:

```fsharp
#if !DEBUG
let str = "Not debugging!"
#else
let str = "Debugging!"
#if SILVERLIGHT || COMPILED && (NETCOREFX || !DEBUG)
#endif
```

The following expressions can be used.

| if-expr | evaluation |
| --- | --- |
| `if-expr1 \|\| if-expr2` | `defined` if `if-expr1` or `if-expr2` is `defined`. |
| `if-expr1 && if-expr2` | `defined` if `if-expr1` and `if-expr2` are `defined`. |
| `!if-expr1` | `defined` if `if-expr1` is not `defined`. |
| `( if-expr1 )` | defined if `if-expr1` is defined. |
| `symbol` | `defined` if it is flagged as defined by the `-define` compiler option. |

The logical operators have the usual logical precedence.

There is no `#define` compiler directive in F#. You must use the compiler option or project settings to define the symbols used by the `#if` directive.

Conditional compilation directives can be nested. Indentation is not significant for compiler directives.

## NULLABLE directive

Starting with F# 9, you can enable nullable reference types in the project:
Expand Down Expand Up @@ -84,6 +85,42 @@ When you use the `#line` directive, file names must be enclosed in quotation mar

These tokens indicate that the F# code generated at this location is derived from some constructs at or near line `25` in `Script1`.

Note that `#line` directives do not influence the behavior of `#nowarn` / `#warnon`. These two directives always relate the the file that is being compiled.

## Warn Directives

Warn directives disable or enable specified compiler warnings for parts of a source file.

A warn directive is a single line of source code that consists of

- Optional leading whitespace
- The string `#nowarn` or `#warnon`
- Whitespace
- One or more *warningcodes* (see below), separated by whitespace
- Optional whitespace
- Optional line comment

A *warningcode* is a sequence of digits (representing the warning number), optionally preceded by `FS`, optionally surrounded by double quotes.

A `#nowarn` directive disables a warning until a `#warnon` directive for the same warning number is found, or else until end of file. Similarly, a `#nowarn` directive disables a warning until a `#warnon` directive for the same warning numberis found, or else until end of file. Before and after such pairs, the compilation default applies, which is

- no warning if disabled by a --nowarn compiler option (or the respective msbuild property)
- no warning for [opt-in warnings](./compiler-options.md#opt-in-warnings), unless enabled by the --warnon compiler option (or the respective msbuild property)

Here is a (contrived) example.

```
module A
match None with None -> () // warning
let x =
#nowarn 25
match None with None -> 1 // no warning
#warnon FS25
match None with None -> () // warning
#nowarn "FS25" FS007 "42"
match None with None -> () // no warning
```

## See also

- [F# Language Reference](index.md)
Expand Down