Skip to content

Commit 8b51fa7

Browse files
Allow AttributeTargets.Field and .Property for type let bindings (#17093)
* Allow AttributeTargets.Field and .Property for type let bindings * Fixed tests which involved fields+functions --------- Co-authored-by: Petr <[email protected]>
1 parent 353560e commit 8b51fa7

File tree

3 files changed

+44
-43
lines changed

3 files changed

+44
-43
lines changed

src/Compiler/Checking/CheckExpressions.fs

+12-3
Original file line numberDiff line numberDiff line change
@@ -10625,6 +10625,11 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt
1062510625
| NormalizedBinding(vis, kind, isInline, isMutable, attrs, xmlDoc, _, valSynData, pat, NormalizedBindingRhs(spatsL, rtyOpt, rhsExpr), mBinding, debugPoint) ->
1062610626
let (SynValData(memberFlags = memberFlagsOpt)) = valSynData
1062710627

10628+
let isClassLetBinding =
10629+
match declKind, kind with
10630+
| ClassLetBinding _, SynBindingKind.Normal -> true
10631+
| _ -> false
10632+
1062810633
let callerName =
1062910634
match declKind, kind, pat with
1063010635
| ExpressionBinding, _, _ -> envinner.eCallerMemberName
@@ -10880,14 +10885,14 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt
1088010885
errorR(Error(FSComp.SR.tcLiteralCannotHaveGenericParameters(), mBinding))
1088110886

1088210887
if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) && memberFlagsOpt.IsNone && not attrs.IsEmpty then
10883-
TcAttributeTargetsOnLetBindings cenv env attrs overallPatTy overallExprTy (not declaredTypars.IsEmpty)
10888+
TcAttributeTargetsOnLetBindings cenv env attrs overallPatTy overallExprTy (not declaredTypars.IsEmpty) isClassLetBinding
1088410889

1088510890
CheckedBindingInfo(inlineFlag, valAttribs, xmlDoc, tcPatPhase2, explicitTyparInfo, nameToPrelimValSchemeMap, rhsExprChecked, argAndRetAttribs, overallPatTy, mBinding, debugPoint, isCompGen, literalValue, isFixed), tpenv
1088610891

1088710892
// Note:
1088810893
// - Let bound values can only have attributes that uses AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue
1088910894
// - Let function bindings can only have attributes that uses AttributeTargets.Method ||| AttributeTargets.ReturnValue
10890-
and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallExprTy areTyparsDeclared =
10895+
and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallExprTy areTyparsDeclared isClassLetBinding =
1089110896
let attrTgt =
1089210897
if
1089310898
// It's a type function:
@@ -10899,7 +10904,11 @@ and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallE
1089910904
|| isFunTy cenv.g overallPatTy
1090010905
|| isFunTy cenv.g overallExprTy
1090110906
then
10902-
AttributeTargets.ReturnValue ||| AttributeTargets.Method
10907+
// Class let bindings are a special case, they can have attributes that target fields and properties, since they might be lifted to those and contain lambdas/functions.
10908+
if isClassLetBinding then
10909+
AttributeTargets.ReturnValue ||| AttributeTargets.Method ||| AttributeTargets.Field ||| AttributeTargets.Property
10910+
else
10911+
AttributeTargets.ReturnValue ||| AttributeTargets.Method
1090310912
else
1090410913
AttributeTargets.ReturnValue ||| AttributeTargets.Field ||| AttributeTargets.Property
1090510914

tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs

+14-22
Original file line numberDiff line numberDiff line change
@@ -171,27 +171,7 @@ module CustomAttributes_AttributeUsage =
171171
|> withLangVersionPreview
172172
|> withOptions ["--nowarn:25"]
173173
|> verifyCompile
174-
|> shouldFail
175-
|> withDiagnostics [
176-
(Error 842, Line 11, Col 6, Line 11, Col 15, "This attribute is not valid for use on this language element")
177-
(Error 842, Line 14, Col 6, Line 14, Col 15, "This attribute is not valid for use on this language element")
178-
(Error 842, Line 17, Col 6, Line 17, Col 15, "This attribute is not valid for use on this language element")
179-
(Error 842, Line 19, Col 10, Line 19, Col 19, "This attribute is not valid for use on this language element")
180-
(Error 842, Line 21, Col 6, Line 21, Col 15, "This attribute is not valid for use on this language element")
181-
(Error 842, Line 24, Col 6, Line 24, Col 15, "This attribute is not valid for use on this language element")
182-
(Error 842, Line 27, Col 6, Line 27, Col 15, "This attribute is not valid for use on this language element")
183-
(Error 842, Line 30, Col 6, Line 30, Col 15, "This attribute is not valid for use on this language element")
184-
(Error 842, Line 33, Col 6, Line 33, Col 15, "This attribute is not valid for use on this language element")
185-
(Error 842, Line 36, Col 6, Line 36, Col 15, "This attribute is not valid for use on this language element")
186-
(Error 842, Line 39, Col 6, Line 39, Col 15, "This attribute is not valid for use on this language element")
187-
(Error 842, Line 42, Col 6, Line 42, Col 15, "This attribute is not valid for use on this language element")
188-
(Error 842, Line 45, Col 6, Line 45, Col 15, "This attribute is not valid for use on this language element")
189-
(Error 842, Line 49, Col 6, Line 49, Col 15, "This attribute is not valid for use on this language element")
190-
(Error 842, Line 56, Col 6, Line 56, Col 15, "This attribute is not valid for use on this language element")
191-
(Error 842, Line 64, Col 6, Line 64, Col 15, "This attribute is not valid for use on this language element")
192-
(Error 842, Line 66, Col 10, Line 66, Col 19, "This attribute is not valid for use on this language element")
193-
(Error 842, Line 68, Col 6, Line 68, Col 15, "This attribute is not valid for use on this language element")
194-
]
174+
|> shouldSucceed
195175

