From fe73348c3d7f3eb697d65bffbf437a2a03206206 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 12 Feb 2024 18:13:45 +0000 Subject: [PATCH 01/15] Enforce attribute targets on functions --- src/Compiler/Checking/CheckExpressions.fs | 20 +++- src/Compiler/FSComp.txt | 1 + src/Compiler/Facilities/LanguageFeatures.fs | 3 + src/Compiler/Facilities/LanguageFeatures.fsi | 1 + src/Compiler/xlf/FSComp.txt.cs.xlf | 5 + src/Compiler/xlf/FSComp.txt.de.xlf | 5 + src/Compiler/xlf/FSComp.txt.es.xlf | 5 + src/Compiler/xlf/FSComp.txt.fr.xlf | 5 + src/Compiler/xlf/FSComp.txt.it.xlf | 5 + src/Compiler/xlf/FSComp.txt.ja.xlf | 5 + src/Compiler/xlf/FSComp.txt.ko.xlf | 5 + src/Compiler/xlf/FSComp.txt.pl.xlf | 5 + src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 5 + src/Compiler/xlf/FSComp.txt.ru.xlf | 5 + src/Compiler/xlf/FSComp.txt.tr.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 5 + .../AttributeUsage/AttributeUsage.fs | 23 ++++ .../AttributeUsage/E_AttributeTargets03.fs | 101 ++++++++++++++++++ 19 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index e59fb6bd5ff..72e24540f30 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10556,8 +10556,24 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt | _, _, _ -> envinner.eCallerMemberName let envinner = {envinner with eCallerMemberName = callerName } - - let attrTgt = declKind.AllowedAttribTargets memberFlagsOpt + let attrTgt = + if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnFunctions) then + let supportsNameofFeature = g.langVersion.SupportsFeature(LanguageFeature.NameOf) + let rhsExprIsFunction = + match rhsExpr with + | SynExpr.Lambda _ + | SynExpr.Match _ + | SynExpr.MatchLambda _ -> true + | SynExpr.App(funcExpr = SynExpr.Ident(ident)) when supportsNameofFeature && ident.idText <> "nameof" -> true + | SynExpr.Ident ident when ident.idText = "id" -> true + | _ -> false + + match pat with + | SynPat.Tuple _ when not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue + | SynPat.Named _ when spatsL.IsEmpty && declaredTypars.IsEmpty && not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue + | _ -> declKind.AllowedAttribTargets memberFlagsOpt + else + declKind.AllowedAttribTargets memberFlagsOpt let isFixed, rhsExpr, overallPatTy, overallExprTy = match rhsExpr with diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index a9fc2692157..ab21ca7abc5 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1594,6 +1594,7 @@ featureWarningIndexedPropertiesGetSetSameType,"Indexed properties getter and set featureChkTailCallAttrOnNonRec,"Raises warnings if the 'TailCall' attribute is used on non-recursive functions." featureUnionIsPropertiesVisible,"Union case test properties" featureBooleanReturningAndReturnTypeDirectedPartialActivePattern,"Boolean-returning and return-type-directed partial active patterns" +featureEnforceAttributeTargetsOnFunctions,"Enforce AttributeTargets on functions" 3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." 3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." 3355,tcNotAnIndexerNamedIndexingNotYetEnabled,"The value '%s' is not a function and does not support index notation." diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index e7c2a25ee3d..f734ac5b62d 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -85,6 +85,7 @@ type LanguageFeature = | WarningIndexedPropertiesGetSetSameType | WarningWhenTailCallAttrOnNonRec | BooleanReturningAndReturnTypeDirectedPartialActivePattern + | EnforceAttributeTargetsOnFunctions /// LanguageVersion management type LanguageVersion(versionText) = @@ -197,6 +198,7 @@ type LanguageVersion(versionText) = LanguageFeature.WarningWhenTailCallAttrOnNonRec, previewVersion LanguageFeature.UnionIsPropertiesVisible, previewVersion LanguageFeature.BooleanReturningAndReturnTypeDirectedPartialActivePattern, previewVersion + LanguageFeature.EnforceAttributeTargetsOnFunctions, previewVersion ] static let defaultLanguageVersion = LanguageVersion("default") @@ -340,6 +342,7 @@ type LanguageVersion(versionText) = | LanguageFeature.WarningWhenTailCallAttrOnNonRec -> FSComp.SR.featureChkTailCallAttrOnNonRec () | LanguageFeature.BooleanReturningAndReturnTypeDirectedPartialActivePattern -> FSComp.SR.featureBooleanReturningAndReturnTypeDirectedPartialActivePattern () + | LanguageFeature.EnforceAttributeTargetsOnFunctions -> FSComp.SR.featureEnforceAttributeTargetsOnFunctions () /// Get a version string associated with the given feature. static member GetFeatureVersionString feature = diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index 29d6c2c33a3..02a15375d97 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -76,6 +76,7 @@ type LanguageFeature = | WarningIndexedPropertiesGetSetSameType | WarningWhenTailCallAttrOnNonRec | BooleanReturningAndReturnTypeDirectedPartialActivePattern + | EnforceAttributeTargetsOnFunctions /// LanguageVersion management type LanguageVersion = diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index c7dbc64bac7..ca0b8d396c4 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -292,6 +292,11 @@ literál float32 bez tečky + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Vyvolá chyby pro přepsání jiných než virtuálních členů diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index d5800420f00..843bed3cb41 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -292,6 +292,11 @@ punktloses float32-Literal + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Löst Fehler für Außerkraftsetzungen nicht virtueller Member aus. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index dcfce175697..70c73d123c9 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -292,6 +292,11 @@ literal float32 sin punto + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Genera errores para invalidaciones de miembros no virtuales diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 590c4fb8e15..8be0b215aae 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -292,6 +292,11 @@ littéral float32 sans point + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Déclenche des erreurs pour les remplacements de membres non virtuels diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 70613984b76..a22ddab4239 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -292,6 +292,11 @@ valore letterale float32 senza punti + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Genera errori per gli override dei membri non virtuali diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 84a9ca6ef70..de17a7edb6f 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -292,6 +292,11 @@ ドットなしの float32 リテラル + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides 仮想メンバー以外のオーバーライドに対してエラーを発生させます diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 38ffac7d32d..86d6ce4dbf7 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -292,6 +292,11 @@ 점이 없는 float32 리터럴 + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides 비가상 멤버 재정의에 대한 오류 발생 diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index ac1d54f63c4..825e5ceef21 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -292,6 +292,11 @@ bezkropkowy literał float32 + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Zgłasza błędy w przypadku przesłonięć elementów innych niż wirtualne diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 6beb1946267..f80e0ab75fc 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -292,6 +292,11 @@ literal float32 sem ponto + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Gera erros para substituições de membros não virtuais diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 1b83dc7cc6b..287274be071 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -292,6 +292,11 @@ литерал float32 без точки + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Вызывает ошибки при переопределениях невиртуальных элементов diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 43f5069b2eb..e4f5308c2b6 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -292,6 +292,11 @@ noktasız float32 sabit değeri + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides Sanal olmayan üyelerde geçersiz kılmalar için hatalar oluştur diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 91cad01e99e..09e8b278b70 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -292,6 +292,11 @@ 无点 float32 文本 + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides 引发非虚拟成员替代的错误 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index f12b3fd0b5e..c5a6ba081d6 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -292,6 +292,11 @@ 無點號的 float32 常值 + + Enforce AttributeTargets on functions + Enforce AttributeTargets on functions + + Raises errors for non-virtual members overrides 引發非虛擬成員覆寫的錯誤 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 cddee9f80ab..f86b050cee7 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -94,6 +94,29 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 24, Col 7, Line 24, Col 36, "This attribute is not valid for use on this language element") (Error 842, Line 29, Col 15, Line 29, Col 47, "This attribute is not valid for use on this language element") ] + + // SOURCE=E_AttributeTargets03.fs # E_AttributeTargets03.fs + [] + let ``E_AttributeTargets03_fs`` compilation = + compilation + |> withLangVersion80 + |> verifyCompile + |> shouldSucceed + + // SOURCE=E_AttributeTargets03.fs # E_AttributeTargets03.fs + [] + let ``E_AttributeTargets03_fs preview`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 842, Line 8, Col 3, Line 8, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 11, Col 3, Line 11, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 14, Col 3, Line 14, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 17, Col 3, Line 17, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 20, Col 3, Line 20, Col 13, "This attribute is not valid for use on this language element") + ] // SOURCE=E_ConditionalAttribute.fs SCFLAGS="--test:ErrorRanges" # E_ConditionalAttribute.fs [] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs new file mode 100644 index 00000000000..6a9785ef695 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs @@ -0,0 +1,101 @@ + +open System + +[] +type MethodOnlyAttribute() = + inherit Attribute() + +[] +let someValue = "someValue" // Should fail + +[] +let i, j, k = (1, 2, 3) // Should fail + +[] +let someRecLetBoundValue = nameof(MethodOnlyAttribute) // Should fail + +[] +let rec someRecLetBoundValue2 = nameof(someRecLetBoundValue2) // Should fail + +[] +let ``someValue2`` = "someValue" // Should fail + +[] +let someFunction () = "someFunction" + +[] +let someFunction2 a = a + 1 + +[] +let someFunction3 (a, b) = a + b + +[] +let someFunction4 (a: int) : int = a + 1 + +[] +let makeList a b = [ a; b ] + +[] +let someTypedFunction<'a> = "someTypedFunction" + +[] +let someTypedFunction2<'a> (x : 'a) = "someTypedFunction2" + +[] +let someTypedFunction3 = fun x -> x + +[] +let someTypedFunction4 = id + +[] +let __someTypedFunction5<'a> = false + +[] +let __someTypedFunction6<'a> : bool = false + +type TestConst = + | Bool of bool + +[] +type TestExpr = + | Const of TestConst * Type * int + | Var of string * Type * int + +[] +let (|BoolExpr|_|) = + function + | TestExpr.Const (TestConst.Bool b, _, _) -> Some b + | _ -> None + +[] +[] +let (|BoolExpr2|_|) = + function + | TestExpr.Const(TestConst.Bool b1, _, _) -> ValueSome b1 + | _ -> ValueNone + +[] +let (|BoolExpr3|_|) x = + match x with + | TestExpr.Const (TestConst.Bool b, _, _) -> Some b + | _ -> None + +[] +[] +let (|BoolExpr4|_|) x = + match x with + | TestExpr.Const(TestConst.Bool b1, _, _) -> ValueSome b1 + | _ -> ValueNone + +let private dangling (target: TestExpr -> TestExpr voption) = + function + | TestExpr.Const (TestConst.Bool _, _, _) as b -> ValueSome b + | _ -> ValueNone + +[] +[] +let (|IfThen|_|) = + dangling (function + | TestExpr.Const(TestConst.Bool b1, _, _) as expr -> ValueSome expr + | _ -> ValueNone) + From 5c8d2a8ace591b16d5d50628b4978574801e7e9b Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 12 Feb 2024 20:21:33 +0000 Subject: [PATCH 02/15] Remove redundant check as now will be properly check for attribute targets on functions --- src/Compiler/Checking/TailCallChecks.fs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Compiler/Checking/TailCallChecks.fs b/src/Compiler/Checking/TailCallChecks.fs index c26683e3da9..ce6ab702bdc 100644 --- a/src/Compiler/Checking/TailCallChecks.fs +++ b/src/Compiler/Checking/TailCallChecks.fs @@ -725,12 +725,7 @@ let CheckModuleBinding cenv (isRec: bool) (TBind _ as bind) = // warn for non-rec functions which have the attribute if cenv.g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailCallAttrOnNonRec then - let isNotAFunction = - match bind.Var.ValReprInfo with - | Some info -> info.HasNoArgs - | _ -> false - - if (not isRec || isNotAFunction) && cenv.g.HasTailCallAttrib bind.Var.Attribs then + if not isRec && cenv.g.HasTailCallAttrib bind.Var.Attribs then warning (Error(FSComp.SR.chkTailCallAttrOnNonRec (), bind.Var.Range)) // Check if a let binding to the result of a rec expression is not inside the rec expression From 5ffd470795a1e5b15dc797d50e99899ac359db3f Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 12 Feb 2024 20:21:55 +0000 Subject: [PATCH 03/15] Update Tests --- .../ErrorMessages/TailCallAttribute.fs | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 56572879715..9d34b2466e6 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1440,7 +1440,7 @@ namespace N ] [] - let ``Warn about attribute on non-recursive let-bound value`` () = + let ``Error about attribute on non-recursive let-bound value`` () = """ namespace N @@ -1453,18 +1453,10 @@ namespace N |> withLangVersionPreview |> compile |> shouldFail - |> withResults [ - { Error = Warning 3861 - Range = { StartLine = 7 - StartColumn = 13 - EndLine = 7 - EndColumn = 18 } - Message = - "The TailCall attribute should only be applied to recursive functions." } - ] + |> withSingleDiagnostic (Error 842, Line 6, Col 11, Line 6, Col 19, "This attribute is not valid for use on this language element") [] - let ``Warn about attribute on recursive let-bound value`` () = + let ``Error about attribute on recursive let-bound value`` () = """ namespace N @@ -1477,15 +1469,7 @@ namespace N |> withLangVersionPreview |> compile |> shouldFail - |> withResults [ - { Error = Warning 3861 - Range = { StartLine = 7 - StartColumn = 17 - EndLine = 7 - EndColumn = 37 } - Message = - "The TailCall attribute should only be applied to recursive functions." } - ] + |> withSingleDiagnostic (Error 842, Line 6, Col 11, Line 6, Col 19, "This attribute is not valid for use on this language element") [] let ``Warn about self-defined attribute`` () = // is the analysis available for users of older FSharp.Core versions From 66c803d20322808d45e289aaca6d0083596a592c Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 12 Feb 2024 21:36:26 +0000 Subject: [PATCH 04/15] More tests --- tests/service/ProjectAnalysisTests.fs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 8a643c9a7bc..ab38d14efec 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -4749,17 +4749,17 @@ type TestRecord = { B : int } module Test = [)>] - let withType = 0 + let withType() = 0 [>)>] - let withGenericType = 0 + let withGenericType() = 0 [)>] - let withTupleType = 0 + let withTupleType() = 0 [ int>)>] - let withFuncType = 0 + let withFuncType() = 0 [; typeof |])>] - let withTypeArray = 0 + let withTypeArray() = 0 [] - let withIntArray = 0 + let withIntArray() = 0 module NestedModule = type NestedRecordType = { B : int } From 99f311e93bc80b825936799b4439372e86bb7755 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Tue, 13 Feb 2024 16:46:21 +0000 Subject: [PATCH 05/15] More tests --- src/Compiler/Checking/CheckExpressions.fs | 2 +- .../AttributeUsage/AttributeUsage.fs | 34 ++++++ .../AttributeUsage/E_AttributeTargets04.fs | 101 ++++++++++++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 72e24540f30..9b12d80692a 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10571,7 +10571,7 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt match pat with | SynPat.Tuple _ when not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue | SynPat.Named _ when spatsL.IsEmpty && declaredTypars.IsEmpty && not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue - | _ -> declKind.AllowedAttribTargets memberFlagsOpt + | _ -> AttributeTargets.Method ||| AttributeTargets.ReturnValue else declKind.AllowedAttribTargets memberFlagsOpt 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 f86b050cee7..ba2164932c5 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -117,6 +117,40 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 17, Col 3, Line 17, Col 13, "This attribute is not valid for use on this language element") (Error 842, Line 20, Col 3, Line 20, Col 13, "This attribute is not valid for use on this language element") ] + + // SOURCE=E_AttributeTargets04.fs # E_AttributeTargets04.fs + [] + let ``E_AttributeTargets04_fs`` compilation = + compilation + |> withLangVersion80 + |> verifyCompile + |> shouldSucceed + + // SOURCE=E_AttributeTargets04.fs # E_AttributeTargets04.fs + [] + let ``E_AttributeTargets04_fs preview`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 842, Line 23, Col 3, Line 23, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 26, Col 3, Line 26, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 29, Col 3, Line 29, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 32, Col 3, Line 32, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 35, Col 3, Line 35, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 38, Col 3, Line 38, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 41, Col 3, Line 41, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 44, Col 3, Line 44, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 47, Col 3, Line 47, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 50, Col 3, Line 50, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 53, Col 3, Line 53, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 64, Col 3, Line 64, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 70, Col 3, Line 70, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 77, Col 3, Line 77, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 83, Col 3, Line 83, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 95, Col 3, Line 95, Col 12, "This attribute is not valid for use on this language element") + ] // SOURCE=E_ConditionalAttribute.fs SCFLAGS="--test:ErrorRanges" # E_ConditionalAttribute.fs [] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs new file mode 100644 index 00000000000..01251168b44 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs @@ -0,0 +1,101 @@ + +open System + +[] +type FieldOnlyAttribute() = + inherit Attribute() + +[] +let someValue = "someValue" + +[] +let i, j, k = (1, 2, 3) // Should fail + +[] +let someRecLetBoundValue = nameof(FieldOnlyAttribute) + +[] +let rec someRecLetBoundValue2 = nameof(someRecLetBoundValue2) + +[] +let ``someValue2`` = "someValue" + +[] +let someFunction () = "someFunction" + +[] +let someFunction2 a = a + 1 + +[] +let someFunction3 (a, b) = a + b + +[] +let someFunction4 (a: int) : int = a + 1 + +[] +let makeList a b = [ a; b ] + +[] +let someTypedFunction<'a> = "someTypedFunction" + +[] +let someTypedFunction2<'a> (x : 'a) = "someTypedFunction2" + +[] +let someTypedFunction3 = fun x -> x + +[] +let someTypedFunction4 = id + +[] +let __someTypedFunction5<'a> = false + +[] +let __someTypedFunction6<'a> : bool = false + +type TestConst = + | Bool of bool + +[] +type TestExpr = + | Const of TestConst * Type * int + | Var of string * Type * int + +[] +let (|BoolExpr|_|) = + function + | TestExpr.Const (TestConst.Bool b, _, _) -> Some b + | _ -> None + +[] +[] +let (|BoolExpr2|_|) = + function + | TestExpr.Const(TestConst.Bool b1, _, _) -> ValueSome b1 + | _ -> ValueNone + +[] +let (|BoolExpr3|_|) x = + match x with + | TestExpr.Const (TestConst.Bool b, _, _) -> Some b + | _ -> None + +[] +[] +let (|BoolExpr4|_|) x = + match x with + | TestExpr.Const(TestConst.Bool b1, _, _) -> ValueSome b1 + | _ -> ValueNone + +let private dangling (target: TestExpr -> TestExpr voption) = + function + | TestExpr.Const (TestConst.Bool _, _, _) as b -> ValueSome b + | _ -> ValueNone + +[] +[] +let (|IfThen|_|) = + dangling (function + | TestExpr.Const(TestConst.Bool b1, _, _) as expr -> ValueSome expr + | _ -> ValueNone) + From 42b6745a34f602f8528eca18d14f42db22cedb35 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Tue, 13 Feb 2024 19:20:31 +0000 Subject: [PATCH 06/15] More tests --- src/Compiler/Checking/CheckExpressions.fs | 9 ++++-- .../AttributeUsage/AttributeUsage.fs | 20 +++++++++++++ .../AttributeUsage/E_AttributeTargets05.fs | 28 +++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 9b12d80692a..081a27153ab 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10556,8 +10556,13 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt | _, _, _ -> envinner.eCallerMemberName let envinner = {envinner with eCallerMemberName = callerName } + let isInstance = + match memberFlagsOpt with + | Some memberFlags -> memberFlags.IsInstance + | _ -> false + let attrTgt = - if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnFunctions) then + if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnFunctions) && not isInstance then let supportsNameofFeature = g.langVersion.SupportsFeature(LanguageFeature.NameOf) let rhsExprIsFunction = match rhsExpr with @@ -10569,7 +10574,7 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt | _ -> false match pat with - | SynPat.Tuple _ when not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue + | SynPat.Tuple _ when not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.ReturnValue | SynPat.Named _ when spatsL.IsEmpty && declaredTypars.IsEmpty && not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue | _ -> AttributeTargets.Method ||| AttributeTargets.ReturnValue else 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 ba2164932c5..392d1705766 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -151,6 +151,26 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 83, Col 3, Line 83, Col 12, "This attribute is not valid for use on this language element") (Error 842, Line 95, Col 3, Line 95, Col 12, "This attribute is not valid for use on this language element") ] + + // SOURCE=E_AttributeTargets05.fs # E_AttributeTargets05.fs + [] + let ``E_AttributeTargets05_fs`` compilation = + compilation + |> withLangVersion80 + |> verifyCompile + |> shouldSucceed + + // SOURCE=E_AttributeTargets05.fs # E_AttributeTargets05.fs + [] + let ``E_AttributeTargets05_fs preview`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 842, Line 20, Col 6, Line 20, Col 15, "This attribute is not valid for use on this language element"); + (Error 842, Line 23, Col 6, Line 23, Col 16, "This attribute is not valid for use on this language element") + ] // SOURCE=E_ConditionalAttribute.fs SCFLAGS="--test:ErrorRanges" # E_ConditionalAttribute.fs [] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs new file mode 100644 index 00000000000..5c54560736e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs @@ -0,0 +1,28 @@ + +open System +open System.Diagnostics + +[] +type FieldOnlyAttribute() = + inherit Attribute() + +[] +type MethodOnlyAttribute() = + inherit Attribute() + +type Test() = + [] + let mutable value = 0 + + [] + let myFunction() = () + + [] + let myFunction2 () = () + + [] + let value2 = 0 + + [] + member this.IsNone = match 0 with 1 -> true | _ -> false + From c532bc360b0e30a5a3937b13158a1458e5004d75 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Tue, 13 Feb 2024 20:27:51 +0000 Subject: [PATCH 07/15] More tests --- src/Compiler/Checking/CheckExpressions.fs | 7 +------ .../AttributeUsage/E_AttributeTargets05.fs | 3 +++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 081a27153ab..df70f5f3c07 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10556,13 +10556,8 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt | _, _, _ -> envinner.eCallerMemberName let envinner = {envinner with eCallerMemberName = callerName } - let isInstance = - match memberFlagsOpt with - | Some memberFlags -> memberFlags.IsInstance - | _ -> false - let attrTgt = - if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnFunctions) && not isInstance then + if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnFunctions) && memberFlagsOpt.IsNone then let supportsNameofFeature = g.langVersion.SupportsFeature(LanguageFeature.NameOf) let rhsExprIsFunction = match rhsExpr with diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs index 5c54560736e..c566161186f 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs @@ -26,3 +26,6 @@ type Test() = [] member this.IsNone = match 0 with 1 -> true | _ -> false + [] + static member None = None + From 6f82303aca043b914f337169fb4e9431056d976a Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 14 Feb 2024 14:45:26 +0000 Subject: [PATCH 08/15] More tests --- .../AttributeUsage/AttributeUsage.fs | 12 ++++++- .../AttributeUsage/E_AttributeTargets03.fs | 7 ++++ .../AttributeUsage/E_AttributeTargets04.fs | 7 ++++ .../AttributeUsage/E_AttributeTargets05.fs | 32 +++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) 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 392d1705766..5652fdc786b 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -116,6 +116,8 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 14, Col 3, Line 14, Col 13, "This attribute is not valid for use on this language element") (Error 842, Line 17, Col 3, Line 17, Col 13, "This attribute is not valid for use on this language element") (Error 842, Line 20, Col 3, Line 20, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 102, Col 3, Line 102, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 106, Col 3, Line 106, Col 13, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargets04.fs # E_AttributeTargets04.fs @@ -150,6 +152,8 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 77, Col 3, Line 77, Col 12, "This attribute is not valid for use on this language element") (Error 842, Line 83, Col 3, Line 83, Col 12, "This attribute is not valid for use on this language element") (Error 842, Line 95, Col 3, Line 95, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 104, Col 7, Line 104, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 108, Col 7, Line 108, Col 16, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargets05.fs # E_AttributeTargets05.fs @@ -168,8 +172,14 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 20, Col 6, Line 20, Col 15, "This attribute is not valid for use on this language element"); + (Error 842, Line 20, Col 6, Line 20, Col 15, "This attribute is not valid for use on this language element") (Error 842, Line 23, Col 6, Line 23, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 32, Col 6, Line 32, Col 15, "This attribute is not valid for use on this language element") + (Error 842, Line 35, Col 6, Line 35, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 38, Col 6, Line 38, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 40, Col 10, Line 40, Col 19, "This attribute is not valid for use on this language element") + (Error 842, Line 52, Col 6, Line 52, Col 15, "This attribute is not valid for use on this language element") + (Error 842, Line 55, Col 6, Line 55, Col 16, "This attribute is not valid for use on this language element") ] // SOURCE=E_ConditionalAttribute.fs SCFLAGS="--test:ErrorRanges" # E_ConditionalAttribute.fs diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs index 6a9785ef695..8c5db122cba 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs @@ -99,3 +99,10 @@ let (|IfThen|_|) = | TestExpr.Const(TestConst.Bool b1, _, _) as expr -> ValueSome expr | _ -> ValueNone) +[] +let rec f = 0 +and [] g() = [] + +[] +let rec f1 = 0 +and [] g2() = [] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs index 01251168b44..ee8fe43c60a 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs @@ -99,3 +99,10 @@ let (|IfThen|_|) = | TestExpr.Const(TestConst.Bool b1, _, _) as expr -> ValueSome expr | _ -> ValueNone) +[] +let rec f = 0 +and [] g() = [] + +[] +let rec f1 = 0 +and [] g2() = [] \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs index c566161186f..51ee9ba5b43 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs @@ -22,6 +22,38 @@ type Test() = [] let value2 = 0 + + [] + static let value3 = 0 + + [] + static let myFunction3 () = () + + [] + static let myFunction4 () = () + + [] + static let value4 = 0 + + [] + let rec f = 0 + and [] g() = [] + + [] + let rec f1 = 0 + and [] g2() = [] + + [] + static let rec value5 = 0 + + [] + static let rec myFunction5() = () + + [] + static let rec myFunction6() = 0 + + [] + static let rec value6 = () [] member this.IsNone = match 0 with 1 -> true | _ -> false From d24c55e05cd9e74085e43390d2152e3a35686d3f Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 14 Feb 2024 16:24:40 +0000 Subject: [PATCH 09/15] Simplify check --- src/Compiler/Checking/CheckExpressions.fs | 32 +++++++++++++---------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index df70f5f3c07..792fbf04ffd 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10558,20 +10558,24 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt let envinner = {envinner with eCallerMemberName = callerName } let attrTgt = if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnFunctions) && memberFlagsOpt.IsNone then - let supportsNameofFeature = g.langVersion.SupportsFeature(LanguageFeature.NameOf) - let rhsExprIsFunction = - match rhsExpr with - | SynExpr.Lambda _ - | SynExpr.Match _ - | SynExpr.MatchLambda _ -> true - | SynExpr.App(funcExpr = SynExpr.Ident(ident)) when supportsNameofFeature && ident.idText <> "nameof" -> true - | SynExpr.Ident ident when ident.idText = "id" -> true - | _ -> false - - match pat with - | SynPat.Tuple _ when not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.ReturnValue - | SynPat.Named _ when spatsL.IsEmpty && declaredTypars.IsEmpty && not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue - | _ -> AttributeTargets.Method ||| AttributeTargets.ReturnValue + match declKind with + | ModuleOrMemberBinding + | ClassLetBinding _ -> + let supportsNameofFeature = g.langVersion.SupportsFeature(LanguageFeature.NameOf) + let rhsExprIsFunction = + match rhsExpr with + | SynExpr.Lambda _ + | SynExpr.Match _ + | SynExpr.MatchLambda _ -> true + | SynExpr.App(funcExpr = SynExpr.Ident(ident)) when supportsNameofFeature && ident.idText <> "nameof" -> true + | SynExpr.Ident ident when ident.idText = "id" -> true + | _ -> false + + match pat with + | SynPat.Tuple _ + | SynPat.Named _ when spatsL.IsEmpty && declaredTypars.IsEmpty && not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.ReturnValue + | _ -> AttributeTargets.Method ||| AttributeTargets.ReturnValue + | _ -> declKind.AllowedAttribTargets memberFlagsOpt else declKind.AllowedAttribTargets memberFlagsOpt From 1956d417c30b99b7956ca6cb872bd1c23554d721 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 14 Feb 2024 16:24:56 +0000 Subject: [PATCH 10/15] Update release notes --- docs/release-notes/.FSharp.Compiler.Service/8.0.300.md | 1 + docs/release-notes/.Language/preview.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md index 672209d2ed1..c27d4d317f8 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md @@ -11,6 +11,7 @@ * `[]` member should not produce property symbol. ([Issue #16640](https://github.com/dotnet/fsharp/issues/16640), [PR #16658](https://github.com/dotnet/fsharp/pull/16658)) * Fix discriminated union initialization. ([#PR 16661](https://github.com/dotnet/fsharp/pull/16661)) * Allow calling method with both Optional and ParamArray. ([#PR 16688](https://github.com/dotnet/fsharp/pull/16688), [suggestions #1120](https://github.com/fsharp/fslang-suggestions/issues/1120)) +* Enforce AttributeTargets on let values and functions. ([PR #16692](https://github.com/dotnet/fsharp/pull/16692)) ### Added diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index 832dd924a44..238f6c9ce76 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -8,3 +8,4 @@ ### Fixed * Allow extension methods without type attribute work for types from imported assemblies. ([PR #16368](https://github.com/dotnet/fsharp/pull/16368)) +* Enforce AttributeTargets on let values and functions. ([PR #16692](https://github.com/dotnet/fsharp/pull/16692)) From 1bff6c7bf7883b9e719cb070b0d1d69dbdc44fbb Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 14 Feb 2024 16:54:32 +0000 Subject: [PATCH 11/15] ValueAsStaticProperty --- src/Compiler/Checking/CheckExpressions.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 792fbf04ffd..1850f780c42 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10573,7 +10573,7 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt match pat with | SynPat.Tuple _ - | SynPat.Named _ when spatsL.IsEmpty && declaredTypars.IsEmpty && not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.ReturnValue + | SynPat.Named _ when spatsL.IsEmpty && declaredTypars.IsEmpty && not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue | _ -> AttributeTargets.Method ||| AttributeTargets.ReturnValue | _ -> declKind.AllowedAttribTargets memberFlagsOpt else From 40190e034d9104656212e818f1378b83804aa627 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 21 Feb 2024 16:45:33 +0000 Subject: [PATCH 12/15] use more reliable check --- src/Compiler/Checking/CheckExpressions.fs | 35 ++++++++--------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 1850f780c42..1adacab81c1 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -10555,29 +10555,8 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt | ModuleOrMemberBinding, SynBindingKind.StandaloneExpression, _ -> Some(".cctor") | _, _, _ -> envinner.eCallerMemberName - let envinner = {envinner with eCallerMemberName = callerName } - let attrTgt = - if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnFunctions) && memberFlagsOpt.IsNone then - match declKind with - | ModuleOrMemberBinding - | ClassLetBinding _ -> - let supportsNameofFeature = g.langVersion.SupportsFeature(LanguageFeature.NameOf) - let rhsExprIsFunction = - match rhsExpr with - | SynExpr.Lambda _ - | SynExpr.Match _ - | SynExpr.MatchLambda _ -> true - | SynExpr.App(funcExpr = SynExpr.Ident(ident)) when supportsNameofFeature && ident.idText <> "nameof" -> true - | SynExpr.Ident ident when ident.idText = "id" -> true - | _ -> false - - match pat with - | SynPat.Tuple _ - | SynPat.Named _ when spatsL.IsEmpty && declaredTypars.IsEmpty && not rhsExprIsFunction -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue - | _ -> AttributeTargets.Method ||| AttributeTargets.ReturnValue - | _ -> declKind.AllowedAttribTargets memberFlagsOpt - else - declKind.AllowedAttribTargets memberFlagsOpt + let envinner = { envinner with eCallerMemberName = callerName } + let attrTgt = declKind.AllowedAttribTargets memberFlagsOpt let isFixed, rhsExpr, overallPatTy, overallExprTy = match rhsExpr with @@ -10812,6 +10791,16 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt errorR(Error(FSComp.SR.tcLiteralCannotBeInline(), mBinding)) if not (isNil declaredTypars) then errorR(Error(FSComp.SR.tcLiteralCannotHaveGenericParameters(), mBinding)) + + if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnFunctions) && memberFlagsOpt.IsNone && not attrs.IsEmpty then + let rhsIsFunction = isFunTy g overallPatTy + let lhsIsFunction = isFunTy g overallExprTy + let attrTgt = + match rhsIsFunction, lhsIsFunction with + | false, false when declaredTypars.IsEmpty -> AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue + | _, _ -> AttributeTargets.Method ||| AttributeTargets.ReturnValue + + TcAttributesWithPossibleTargets false cenv env attrTgt attrs |> ignore CheckedBindingInfo(inlineFlag, valAttribs, xmlDoc, tcPatPhase2, explicitTyparInfo, nameToPrelimValSchemeMap, rhsExprChecked, argAndRetAttribs, overallPatTy, mBinding, debugPoint, isCompGen, literalValue, isFixed), tpenv From 2bc5316ada205667d8c2113241e98783921b00d7 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 21 Feb 2024 21:03:14 +0000 Subject: [PATCH 13/15] more tests --- .../AttributeUsage/AttributeUsage.fs | 8 ++++++++ .../AttributeUsage/E_AttributeTargets03.fs | 14 ++++++++++++++ .../AttributeUsage/E_AttributeTargets04.fs | 16 +++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) 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 5652fdc786b..30325519fc4 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -100,6 +100,7 @@ module CustomAttributes_AttributeUsage = let ``E_AttributeTargets03_fs`` compilation = compilation |> withLangVersion80 + |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldSucceed @@ -108,6 +109,7 @@ module CustomAttributes_AttributeUsage = let ``E_AttributeTargets03_fs preview`` compilation = compilation |> withLangVersionPreview + |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldFail |> withDiagnostics [ @@ -118,6 +120,10 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 20, Col 3, Line 20, Col 13, "This attribute is not valid for use on this language element") (Error 842, Line 102, Col 3, Line 102, Col 13, "This attribute is not valid for use on this language element") (Error 842, Line 106, Col 3, Line 106, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 110, Col 3, Line 110, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 113, Col 3, Line 113, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 116, Col 3, Line 116, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 121, Col 3, Line 121, Col 13, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargets04.fs # E_AttributeTargets04.fs @@ -125,6 +131,7 @@ module CustomAttributes_AttributeUsage = let ``E_AttributeTargets04_fs`` compilation = compilation |> withLangVersion80 + |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldSucceed @@ -133,6 +140,7 @@ module CustomAttributes_AttributeUsage = let ``E_AttributeTargets04_fs preview`` compilation = compilation |> withLangVersionPreview + |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldFail |> withDiagnostics [ diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs index 8c5db122cba..8e120dad9a0 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs @@ -106,3 +106,17 @@ and [] g() = [] [] let rec f1 = 0 and [] g2() = [] + +[] +let (a :: _) = [] + +[] +let (d, e) as foo = 1, 2 + +[] +let 1 = 0 + +type X = { X: int } + +[] +let { X = _ } = { X = 1 } diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs index ee8fe43c60a..a45c5931d11 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs @@ -105,4 +105,18 @@ and [] g() = [] [] let rec f1 = 0 -and [] g2() = [] \ No newline at end of file +and [] g2() = [] + +[] +let (a :: _) = [] + +[] +let (d, e) as foo = 1, 2 + +[] +let 1 = 0 + +type X = { X: int } + +[] +let { X = _ } = { X = 1 } \ No newline at end of file From 8c9015b99e9168ff40794b31a2a63d884b18b835 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Thu, 22 Feb 2024 15:19:32 +0000 Subject: [PATCH 14/15] Improve tests --- .../AttributeUsage/AttributeUsage.fs | 156 ++++++++++++------ .../E_AttributeTargetIsField01.fs | 67 ++++++++ .../E_AttributeTargetIsField02.fs | 69 ++++++++ .../E_AttributeTargetIsMethod02.fs | 40 +++++ .../E_AttributeTargetIsMethod03.fs | 54 ++++++ .../AttributeUsage/E_AttributeTargets03.fs | 122 -------------- .../AttributeUsage/E_AttributeTargets04.fs | 122 -------------- .../AttributeUsage/E_AttributeTargets05.fs | 63 ------- 8 files changed, 331 insertions(+), 362 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField01.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField02.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod02.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod03.fs delete mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs delete mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs delete mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs 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 30325519fc4..c7861ee3e56 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -95,99 +95,145 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 29, Col 15, Line 29, Col 47, "This attribute is not valid for use on this language element") ] - // SOURCE=E_AttributeTargets03.fs # E_AttributeTargets03.fs - [] - let ``E_AttributeTargets03_fs`` compilation = + // SOURCE=E_AttributeTargetIsField01.fs # E_AttributeTargetIsField01.fs + [] + let ``E_AttributeTargetIsField01_fs`` compilation = compilation |> withLangVersion80 |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldSucceed - // SOURCE=E_AttributeTargets03.fs # E_AttributeTargets03.fs - [] - let ``E_AttributeTargets03_fs preview`` compilation = + // SOURCE=E_AttributeTargetIsField01.fs # E_AttributeTargetIsField01.fs + [] + let ``E_AttributeTargetIsField01_fs preview`` compilation = compilation |> withLangVersionPreview |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 8, Col 3, Line 8, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 11, Col 3, Line 11, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 14, Col 3, Line 14, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 17, Col 3, Line 17, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 20, Col 3, Line 20, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 102, Col 3, Line 102, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 106, Col 3, Line 106, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 110, Col 3, Line 110, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 113, Col 3, Line 113, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 116, Col 3, Line 116, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 121, Col 3, Line 121, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 9, Col 3, Line 9, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 12, Col 3, Line 12, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 15, Col 3, Line 15, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 18, Col 3, Line 18, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 21, Col 3, Line 21, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 24, Col 3, Line 24, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 27, Col 3, Line 27, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 30, Col 3, Line 30, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 33, Col 3, Line 33, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 36, Col 3, Line 36, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 39, Col 3, Line 39, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 42, Col 3, Line 42, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 45, Col 3, Line 45, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 49, Col 3, Line 49, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 56, Col 3, Line 56, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 64, Col 3, Line 64, Col 12, "This attribute is not valid for use on this language element") + (Error 842, Line 66, Col 7, Line 66, Col 16, "This attribute is not valid for use on this language element") ] - // SOURCE=E_AttributeTargets04.fs # E_AttributeTargets04.fs - [] - let ``E_AttributeTargets04_fs`` compilation = + // SOURCE=E_AttributeTargetIsField02.fs # E_AttributeTargetIsField02.fs + [] + let ``E_AttributeTargetIsField02_fs`` compilation = compilation |> withLangVersion80 |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldSucceed - // SOURCE=E_AttributeTargets04.fs # E_AttributeTargets04.fs - [] - let ``E_AttributeTargets04_fs preview`` compilation = + // SOURCE=E_AttributeTargetIsField02.fs # E_AttributeTargetIsField02.fs + [] + let ``E_AttributeTargetIsField02_fs preview`` compilation = compilation |> withLangVersionPreview |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 23, Col 3, Line 23, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 26, Col 3, Line 26, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 29, Col 3, Line 29, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 32, Col 3, Line 32, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 35, Col 3, Line 35, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 38, Col 3, Line 38, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 41, Col 3, Line 41, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 44, Col 3, Line 44, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 47, Col 3, Line 47, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 50, Col 3, Line 50, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 53, Col 3, Line 53, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 64, Col 3, Line 64, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 70, Col 3, Line 70, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 77, Col 3, Line 77, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 83, Col 3, Line 83, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 95, Col 3, Line 95, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 104, Col 7, Line 104, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 108, Col 7, Line 108, Col 16, "This attribute is not valid for use on this language element") + (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") + ] + + // SOURCE=E_AttributeTargetIsMethod02.fs # E_AttributeTargetIsMethod02.fs + [] + let ``E_AttributeTargetIsMethod02_fs`` compilation = + compilation + |> withLangVersion80 + |> withOptions ["--nowarn:25"] + |> verifyCompile + |> shouldSucceed + + // SOURCE=E_AttributeTargetIsMethod02.fs # E_AttributeTargetIsMethod02.fs + [] + let ``E_AttributeTargetIsMethod02_fs preview`` compilation = + compilation + |> withLangVersionPreview + |> withOptions ["--nowarn:25"] + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 842, Line 9, Col 3, Line 9, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 12, Col 3, Line 12, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 15, Col 3, Line 15, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 18, Col 3, Line 18, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 21, Col 3, Line 21, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 24, Col 3, Line 24, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 26, Col 7, Line 26, Col 17, "This attribute is not valid for use on this language element") + (Error 842, Line 28, Col 3, Line 28, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 31, Col 3, Line 31, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 34, Col 3, Line 34, Col 13, "This attribute is not valid for use on this language element") + (Error 842, Line 39, Col 3, Line 39, Col 13, "This attribute is not valid for use on this language element") ] - // SOURCE=E_AttributeTargets05.fs # E_AttributeTargets05.fs - [] - let ``E_AttributeTargets05_fs`` compilation = + // SOURCE=E_AttributeTargetIsMethod03.fs # E_AttributeTargetIsMethod03.fs + [] + let ``E_AttributeTargetIsMethod03_fs`` compilation = compilation |> withLangVersion80 + |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldSucceed - // SOURCE=E_AttributeTargets05.fs # E_AttributeTargets05.fs - [] - let ``E_AttributeTargets05_fs preview`` compilation = + // SOURCE=E_AttributeTargetIsMethod03.fs # E_AttributeTargetIsMethod03.fs + [] + let ``E_AttributeTargetIsMethod03_fs preview`` compilation = compilation |> withLangVersionPreview + |> withOptions ["--nowarn:25"] |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 20, Col 6, Line 20, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 23, Col 6, Line 23, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 32, Col 6, Line 32, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 35, Col 6, Line 35, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 38, Col 6, Line 38, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 40, Col 10, Line 40, Col 19, "This attribute is not valid for use on this language element") - (Error 842, Line 52, Col 6, Line 52, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 55, Col 6, Line 55, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 12, Col 6, Line 12, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 15, Col 6, Line 15, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 18, Col 6, Line 18, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 20, Col 10, Line 20, Col 20, "This attribute is not valid for use on this language element") + (Error 842, Line 22, Col 6, Line 22, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 25, Col 6, Line 25, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 28, Col 6, Line 28, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 31, Col 6, Line 31, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 34, Col 6, Line 34, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 37, Col 6, Line 37, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 39, Col 10, Line 39, Col 20, "This attribute is not valid for use on this language element") + (Error 842, Line 41, Col 6, Line 41, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 44, Col 6, Line 44, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 47, Col 6, Line 47, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 52, Col 6, Line 52, Col 16, "This attribute is not valid for use on this language element") ] // SOURCE=E_ConditionalAttribute.fs SCFLAGS="--test:ErrorRanges" # E_ConditionalAttribute.fs diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField01.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField01.fs new file mode 100644 index 00000000000..1e3e48516c9 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField01.fs @@ -0,0 +1,67 @@ +// This tests that AttributeTargets.Field is not allowed in let function bindings + +open System + +[] +type FieldOnlyAttribute() = + inherit Attribute() + +[] // Should fail +let func1 () = "someFunction" + +[] // Should fail +let func2 a = a + 1 + +[] // Should fail +let func3 (a, b) = a + b + +[] // Should fail +let func4 (a: int) : int = a + 1 + +[] // Should fail +let func5 a b = [ a; b ] + +[] // Should fail +let func6<'a> = "someTypedFunction" + +[] // Should fail +let func7<'a> (x : 'a) = "someTypedFunction2" + +[] // Should fail +let func8 = fun x -> x + +[] // Should fail +let func9 = id + +[] // Should fail +let __func10<'a> = false + +[] // Should fail +let __func11<'a> : bool = false + +[] // Should fail +let (|Bool|_|) = function "true" -> Some true | "false" -> Some false | _ -> None + +[] // Should fail +[] +let (|BoolExpr2|_|) = function "true" -> ValueSome true | "false" -> ValueSome false | _ -> ValueNone + +[] // Should fail +let (|BoolExpr3|_|) x = + match x with + | "true" -> Some true + | "false" -> Some false + | _ -> None + +[] // Should fail +[] +let (|BoolExpr4|_|) x = + match x with + | "true" -> ValueSome true + | "false" -> ValueSome false + | _ -> ValueNone + +[] // Should fail +let rec func12() = 0 +and [] func13() = [] // Should fail + 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 new file mode 100644 index 00000000000..c7ba6dda24f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsField02.fs @@ -0,0 +1,69 @@ +// This tests that AttributeTargets.Field is not allowed in class let function bindings + +open System +open System.Diagnostics + +[] +type FieldOnlyAttribute() = + inherit Attribute() + +type TestClass() = + [] // Should fail + static let func1() = "someFunction" + + [] // Should fail + static let rec func2() = "someFunction" + + []// Should fail + static let rec func3() = "someFunction" + and [] fun4() = "someFunction" // Should fail + + [] // Should fail + let func5 () = "someFunction" + + [] // Should fail + let func6 a = a + 1 + + [] // Should fail + let func7 (a, b) = a + b + + [] // Should fail + let func8 (a: int) : int = a + 1 + + [] // Should fail + let func9 a b = [ a; b ] + + [] // Should fail + let func10 = fun x -> x + + [] // Should fail + let func11 = id + + [] // Should fail + let (|Bool|_|) = function "true" -> Some true | "false" -> Some false | _ -> None + + [] // Should fail + [] + let (|BoolExpr2|_|) = function "true" -> ValueSome true | "false" -> ValueSome false | _ -> ValueNone + + [] // Should fail + let (|BoolExpr3|_|) x = + match x with + | "true" -> Some true + | "false" -> Some false + | _ -> None + + [] // Should fail + [] + let (|BoolExpr4|_|) x = + match x with + | "true" -> ValueSome true + | "false" -> ValueSome false + | _ -> ValueNone + + [] // Should fail + let rec func12() = 0 + and [] func13() = [] // Should fail + + [] // Should fail + let rec func14() = 0 \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod02.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod02.fs new file mode 100644 index 00000000000..8687a9b1d0c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod02.fs @@ -0,0 +1,40 @@ +// This tests that AttributeTargets.Method is not allowed in let bound values + +open System + +[] +type MethodOnlyAttribute() = + inherit Attribute() + +[] // Should fail +let val1 = "someValue" + +[] // Should fail +let i, j, k = (1, 2, 3) + +[] // Should fail +let val2 = nameof(MethodOnlyAttribute) + +[] // Should fail +let rec val3 = nameof(val2) + +[] // Should fail +let ``val4`` = "someValue" + +[] // Should fail +let rec val5 = 0 +and [] val6 = [] // Should fail + +[] // Should fail +let (a :: _) = [] + +[] // Should fail +let (d, e) as val7 = 1, 2 + +[] // Should fail +let 1 = 0 + +type X = { X: int } + +[] // Should fail +let { X = _ } = { X = 1 } diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod03.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod03.fs new file mode 100644 index 00000000000..c60ecae32b2 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod03.fs @@ -0,0 +1,54 @@ +// This tests that AttributeTargets.Method is not allowed in class let bound values + +open System +open System.Diagnostics + +[] +type MethodOnlyAttribute() = + inherit Attribute() + +type TestClass() = + + [] // Should fail + static let val1 = "someValue" + + [] // Should fail + static let rec val2 = "someValue" + + [] // Should fail + static let rec val3 = "someValue" + and [] val4 = "someValue" // Should fail + + [] // Should fail + let val5 = "someValue" + + [] // Should fail + let i, j, k = (1, 2, 3) + + [] // Should fail + let val5 = nameof(MethodOnlyAttribute) + + [] // Should fail + let rec val6 = nameof(val5) + + [] // Should fail + let ``val7`` = "someValue" + + [] // Should fail + let rec val8 = 0 + and [] val9 = [] // Should fail + + [] // Should fail + let (a :: _) = [] + + [] // Should fail + let (d, e) as foo = 1, 2 + + [] // Should fail + let 1 = 0 + + type X = { X: int } + + [] // Should fail + let { X = _ } = { X = 1 } + diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs deleted file mode 100644 index 8e120dad9a0..00000000000 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets03.fs +++ /dev/null @@ -1,122 +0,0 @@ - -open System - -[] -type MethodOnlyAttribute() = - inherit Attribute() - -[] -let someValue = "someValue" // Should fail - -[] -let i, j, k = (1, 2, 3) // Should fail - -[] -let someRecLetBoundValue = nameof(MethodOnlyAttribute) // Should fail - -[] -let rec someRecLetBoundValue2 = nameof(someRecLetBoundValue2) // Should fail - -[] -let ``someValue2`` = "someValue" // Should fail - -[] -let someFunction () = "someFunction" - -[] -let someFunction2 a = a + 1 - -[] -let someFunction3 (a, b) = a + b - -[] -let someFunction4 (a: int) : int = a + 1 - -[] -let makeList a b = [ a; b ] - -[] -let someTypedFunction<'a> = "someTypedFunction" - -[] -let someTypedFunction2<'a> (x : 'a) = "someTypedFunction2" - -[] -let someTypedFunction3 = fun x -> x - -[] -let someTypedFunction4 = id - -[] -let __someTypedFunction5<'a> = false - -[] -let __someTypedFunction6<'a> : bool = false - -type TestConst = - | Bool of bool - -[] -type TestExpr = - | Const of TestConst * Type * int - | Var of string * Type * int - -[] -let (|BoolExpr|_|) = - function - | TestExpr.Const (TestConst.Bool b, _, _) -> Some b - | _ -> None - -[] -[] -let (|BoolExpr2|_|) = - function - | TestExpr.Const(TestConst.Bool b1, _, _) -> ValueSome b1 - | _ -> ValueNone - -[] -let (|BoolExpr3|_|) x = - match x with - | TestExpr.Const (TestConst.Bool b, _, _) -> Some b - | _ -> None - -[] -[] -let (|BoolExpr4|_|) x = - match x with - | TestExpr.Const(TestConst.Bool b1, _, _) -> ValueSome b1 - | _ -> ValueNone - -let private dangling (target: TestExpr -> TestExpr voption) = - function - | TestExpr.Const (TestConst.Bool _, _, _) as b -> ValueSome b - | _ -> ValueNone - -[] -[] -let (|IfThen|_|) = - dangling (function - | TestExpr.Const(TestConst.Bool b1, _, _) as expr -> ValueSome expr - | _ -> ValueNone) - -[] -let rec f = 0 -and [] g() = [] - -[] -let rec f1 = 0 -and [] g2() = [] - -[] -let (a :: _) = [] - -[] -let (d, e) as foo = 1, 2 - -[] -let 1 = 0 - -type X = { X: int } - -[] -let { X = _ } = { X = 1 } diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs deleted file mode 100644 index a45c5931d11..00000000000 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets04.fs +++ /dev/null @@ -1,122 +0,0 @@ - -open System - -[] -type FieldOnlyAttribute() = - inherit Attribute() - -[] -let someValue = "someValue" - -[] -let i, j, k = (1, 2, 3) // Should fail - -[] -let someRecLetBoundValue = nameof(FieldOnlyAttribute) - -[] -let rec someRecLetBoundValue2 = nameof(someRecLetBoundValue2) - -[] -let ``someValue2`` = "someValue" - -[] -let someFunction () = "someFunction" - -[] -let someFunction2 a = a + 1 - -[] -let someFunction3 (a, b) = a + b - -[] -let someFunction4 (a: int) : int = a + 1 - -[] -let makeList a b = [ a; b ] - -[] -let someTypedFunction<'a> = "someTypedFunction" - -[] -let someTypedFunction2<'a> (x : 'a) = "someTypedFunction2" - -[] -let someTypedFunction3 = fun x -> x - -[] -let someTypedFunction4 = id - -[] -let __someTypedFunction5<'a> = false - -[] -let __someTypedFunction6<'a> : bool = false - -type TestConst = - | Bool of bool - -[] -type TestExpr = - | Const of TestConst * Type * int - | Var of string * Type * int - -[] -let (|BoolExpr|_|) = - function - | TestExpr.Const (TestConst.Bool b, _, _) -> Some b - | _ -> None - -[] -[] -let (|BoolExpr2|_|) = - function - | TestExpr.Const(TestConst.Bool b1, _, _) -> ValueSome b1 - | _ -> ValueNone - -[] -let (|BoolExpr3|_|) x = - match x with - | TestExpr.Const (TestConst.Bool b, _, _) -> Some b - | _ -> None - -[] -[] -let (|BoolExpr4|_|) x = - match x with - | TestExpr.Const(TestConst.Bool b1, _, _) -> ValueSome b1 - | _ -> ValueNone - -let private dangling (target: TestExpr -> TestExpr voption) = - function - | TestExpr.Const (TestConst.Bool _, _, _) as b -> ValueSome b - | _ -> ValueNone - -[] -[] -let (|IfThen|_|) = - dangling (function - | TestExpr.Const(TestConst.Bool b1, _, _) as expr -> ValueSome expr - | _ -> ValueNone) - -[] -let rec f = 0 -and [] g() = [] - -[] -let rec f1 = 0 -and [] g2() = [] - -[] -let (a :: _) = [] - -[] -let (d, e) as foo = 1, 2 - -[] -let 1 = 0 - -type X = { X: int } - -[] -let { X = _ } = { X = 1 } \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs deleted file mode 100644 index 51ee9ba5b43..00000000000 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargets05.fs +++ /dev/null @@ -1,63 +0,0 @@ - -open System -open System.Diagnostics - -[] -type FieldOnlyAttribute() = - inherit Attribute() - -[] -type MethodOnlyAttribute() = - inherit Attribute() - -type Test() = - [] - let mutable value = 0 - - [] - let myFunction() = () - - [] - let myFunction2 () = () - - [] - let value2 = 0 - - [] - static let value3 = 0 - - [] - static let myFunction3 () = () - - [] - static let myFunction4 () = () - - [] - static let value4 = 0 - - [] - let rec f = 0 - and [] g() = [] - - [] - let rec f1 = 0 - and [] g2() = [] - - [] - static let rec value5 = 0 - - [] - static let rec myFunction5() = () - - [] - static let rec myFunction6() = 0 - - [] - static let rec value6 = () - - [] - member this.IsNone = match 0 with 1 -> true | _ -> false - - [] - static member None = None - From ee83bd01be97f405ab25a96d983ea440578dd28f Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Fri, 23 Feb 2024 16:30:52 +0000 Subject: [PATCH 15/15] Update Lang preview release notes --- docs/release-notes/.Language/preview.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index 238f6c9ce76..b0330c15448 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -9,3 +9,7 @@ * Allow extension methods without type attribute work for types from imported assemblies. ([PR #16368](https://github.com/dotnet/fsharp/pull/16368)) * Enforce AttributeTargets on let values and functions. ([PR #16692](https://github.com/dotnet/fsharp/pull/16692)) + +### Changed + +* Lower interpolated strings to string concatenation. ([PR #16556](https://github.com/dotnet/fsharp/pull/16556)) \ No newline at end of file