diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md index 7765f188e0e..bccd5a0d762 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md @@ -20,7 +20,7 @@ * Generate new `Equals` overload to avoid boxing for structural comparison ([PR #16857](https://github.com/dotnet/fsharp/pull/16857)) ### Changed - +* Enforce `AttributeTargets.Interface` ([PR #17173](https://github.com/dotnet/fsharp/pull/17173)) * Minor compiler perf improvements. ([PR #17130](https://github.com/dotnet/fsharp/pull/17130)) * Improve error of Active Pattern case Argument Count Not Match ([PR #16846](https://github.com/dotnet/fsharp/pull/16846)) * AsyncLocal diagnostics context. ([PR #16779](https://github.com/dotnet/fsharp/pull/16779)) diff --git a/docs/release-notes/.FSharp.Core/8.0.400.md b/docs/release-notes/.FSharp.Core/8.0.400.md index 48a05231dc9..ee24d8d0a53 100644 --- a/docs/release-notes/.FSharp.Core/8.0.400.md +++ b/docs/release-notes/.FSharp.Core/8.0.400.md @@ -5,3 +5,4 @@ ### Changed * Cache delegate in query extensions. ([PR #17130](https://github.com/dotnet/fsharp/pull/17130)) +* Update `AllowNullLiteralAttribute` to also use `AttributeTargets.Interface` ([PR #17173](https://github.com/dotnet/fsharp/pull/17173)) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 1736132abe8..be083e74871 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -2912,7 +2912,10 @@ module EstablishTypeDefinitionCores = if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) then TcAttributesWithPossibleTargets false cenv envinner AttributeTargets.Class synAttrs |> ignore TFSharpClass - | SynTypeDefnKind.Interface -> TFSharpInterface + | SynTypeDefnKind.Interface -> + if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) then + TcAttributesWithPossibleTargets false cenv envinner AttributeTargets.Interface synAttrs |> ignore + TFSharpInterface | SynTypeDefnKind.Delegate _ -> if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) then TcAttributesWithPossibleTargets false cenv envinner AttributeTargets.Delegate synAttrs |> ignore diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs index 245a83380f5..556fb1bcde5 100644 --- a/src/FSharp.Core/prim-types.fs +++ b/src/FSharp.Core/prim-types.fs @@ -76,7 +76,7 @@ namespace Microsoft.FSharp.Core type ComparisonConditionalOnAttribute() = inherit Attribute() - [] + [] [] type AllowNullLiteralAttribute(value: bool) = inherit Attribute() diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi index e7ceb9b6166..dee677aac31 100644 --- a/src/FSharp.Core/prim-types.fsi +++ b/src/FSharp.Core/prim-types.fsi @@ -263,7 +263,7 @@ namespace Microsoft.FSharp.Core /// interface types. /// /// Attributes - [] + [] [] type AllowNullLiteralAttribute = inherit Attribute diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsInterface.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsInterface.fs new file mode 100644 index 00000000000..028bd8979f4 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsInterface.fs @@ -0,0 +1,17 @@ +open System + +[] +type CustomInterfaceAttribute() = + inherit Attribute() + +[] +type IFoo = interface end + +[] +type IFoo2 = + abstract A :int + +[] +[] +type IFoo3 = + abstract A :int 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 d9ff7e9597c..1e68d9d5ee8 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -351,6 +351,13 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldSucceed + // SOURCE=E_AttributeTargetIsClass01.fs # E_AttributeTargetIsClass01.fs + [] + let ``E_AttributeTargetIsClass01_fs`` compilation = + compilation + |> verifyCompile + |> shouldSucceed + // SOURCE=E_AttributeTargetIsClass.fs # E_AttributeTargetIsClass.fs [] let ``E_AttributeTargetIsClass_fs preview`` compilation = @@ -363,6 +370,18 @@ module CustomAttributes_AttributeUsage = (Error 842, Line 19, Col 3, Line 19, Col 15, "This attribute is not valid for use on this language element") (Error 842, Line 22, Col 10, Line 22, Col 22, "This attribute is not valid for use on this language element") ] + + // SOURCE=E_AttributeTargetIsClass01.fs # E_AttributeTargetIsClass01.fs + [] + let ``E_AttributeTargetIsClass01_fs preview`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 842, Line 7, Col 3, Line 7, Col 18, "This attribute is not valid for use on this language element") + (Error 842, Line 10, Col 10, Line 10, Col 25, "This attribute is not valid for use on this language element") + ] // SOURCE=MarshalAsAttribute.fs # MarshalAsAttribute.fs [] @@ -583,4 +602,40 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) = """ |> withLangVersionPreview |> compile - |> shouldSucceed \ No newline at end of file + |> shouldSucceed + + // SOURCE=AttributeTargetsIsInterface.fs # AttributeTargetsIsInterface.fs + [] + let ``AttributeTargetsIsInterface_fs`` compilation = + compilation + |> verifyCompile + |> shouldSucceed + + // SOURCE=AttributeTargetsIsInterface.fs # AttributeTargetsIsInterface.fs + [] + let ``AttributeTargetsIsInterface_fs preview`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompile + |> shouldSucceed + + // SOURCE=E_AttributeTargetIsInterface.fs # E_AttributeTargetIsInterface.fs + [] + let ``E_AttributeTargetIsInterface_fs`` compilation = + compilation + |> verifyCompile + |> shouldSucceed + + // SOURCE=E_AttributeTargetIsInterface.fs # E_AttributeTargetIsInterface.fs + [] + let ``E_AttributeTargetIsInterface_fs preview`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 842, Line 11, Col 3, Line 11, Col 14, "This attribute is not valid for use on this language element") + (Error 842, Line 14, Col 3, Line 14, Col 15, "This attribute is not valid for use on this language element") + (Error 842, Line 18, Col 3, Line 18, Col 14, "This attribute is not valid for use on this language element") + (Error 842, Line 19, Col 3, Line 19, Col 15, "This attribute is not valid for use on this language element") + ] \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsClass01.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsClass01.fs new file mode 100644 index 00000000000..e3f94e20bf1 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsClass01.fs @@ -0,0 +1,11 @@ +open System + +[] +type CustomInterfaceAttribute() = + inherit Attribute() + +[] +type Class(x: int) = class end + +[] +type Class3 = class end \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsInterface.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsInterface.fs new file mode 100644 index 00000000000..5f4e2ff5ea0 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsInterface.fs @@ -0,0 +1,22 @@ +open System + +[] +type CustomStructAttribute() = + inherit Attribute() + +[] +type CustomClassAttribute() = + inherit Attribute() + +[] +type IFoo = interface end + +[] +type IFoo2 = + abstract A :int + +[] +[] +[] +type IFoo3 = + abstract A :int \ No newline at end of file diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs index c5e347878a4..991337acba3 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs @@ -158,21 +158,22 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem member this.Advise(callbackOwnerKey, callback) = notificationsDict.[callbackOwnerKey] <- callback - // Used to get us sorted appropriately with the other MSFT products in the splash screen and about box - [] - [] - [] - [] - [] - [] - type public IVsMicrosoftInstalledProduct = - inherit IVsInstalledProduct - abstract IdBmpSplashM : byref -> unit - abstract OfficialNameM : on : byref -> unit - abstract ProductIDM : pid : byref -> unit - abstract ProductDetailsM : pd : byref -> unit - abstract IdIcoLogoForAboutboxM : byref -> unit - abstract ProductRegistryName : prn : byref -> unit + // // Used to get us sorted appropriately with the other MSFT products in the splash screen and about box + // [] + // [] + // [] + // [] + // [] + // [] + // type public IVsMicrosoftInstalledProduct = + // interface IVsInstalledProduct + // + // abstract IdBmpSplashM : byref -> unit + // abstract OfficialNameM : on : byref -> unit + // abstract ProductIDM : pid : byref -> unit + // abstract ProductDetailsM : pd : byref -> unit + // abstract IdIcoLogoForAboutboxM : byref -> unit + // abstract ProductRegistryName : prn : byref -> unit exception internal ExitedOk exception internal ExitedWithError