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 460e58b0fdc..83b2c864908 100644
--- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md
+++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md
@@ -16,6 +16,7 @@
* Enforce AttributeTargets on let values and functions. ([PR #16692](https://github.com/dotnet/fsharp/pull/16692))
* Enforce AttributeTargets on union case declarations. ([PR #16764](https://github.com/dotnet/fsharp/pull/16764))
* Disallow using base to invoke an abstract base method. ([Issue #13926](https://github.com/dotnet/fsharp/issues/13926), [PR #16773](https://github.com/dotnet/fsharp/pull/16773))
+* Enforce AttributeTargets on structs and classes ([PR #16790](https://github.com/dotnet/fsharp/pull/16790))
* Parser: fix pattern range for idents with trivia ([PR #16824](https://github.com/dotnet/fsharp/pull/16824))
* Fix broken code completion after a record type declaration ([PR #16813](https://github.com/dotnet/fsharp/pull/16813))
diff --git a/docs/release-notes/.FSharp.Core/8.0.300.md b/docs/release-notes/.FSharp.Core/8.0.300.md
index 7c3911ae98f..60b25705745 100644
--- a/docs/release-notes/.FSharp.Core/8.0.300.md
+++ b/docs/release-notes/.FSharp.Core/8.0.300.md
@@ -6,3 +6,4 @@
### Fixed
* Preserve original stack traces in resumable state machines generated code if available. ([PR #16568](https://github.com/dotnet/fsharp/pull/16568))
+* Enforce AttributeTargets on structs and classes. Also update `RequireQualifiedAccessAttribute` and `AutoOpenAttribute` to use `AttributeTargets.Struct` ([PR #16790](https://github.com/dotnet/fsharp/pull/16790))
\ No newline at end of file
diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md
index eb7ddd08e54..4a6122e29dd 100644
--- a/docs/release-notes/.Language/preview.md
+++ b/docs/release-notes/.Language/preview.md
@@ -11,6 +11,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))
* Enforce AttributeTargets on union case declarations. ([PR #16764](https://github.com/dotnet/fsharp/pull/16764))
+* Enforce AttributeTargets on structs and classes ([PR #16790](https://github.com/dotnet/fsharp/pull/16790))
### Changed
diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs
index 457a3489576..88c8c7b5a72 100644
--- a/src/Compiler/Checking/CheckDeclarations.fs
+++ b/src/Compiler/Checking/CheckDeclarations.fs
@@ -2926,10 +2926,16 @@ module EstablishTypeDefinitionCores =
| _ ->
let kind =
match kind with
- | SynTypeDefnKind.Class -> TFSharpClass
+ | SynTypeDefnKind.Class ->
+ if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnStructAndClasses) then
+ TcAttributesWithPossibleTargets false cenv envinner AttributeTargets.Class synAttrs |> ignore
+ TFSharpClass
| SynTypeDefnKind.Interface -> TFSharpInterface
| SynTypeDefnKind.Delegate _ -> TFSharpDelegate (MakeSlotSig("Invoke", g.unit_ty, [], [], [], None))
- | SynTypeDefnKind.Struct -> TFSharpStruct
+ | SynTypeDefnKind.Struct ->
+ if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargetsOnStructAndClasses) then
+ TcAttributesWithPossibleTargets false cenv envinner AttributeTargets.Struct synAttrs |> ignore
+ TFSharpStruct
| _ -> error(InternalError("should have inferred tycon kind", m))
TFSharpTyconRepr (Construct.NewEmptyFSharpTyconData kind)
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index 838ead87857..eda76095bb2 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -1596,6 +1596,7 @@ featureBooleanReturningAndReturnTypeDirectedPartialActivePattern,"Boolean-return
featureEnforceAttributeTargetsOnFunctions,"Enforce AttributeTargets on functions"
featureEnforceAttributeTargetsUnionCaseDeclarations,"Enforce AttributeTargets on union case declarations"
featureLowerInterpolatedStringToConcat,"Optimizes interpolated strings in certain cases, by lowering to concatenation"
+featureEnforceAttributeTargetsOnStructAndClasses,"Enforce AttributeTargets on structs and classes"
featureLowerIntegralRangesToFastLoops,"Optimizes certain uses of the integral range (..) and range-step (.. ..) operators to fast while-loops."
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."
diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs
index 3103d8b159e..ac48fc40b91 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fs
+++ b/src/Compiler/Facilities/LanguageFeatures.fs
@@ -88,6 +88,7 @@ type LanguageFeature =
| EnforceAttributeTargetsOnFunctions
| EnforceAttributeTargetsUnionCaseDeclarations
| LowerInterpolatedStringToConcat
+ | EnforceAttributeTargetsOnStructAndClasses
| LowerIntegralRangesToFastLoops
/// LanguageVersion management
@@ -204,6 +205,7 @@ type LanguageVersion(versionText) =
LanguageFeature.EnforceAttributeTargetsOnFunctions, previewVersion
LanguageFeature.EnforceAttributeTargetsUnionCaseDeclarations, previewVersion
LanguageFeature.LowerInterpolatedStringToConcat, previewVersion
+ LanguageFeature.EnforceAttributeTargetsOnStructAndClasses, previewVersion
LanguageFeature.LowerIntegralRangesToFastLoops, previewVersion
]
@@ -351,6 +353,7 @@ type LanguageVersion(versionText) =
| LanguageFeature.EnforceAttributeTargetsOnFunctions -> FSComp.SR.featureEnforceAttributeTargetsOnFunctions ()
| LanguageFeature.EnforceAttributeTargetsUnionCaseDeclarations -> FSComp.SR.featureEnforceAttributeTargetsUnionCaseDeclarations ()
| LanguageFeature.LowerInterpolatedStringToConcat -> FSComp.SR.featureLowerInterpolatedStringToConcat ()
+ | LanguageFeature.EnforceAttributeTargetsOnStructAndClasses -> FSComp.SR.featureEnforceAttributeTargetsOnStructAndClasses ()
| LanguageFeature.LowerIntegralRangesToFastLoops -> FSComp.SR.featureLowerIntegralRangesToFastLoops ()
/// Get a version string associated with the given feature.
diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi
index 4f0fe835ffa..80a41c8ce54 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fsi
+++ b/src/Compiler/Facilities/LanguageFeatures.fsi
@@ -79,6 +79,7 @@ type LanguageFeature =
| EnforceAttributeTargetsOnFunctions
| EnforceAttributeTargetsUnionCaseDeclarations
| LowerInterpolatedStringToConcat
+ | EnforceAttributeTargetsOnStructAndClasses
| LowerIntegralRangesToFastLoops
/// LanguageVersion management
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index 8d023b7157f..29a83a20d98 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index a64e570f7b9..e28b1177ea9 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index 77d35305506..d86bb178a0d 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index 03ce9378c00..e9cefd5803b 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index 2344a13f7a1..539502d9670 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index 53c737bbfcf..a364c7953d6 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index 5ff6910f893..96768306e24 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index 266d64c82cd..22210fdee9c 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 345fd834ac0..8449413e457 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index 8daa89725d2..41129014c1b 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index b062ac01ce4..659004ddc36 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index b8a8910a995..1b8716f794d 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index bbf312f436b..43da50f6960 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -297,6 +297,11 @@
Enforce AttributeTargets on functions
+
+ Enforce AttributeTargets on structs and classes
+ Enforce AttributeTargets on structs and classes
+
+
Enforce AttributeTargets on union case declarations
Enforce AttributeTargets on union case declarations
diff --git a/src/FSharp.Core/fslib-extra-pervasives.fs b/src/FSharp.Core/fslib-extra-pervasives.fs
index b62d5b16eb8..b5cf5dee3af 100644
--- a/src/FSharp.Core/fslib-extra-pervasives.fs
+++ b/src/FSharp.Core/fslib-extra-pervasives.fs
@@ -363,7 +363,7 @@ type MeasureOne =
class
end
-[]
+[]
type TypeProviderAttribute() =
inherit System.Attribute()
diff --git a/src/FSharp.Core/fslib-extra-pervasives.fsi b/src/FSharp.Core/fslib-extra-pervasives.fsi
index ffd6f6f6a00..97120245f87 100644
--- a/src/FSharp.Core/fslib-extra-pervasives.fsi
+++ b/src/FSharp.Core/fslib-extra-pervasives.fsi
@@ -385,7 +385,7 @@ namespace Microsoft.FSharp.Core.CompilerServices
type MeasureOne
/// Place on a class that implements ITypeProvider to extend the compiler
- []
+ []
type TypeProviderAttribute =
inherit System.Attribute
diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs
index 346c1a64e0e..777a31b8e15 100644
--- a/src/FSharp.Core/prim-types.fs
+++ b/src/FSharp.Core/prim-types.fs
@@ -104,7 +104,7 @@ namespace Microsoft.FSharp.Core
type CLIMutableAttribute() =
inherit Attribute()
- []
+ []
[]
type AutoSerializableAttribute(value:bool) =
inherit Attribute()
@@ -127,19 +127,19 @@ namespace Microsoft.FSharp.Core
type ReferenceEqualityAttribute() =
inherit Attribute()
- []
+ []
[]
type StructuralComparisonAttribute() =
inherit Attribute()
- []
+ []
[]
type StructuralEqualityAttribute() =
inherit Attribute()
[]
+ AttributeTargets.Enum, AllowMultiple=false)>]
[]
type NoEqualityAttribute() =
inherit Attribute()
@@ -161,9 +161,9 @@ namespace Microsoft.FSharp.Core
type NoComparisonAttribute() =
inherit Attribute()
- []
+ []
[]
type ReflectedDefinitionAttribute(includeValue: bool) =
inherit Attribute()
@@ -350,12 +350,12 @@ namespace Microsoft.FSharp.Core
type RequiresExplicitTypeArgumentsAttribute() =
inherit Attribute()
- []
+ []
[]
type RequireQualifiedAccessAttribute() =
inherit Attribute()
- []
+ []
[]
type AutoOpenAttribute(path:string) =
inherit Attribute()
diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi
index dc4b9cc22dd..fc2b4d756a9 100644
--- a/src/FSharp.Core/prim-types.fsi
+++ b/src/FSharp.Core/prim-types.fsi
@@ -129,7 +129,7 @@ namespace Microsoft.FSharp.Core
/// for use at runtime.
///
/// Attributes
- []
+ []
[]
type ReflectedDefinitionAttribute =
inherit Attribute
@@ -385,7 +385,7 @@ namespace Microsoft.FSharp.Core
/// 'System.Object.GetHashCode()' for the type.
///
/// Attributes
- []
+ []
[]
type StructuralEqualityAttribute =
inherit Attribute
@@ -398,7 +398,7 @@ namespace Microsoft.FSharp.Core
/// automatic generation of implementations for 'System.IComparable' for the type.
///
/// Attributes
- []
+ []
[]
type StructuralComparisonAttribute =
inherit Attribute
@@ -604,7 +604,7 @@ namespace Microsoft.FSharp.Core
/// type Serializable by default.
///
/// Attributes
- []
+ []
[]
type AutoSerializableAttribute =
inherit Attribute
@@ -898,7 +898,7 @@ namespace Microsoft.FSharp.Core
/// type require explicit qualified access.
///
/// Attributes
- []
+ []
[]
type RequireQualifiedAccessAttribute =
inherit Attribute
@@ -920,7 +920,7 @@ namespace Microsoft.FSharp.Core
///
///
/// Attributes
- []
+ []
[]
type AutoOpenAttribute =
inherit Attribute
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsClass.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsClass.fs
new file mode 100644
index 00000000000..8f587dcf099
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsClass.fs
@@ -0,0 +1,26 @@
+open System
+
+[]
+type CustomClassAttribute() =
+ inherit Attribute()
+
+[]
+type Class(x: int) = class end
+
+[]
+[]
+type Class2 = class end
+
+[]
+type Class3() = class end
+
+[]
+type SemanticClassificationItem =
+ val Range: int
+ val Type: string
+ new((range, ty)) = { Range = range; Type = ty }
+
+[]
+type ILTableName(idx: int) =
+ member __.Index = idx
+ static member FromIndex n = ILTableName n
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsStruct.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsStruct.fs
new file mode 100644
index 00000000000..9b64c7cb33f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeTargetsIsStruct.fs
@@ -0,0 +1,23 @@
+open System
+
+[]
+type CustomStructAttribute() =
+ inherit Attribute()
+
+[]
+type Class(x: int) = struct end
+
+[]
+[]
+type Class2 = struct end
+
+[]
+type SemanticClassificationItem =
+ val Range: int
+ val Type: string
+ new((range, ty)) = { Range = range; Type = ty }
+
+[]
+type ILTableName(idx: int) =
+ member __.Index = idx
+ static member FromIndex n = ILTableName n
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 0bdc9306cb7..652755fd5cd 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs
@@ -259,6 +259,18 @@ module CustomAttributes_AttributeUsage =
(Error 842, Line 52, Col 6, Line 52, Col 16, "This attribute is not valid for use on this language element")
]
+ // SOURCE=E_AttributeTargetIsMethod04.fs # E_AttributeTargetIsMethod04.fs
+ []
+ let ``E_AttributeTargetIsMethod04_fs`` compilation =
+ compilation
+ |> withOptions ["--nowarn:25"]
+ |> verifyCompile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 842, Line 10, Col 3, Line 10, Col 15, "This attribute is not valid for use on this language element")
+ (Error 842, Line 13, Col 3, Line 13, Col 15, "This attribute is not valid for use on this language element")
+ ]
+
// SOURCE=E_ConditionalAttribute.fs SCFLAGS="--test:ErrorRanges" # E_ConditionalAttribute.fs
[]
let ``E_ConditionalAttribute_fs`` compilation =
@@ -300,6 +312,77 @@ module CustomAttributes_AttributeUsage =
|> withDiagnostics [
(Error 842, Line 12, Col 3, Line 12, Col 6, "This attribute is not valid for use on this language element")
]
+
+ // SOURCE=AttributeTargetIsStruct.fs # AttributeTargetIsStruct.fs
+ []
+ let ``AttributeTargetIsStruct_fs`` compilation =
+ compilation
+ |> verifyCompile
+ |> shouldSucceed
+
+ // SOURCE=AttributeTargetIsStruct.fs # AttributeTargetIsStruct.fs
+ []
+ let ``AttributeTargetIsStruct_fs preview`` compilation =
+ compilation
+ |> withLangVersionPreview
+ |> verifyCompile
+ |> shouldSucceed
+
+ // SOURCE=AttributeTargetIsClass.fs # AttributeTargetIsClass.fs
+ []
+ let ``AttributeTargetIsClass_fs`` compilation =
+ compilation
+ |> verifyCompile
+ |> shouldSucceed
+
+ // SOURCE=AttributeTargetIsClass.fs # AttributeTargetIsClass.fs
+ []
+ let ``AttributeTargetIsClass_fs preview`` compilation =
+ compilation
+ |> withLangVersionPreview
+ |> verifyCompile
+ |> shouldSucceed
+
+ // SOURCE=E_AttributeTargetIsStruct.fs # E_AttributeTargetIsStruct.fs
+ []
+ let ``E_AttributeTargetIsStruct_fs`` compilation =
+ compilation
+ |> verifyCompile
+ |> shouldSucceed
+
+ // SOURCE=E_AttributeTargetIsStruct.fs # E_AttributeTargetIsStruct.fs
+ []
+ let ``E_AttributeTargetIsStruct_fs preview`` compilation =
+ compilation
+ |> withLangVersionPreview
+ |> verifyCompile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 842, Line 13, Col 3, Line 13, Col 14, "This attribute is not valid for use on this language element")
+ (Error 842, Line 19, Col 3, Line 19, Col 14, "This attribute is not valid for use on this language element")
+ (Error 842, Line 22, Col 11, Line 22, Col 22, "This attribute is not valid for use on this language element")
+ (Error 842, Line 25, Col 3, Line 25, Col 14, "This attribute is not valid for use on this language element")
+ ]
+
+ // SOURCE=E_AttributeTargetIsClass.fs # E_AttributeTargetIsClass.fs
+ []
+ let ``E_AttributeTargetIsClass_fs`` compilation =
+ compilation
+ |> verifyCompile
+ |> shouldSucceed
+
+ // SOURCE=E_AttributeTargetIsClass.fs # E_AttributeTargetIsClass.fs
+ []
+ let ``E_AttributeTargetIsClass_fs preview`` compilation =
+ compilation
+ |> withLangVersionPreview
+ |> verifyCompile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 842, Line 13, Col 3, Line 13, Col 15, "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")
+ (Error 842, Line 22, Col 10, Line 22, Col 22, "This attribute is not valid for use on this language element")
+ ]
// SOURCE=MarshalAsAttribute.fs # MarshalAsAttribute.fs
[]
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsClass.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsClass.fs
new file mode 100644
index 00000000000..845b7d1762f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsClass.fs
@@ -0,0 +1,23 @@
+// This tests that AttributeTargets.Struct is not allowed on a class, and that AttributeTargets.Class is not allowed on a struct.
+
+open System
+
+[]
+type CustomStructAttribute() =
+ inherit Attribute()
+
+[]
+type CustomClassAttribute() =
+ inherit Attribute()
+
+[]
+type Class(x: int) = class end
+
+[]
+type Class2(x: int) = class end
+
+[]
+type Class3(x: int) = class end
+
+[]
+type Class4 = class end
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod04.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod04.fs
new file mode 100644
index 00000000000..bd78c8fd5d5
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsMethod04.fs
@@ -0,0 +1,15 @@
+// This tests that AttributeTargets.Method is not allowed in class and struct types.
+
+open System
+open System.Diagnostics
+
+[]
+type CustomMethodAttribute() =
+ inherit Attribute()
+
+[]
+type Class() = class end
+
+[]
+type Struct(x: int) = struct end
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsStruct.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsStruct.fs
new file mode 100644
index 00000000000..ace0b6a5c39
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/E_AttributeTargetIsStruct.fs
@@ -0,0 +1,27 @@
+// This tests that AttributeTargets.Class is not allowed on a struct, and that AttributeTargets.Struct is not allowed on a class.
+
+open System
+
+[]
+type CustomStructAttribute() =
+ inherit Attribute()
+
+[]
+type CustomClassAttribute() =
+ inherit Attribute()
+
+[]
+type Struct(x: int) = struct end
+
+[]
+type Struct1(x: int) = struct end
+
+[]
+type Struct2(x: int) = struct end
+
+[]
+type Struct4 = struct end
+
+[]
+[]
+type Struct5 = struct end
\ No newline at end of file
diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs
index b5324d5611b..5b8da7c30a3 100644
--- a/tests/service/ProjectAnalysisTests.fs
+++ b/tests/service/ProjectAnalysisTests.fs
@@ -2360,8 +2360,10 @@ let ``Test Project14 all symbols`` () =
|> Array.map (fun su -> su.Symbol.ToString(), su.Symbol.DisplayName, Project14.cleanFileName su.FileName, tups su.Range, attribsOfSymbolUse su)
allUsesOfAllSymbols |> shouldEqual
- [|("StructAttribute", "StructAttribute", "file1", ((4, 2), (4, 8)),
- ["attribute"]);
+ [|
+ ("StructAttribute", "StructAttribute", "file1", ((4, 2), (4, 8)), ["attribute"]);
+ ("member .ctor", "StructAttribute", "file1", ((4, 2), (4, 8)), [])
+ ("StructAttribute", "StructAttribute", "file1", ((4, 2), (4, 8)), ["attribute"]);
("member .ctor", "StructAttribute", "file1", ((4, 2), (4, 8)), []);
("int", "int", "file1", ((5, 9), (5, 12)), ["type"]);
("int", "int", "file1", ((5, 9), (5, 12)), ["type"]);
@@ -2514,14 +2516,14 @@ let ``Test Project16 all symbols`` () =
|> Array.map (fun su -> su.Symbol.ToString(), su.Symbol.DisplayName, Project16.cleanFileName su.FileName, tups su.Range, attribsOfSymbolUse su, attribsOfSymbol su.Symbol)
allUsesOfAllSymbols |> shouldEqual
- [|("ClassAttribute", "ClassAttribute", "sig1", ((8, 6), (8, 11)),
- ["attribute"], ["class"]);
- ("member .ctor", "ClassAttribute", "sig1", ((8, 6), (8, 11)), [],
- ["member"]);
- ("ClassAttribute", "ClassAttribute", "sig1", ((12, 6), (12, 11)),
- ["attribute"], ["class"]);
- ("member .ctor", "ClassAttribute", "sig1", ((12, 6), (12, 11)), [],
- ["member"]);
+ [|("ClassAttribute", "ClassAttribute", "sig1", ((8, 6), (8, 11)), ["attribute"], ["class"]);
+ ("member .ctor", "ClassAttribute", "sig1", ((8, 6), (8, 11)), [], ["member"]);
+ ("ClassAttribute", "ClassAttribute", "sig1", ((8, 6), (8, 11)), ["attribute"], ["class"]);
+ ("member .ctor", "ClassAttribute", "sig1", ((8, 6), (8, 11)), [], ["member"]);
+ ("ClassAttribute", "ClassAttribute", "sig1", ((12, 6), (12, 11)), ["attribute"], ["class"]);
+ ("member .ctor", "ClassAttribute", "sig1", ((12, 6), (12, 11)), [], ["member"]);
+ ("ClassAttribute", "ClassAttribute", "sig1", ((12, 6), (12, 11)), ["attribute"], ["class"]);
+ ("member .ctor", "ClassAttribute", "sig1", ((12, 6), (12, 11)), [], ["member"]);
("int", "int", "sig1", ((16, 19), (16, 22)), ["type"], ["abbrev"]);
("int", "int", "sig1", ((16, 33), (16, 36)), ["type"], ["abbrev"]);
("int", "int", "sig1", ((17, 25), (17, 28)), ["type"], ["abbrev"]);
diff --git a/tests/service/data/TestTP/ProvidedTypes.fs b/tests/service/data/TestTP/ProvidedTypes.fs
index 828235a0b9d..9cd4c0dc0a2 100644
--- a/tests/service/data/TestTP/ProvidedTypes.fs
+++ b/tests/service/data/TestTP/ProvidedTypes.fs
@@ -3221,7 +3221,6 @@ module internal AssemblyReader =
override __.ToString() = ""
[]
-
[]
type ILTableName(idx: int) =
member __.Index = idx
diff --git a/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/ProvidedTypes.fs b/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/ProvidedTypes.fs
index ae593e9961a..e787194a7b6 100644
--- a/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/ProvidedTypes.fs
+++ b/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/ProvidedTypes.fs
@@ -2961,7 +2961,6 @@ namespace ProviderImplementation.ProvidedTypes.AssemblyReader
override _.ToString() = ""
[]
-
[]
type ILTableName(idx: int) =
member _.Index = idx