From f184e2c7dd75cd3d1a15b0ba64fef873cbb3f0e5 Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Fri, 26 Apr 2024 12:21:35 +0200 Subject: [PATCH 1/2] Allow AttributeTargets.Field and .Property for type let bindings --- src/Compiler/Checking/CheckExpressions.fs | 15 ++++++++++++--- .../AttributeUsage/AttributeUsage.fs | 14 +++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 3466b162c3a..75f6083dce2 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10630,6 +10630,11 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt | NormalizedBinding(vis, kind, isInline, isMutable, attrs, xmlDoc, _, valSynData, pat, NormalizedBindingRhs(spatsL, rtyOpt, rhsExpr), mBinding, debugPoint) -> let (SynValData(memberFlags = memberFlagsOpt)) = valSynData + let isClassLetBinding = + match declKind, kind with + | ClassLetBinding _, SynBindingKind.Normal -> true + | _ -> false + let callerName = match declKind, kind, pat with | ExpressionBinding, _, _ -> envinner.eCallerMemberName @@ -10885,14 +10890,14 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt errorR(Error(FSComp.SR.tcLiteralCannotHaveGenericParameters(), mBinding)) if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) && memberFlagsOpt.IsNone && not attrs.IsEmpty then - TcAttributeTargetsOnLetBindings cenv env attrs overallPatTy overallExprTy (not declaredTypars.IsEmpty) + TcAttributeTargetsOnLetBindings cenv env attrs overallPatTy overallExprTy (not declaredTypars.IsEmpty) isClassLetBinding CheckedBindingInfo(inlineFlag, valAttribs, xmlDoc, tcPatPhase2, explicitTyparInfo, nameToPrelimValSchemeMap, rhsExprChecked, argAndRetAttribs, overallPatTy, mBinding, debugPoint, isCompGen, literalValue, isFixed), tpenv // Note: // - Let bound values can only have attributes that uses AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue // - Let function bindings can only have attributes that uses AttributeTargets.Method ||| AttributeTargets.ReturnValue -and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallExprTy areTyparsDeclared = +and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallExprTy areTyparsDeclared isClassLetBinding = let attrTgt = if // It's a type function: @@ -10904,7 +10909,11 @@ and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallE || isFunTy cenv.g overallPatTy || isFunTy cenv.g overallExprTy then - AttributeTargets.ReturnValue ||| AttributeTargets.Method + // 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. + if isClassLetBinding then + AttributeTargets.ReturnValue ||| AttributeTargets.Method ||| AttributeTargets.Field ||| AttributeTargets.Property + else + AttributeTargets.ReturnValue ||| AttributeTargets.Method else AttributeTargets.ReturnValue ||| AttributeTargets.Field ||| AttributeTargets.Property diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs index 71cc1266dd4..8936f03fdb8 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -591,4 +591,16 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 20, Col 3, Line 20, Col 15, "This attribute is not valid for use on this language element") (Error 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element") (Error 842, Line 22, Col 3, Line 22, Col 13, "This attribute is not valid for use on this language element") - ] \ No newline at end of file + ] + + [] + let ``Type-level let bindings allowed to use attribute with Field target`` () = + FSharp""" +module Foo +type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) = + [] + let mutable valueFactory = valueFactory + """ + |> withLangVersionPreview + |> compile + |> shouldSucceed \ No newline at end of file From 88967c93d3440a1ea22a5a5c6073c1a894673bc0 Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Fri, 26 Apr 2024 13:01:11 +0200 Subject: [PATCH 2/2] Fixed tests which involved fields+functions --- .../AttributeUsage/AttributeUsage.fs | 22 +----------- .../E_AttributeTargetIsField02.fs | 36 +++++++++---------- 2 files changed, 19 insertions(+), 39 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs index 8936f03fdb8..d9ff7e9597c 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -171,27 +171,7 @@ module CustomAttributes_AttributeUsage = |> withLangVersionPreview |> withOptions ["--nowarn:25"] |> verifyCompile - |> shouldFail - |> withDiagnostics [ - (Error 842, Line 11, Col 6, Line 11, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 14, Col 6, Line 14, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 17, Col 6, Line 17, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 19, Col 10, Line 19, Col 19, "This attribute is not valid for use on this language element") - (Error 842, Line 21, Col 6, Line 21, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 24, Col 6, Line 24, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 27, Col 6, Line 27, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 30, Col 6, Line 30, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 33, Col 6, Line 33, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 36, Col 6, Line 36, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 39, Col 6, Line 39, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 42, Col 6, Line 42, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 45, Col 6, Line 45, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 49, Col 6, Line 49, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 56, Col 6, Line 56, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 64, Col 6, Line 64, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 66, Col 10, Line 66, Col 19, "This attribute is not valid for use on this language element") - (Error 842, Line 68, Col 6, Line 68, Col 15, "This attribute is not valid for use on this language element") - ] + |> shouldSucceed // SOURCE=E_AttributeTargetIsMethod02.fs # E_AttributeTargetIsMethod02.fs [] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField02.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField02.fs index c7ba6dda24f..0cfd840e42b 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField02.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField02.fs @@ -8,52 +8,52 @@ type FieldOnlyAttribute() = inherit Attribute() type TestClass() = - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) static let func1() = "someFunction" - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) static let rec func2() = "someFunction" - []// Should fail + []// Should succeed (special exception when function can be lifted to a field) static let rec func3() = "someFunction" - and [] fun4() = "someFunction" // Should fail + and [] fun4() = "someFunction" // Should succeed (special exception when function can be lifted to a field) - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let func5 () = "someFunction" - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let func6 a = a + 1 - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let func7 (a, b) = a + b - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let func8 (a: int) : int = a + 1 - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let func9 a b = [ a; b ] - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let func10 = fun x -> x - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let func11 = id - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let (|Bool|_|) = function "true" -> Some true | "false" -> Some false | _ -> None - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) [] let (|BoolExpr2|_|) = function "true" -> ValueSome true | "false" -> ValueSome false | _ -> ValueNone - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let (|BoolExpr3|_|) x = match x with | "true" -> Some true | "false" -> Some false | _ -> None - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) [] let (|BoolExpr4|_|) x = match x with @@ -61,9 +61,9 @@ type TestClass() = | "false" -> ValueSome false | _ -> ValueNone - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let rec func12() = 0 - and [] func13() = [] // Should fail + and [] func13() = [] // Should succeed (special exception when function can be lifted to a field) - [] // Should fail + [] // Should succeed (special exception when function can be lifted to a field) let rec func14() = 0 \ No newline at end of file