196176
// SOURCE=E_AttributeTargetIsMethod02.fs # E_AttributeTargetIsMethod02.fs
197177
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_AttributeTargetIsMethod02.fs"|])>]
@@ -591,4 +571,16 @@ module CustomAttributes_AttributeUsage =
591571
(Error 842, Line 20, Col 3, Line 20, Col 15, "This attribute is not valid for use on this language element")
592572
(Error 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element")
593573
(Error 842, Line 22, Col 3, Line 22, Col 13, "This attribute is not valid for use on this language element")
594-
]
574+
]
575+
576+
[<Fact>]
577+
let ``Type-level let bindings allowed to use attribute with Field target`` () =
578+
FSharp"""
579+
module Foo
580+
type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
581+
[<VolatileField>]
582+
let mutable valueFactory = valueFactory
583+
"""
584+
|> withLangVersionPreview
585+
|> compile
586+
|> shouldSucceed

tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField02.fs

+18-18
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,62 @@ type FieldOnlyAttribute() =
88
inherit Attribute()
99

1010
type TestClass() =
11-
[<FieldOnly>] // Should fail
11+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
1212
static let func1() = "someFunction"
1313

14-
[<FieldOnly>] // Should fail
14+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
1515
static let rec func2() = "someFunction"
1616

17-
[<FieldOnly>]// Should fail
17+
[<FieldOnly>]// Should succeed (special exception when function can be lifted to a field)
1818
static let rec func3() = "someFunction"
19-
and [<FieldOnly>] fun4() = "someFunction" // Should fail
19+
and [<FieldOnly>] fun4() = "someFunction" // Should succeed (special exception when function can be lifted to a field)
2020

21-
[<FieldOnly>] // Should fail
21+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
2222
let func5 () = "someFunction"
2323

24-
[<FieldOnly>] // Should fail
24+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
2525
let func6 a = a + 1
2626

27-
[<FieldOnly>] // Should fail
27+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
2828
let func7 (a, b) = a + b
2929

30-
[<FieldOnly>] // Should fail
30+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
3131
let func8 (a: int) : int = a + 1
3232

33-
[<FieldOnly>] // Should fail
33+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
3434
let func9 a b = [ a; b ]
3535

36-
[<FieldOnly>] // Should fail
36+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
3737
let func10 = fun x -> x
3838

39-
[<FieldOnly>] // Should fail
39+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
4040
let func11 = id
4141

42-
[<FieldOnly>] // Should fail
42+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
4343
let (|Bool|_|) = function "true" -> Some true | "false" -> Some false | _ -> None
4444

45-
[<FieldOnly>] // Should fail
45+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
4646
[<return: Struct>]
4747
let (|BoolExpr2|_|) = function "true" -> ValueSome true | "false" -> ValueSome false | _ -> ValueNone
4848

49-
[<FieldOnly>] // Should fail
49+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
5050
let (|BoolExpr3|_|) x =
5151
match x with
5252
| "true" -> Some true
5353
| "false" -> Some false
5454
| _ -> None
5555

56-
[<FieldOnly>] // Should fail
56+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
5757
[<return: Struct>]
5858
let (|BoolExpr4|_|) x =
5959
match x with
6060
| "true" -> ValueSome true
6161
| "false" -> ValueSome false
6262
| _ -> ValueNone
6363

64-
[<FieldOnly>] // Should fail
64+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
6565
let rec func12() = 0
66-
and [<FieldOnly>] func13() = [] // Should fail
66+
and [<FieldOnly>] func13() = [] // Should succeed (special exception when function can be lifted to a field)
6767

68-
[<FieldOnly>] // Should fail
68+
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
6969
let rec func14() = 0

0 commit comments

Comments
 (0)