United Kingdom: +44 (0)208 088 8978

Treating Warnings as Errors across a solution with Directory.Build.Props

Isaac shows us how to apply common settings to all projects in a repository.

We're hiring Software Developers

Click here to find out more

It's not unusual in the F# world to treat warnings as errors, particularly as there are only a few specific warnings that regularly crop up in F#. For example, FS0025 is a warning for a non-exhaustive pattern match:

let x : int = ....

// warning FS0025: Incomplete pattern matches on this expression. For example, the value '2' may indicate a case not covered by the pattern(s).
let description =
    match x with
    | 0 -> "Zero"
    | 1 -> "A single number"

It's good habit to treat FS0025 as an error since an incomplete pattern match can lead to a runtime failure.

You can opt to treat this warning as an error (or indeed all warnings as errors) through either MSBuild arguments, or as settings in the fsproj file associated with your project:

    <WarningsAsErrors>0025</WarningsAsErrors>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <WarningsNotAsErrors>3391</WarningsNotAsErrors>
    <NoWarn>3391</NoWarn>

You can also disable warnings for specific cases using an inline #nowarn:

#nowarn "0025"

// code now compiles
let description =
    match x with
    | 0 -> "Zero"
    | 1 -> "A single number"

Disabling a warning here ultimately means that no compiler error is raised, even if you have TreatWarningsAsErrors set, since no warning is raised in the first place.

Applying across all projects in a solution

If you want to enforce such a standard in your application, if you have only a single project, this is easy enough to do: simply modify the fsproj as described above. However, if you have multiple projects, you can make use of the Directory.Build.Props file that .NET understands in order to apply it across all projects in a directory:

<Project>
    <PropertyGroup>
        <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
        <WarningsNotAsErrors>3391</WarningsNotAsErrors>
    </PropertyGroup>
</Project>

The above file should exist at the root of the directory / repository in which your .NET projects live, and will automatically apply these settings across all projects. Any new projects that you create will automatically "inherit" these settings.

The CIT Application template

We've recently applied this to the latest version of our CIT Console Template, so that you get this for free. By default we've set it to treat all warnings as errors, but you can of course tweak this as you see fit.

Conclusion

Treating warnings as errors is a good way to enforce compile-time safety, specifically in situations such as incomplete pattern matching and, when F# Nullness Support is released, for unsafely accessing nullable reference values. The Directory.Build.Props file is a great way to enforce this across all projects, and can be easily added to existing projects.