Improper AttributeTargets enforcement

The F# 9 release introduced attribute targets enforcement on let binding, as illustrated by the following example from the blog:

[<Fact>]
let ``this test always fails`` =
  Assert.True(false)

In this snippet, an attribute intended for methods is applied on a value bindings, thus leading to an error. The opposite holds as well:

[<FieldOnly>] // Suppose AttributeTargets.Field on it.
let foo () = whatever

However, problem arises when the value binding decorated by the attribute is not in fact a field. In cases of extremely simple values

open System

[<AttributeUsage(AttributeTargets.Field)>]
type FieldOnly() =
    inherit Attribute()

[<FieldOnly>]
let foo = 0

or parametric values

open System

[<AttributeUsage(AttributeTargets.Field)>]
type FieldOnly() =
    inherit Attribute()

[<FieldOnly>]
let foo = None

the value binding compiles to a property without a backing field, so the attribute intended for fields is actually applied on a property.

I think this might lead to some subtle bugs in reflective programs, such as a dynamic script loader. Is there any fix to it? Or is it worth a GitHub issue?

Hello,

You’re absolutely right to be concerned. The issue you’re describing — the incorrect application of attributes due to F#'s compilation model — is subtle, non-obvious, and could easily cause problems in reflective or meta-programming scenarios. Let’s break this down and assess what the behavior is and whether it’s worth raising as a GitHub issue.

Best Regards

Blockquote DogTranslator

Be aware that the feature was put back to preview in F#9. Try setting it in the fsproj and check this is still an issue