Skip to content

Commit 6c96fc7

Browse files
authored
Account for Sealed and StructLayout attributes when checking attribute targets (#17609)
1 parent 11c3b9c commit 6c96fc7

File tree

6 files changed

+93
-17
lines changed

6 files changed

+93
-17
lines changed

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2856,12 +2856,16 @@ module EstablishTypeDefinitionCores =
28562856
let hasStructAttr = HasFSharpAttribute g g.attrib_StructAttribute attrs
28572857
let hasCLIMutable = HasFSharpAttribute g g.attrib_CLIMutableAttribute attrs
28582858
let hasAllowNullLiteralAttr = HasFSharpAttribute g g.attrib_AllowNullLiteralAttribute attrs
2859+
let hasSealedAttr = HasFSharpAttribute g g.attrib_SealedAttribute attrs
2860+
let structLayoutAttr = HasFSharpAttribute g g.attrib_StructLayoutAttribute attrs
28592861

28602862
// We want to keep these special attributes treatment and avoid having two errors for the same attribute.
28612863
let reportAttributeTargetsErrors =
28622864
g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets)
28632865
&& not hasCLIMutable // CLIMutableAttribute has a special treatment(specific error FS3132)
28642866
&& not hasAllowNullLiteralAttr // AllowNullLiteralAttribute has a special treatment(specific errors FS0934, FS093)
2867+
&& not hasSealedAttr // SealedAttribute has a special treatment(specific error FS942)
2868+
&& not structLayoutAttr // StructLayoutAttribute has a special treatment(specific error FS0937)
28652869

28662870
let noCLIMutableAttributeCheck() =
28672871
if hasCLIMutable then errorR (Error(FSComp.SR.tcThisTypeMayNotHaveACLIMutableAttribute(), m))

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

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,4 +846,60 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
846846
compilation
847847
|> withLangVersionPreview
848848
|> verifyCompile
849-
|> shouldSucceed
849+
|> shouldSucceed
850+
851+
// SOURCE= E_SealedAttribute01.fs # E_SealedAttribute01.fs
852+
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_SealedAttribute01.fs"|])>]
853+
let ``E_SealedAttribute01 9.0`` compilation =
854+
compilation
855+
|> withLangVersion90
856+
|> verifyCompile
857+
|> shouldFail
858+
|> withDiagnostics [
859+
(Error 942, Line 2, Col 6, Line 2, Col 31, "Struct types are always sealed")
860+
(Error 948, Line 8, Col 6, Line 8, Col 24, "Interface types cannot be sealed")
861+
(Error 942, Line 14, Col 6, Line 14, Col 33, "Delegate types are always sealed")
862+
]
863+
864+
// SOURCE=E_SealedAttribute01.fs # E_SealedAttribute01.fs
865+
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_SealedAttribute01.fs"|])>]
866+
let ``E_SealedAttribute01 preview`` compilation =
867+
compilation
868+
|> withLangVersionPreview
869+
|> verifyCompile
870+
|> shouldFail
871+
|> withDiagnostics [
872+
(Error 942, Line 2, Col 6, Line 2, Col 31, "Struct types are always sealed")
873+
(Error 948, Line 8, Col 6, Line 8, Col 24, "Interface types cannot be sealed")
874+
(Error 942, Line 14, Col 6, Line 14, Col 33, "Delegate types are always sealed")
875+
]
876+
877+
// SOURCE= E_StructLayout01.fs # E_StructLayout01.fs
878+
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_StructLayout01.fs"|])>]
879+
let ``E_StructLayout01 9.0`` compilation =
880+
compilation
881+
|> withLangVersion90
882+
|> verifyCompile
883+
|> shouldFail
884+
|> withDiagnostics [
885+
(Error 937, Line 2, Col 6, Line 2, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
886+
(Error 937, Line 7, Col 6, Line 7, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
887+
(Error 937, Line 11, Col 6, Line 11, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
888+
(Error 937, Line 14, Col 6, Line 14, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
889+
(Error 937, Line 17, Col 6, Line 17, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
890+
]
891+
892+
// SOURCE=E_StructLayout01.fs # E_StructLayout01.fs
893+
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_StructLayout01.fs"|])>]
894+
let ``E_StructLayout01 preview`` compilation =
895+
compilation
896+
|> withLangVersionPreview
897+
|> verifyCompile
898+
|> shouldFail
899+
|> withDiagnostics [
900+
(Error 937, Line 2, Col 6, Line 2, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
901+
(Error 937, Line 7, Col 6, Line 7, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
902+
(Error 937, Line 11, Col 6, Line 11, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
903+
(Error 937, Line 14, Col 6, Line 14, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
904+
(Error 937, Line 17, Col 6, Line 17, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
905+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[<Sealed>]
2+
type UnnecessarilySealedStruct =
3+
struct
4+
member x.P = 1
5+
end
6+
7+
[<Sealed>]
8+
type BadSealedInterface =
9+
interface
10+
abstract P : int
11+
end
12+
13+
[<Sealed>]
14+
type UnnecessarilySealedDelegate = delegate of int -> int
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
2+
type X1 =
3+
abstract M : unit -> 'a
4+
5+
[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
6+
[<AbstractClass>]
7+
type X2() =
8+
abstract M : unit -> 'a
9+
10+
[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
11+
type X4 = R1 | R2
12+
13+
[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
14+
type X5 = R1 = 1 | R2 = 2
15+
16+
[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
17+
type X6 = delegate of int -> int

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,7 @@ module CustomAttributes_Basic =
159159
|> withLangVersionPreview
160160
|> verifyCompile
161161
|> shouldFail
162-
|> withDiagnostics[
163-
(Error 842, Line 8, Col 7, Line 8, Col 104, "This attribute is not valid for use on this language element")
162+
|> withDiagnostics [
164163
(Error 937, Line 9, Col 10, Line 9, Col 12, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
165164
]
166165

@@ -172,7 +171,6 @@ module CustomAttributes_Basic =
172171
|> verifyCompile
173172
|> shouldFail
174173
|> withDiagnostics [
175-
(Error 842, Line 8, Col 7, Line 8, Col 104, "This attribute is not valid for use on this language element")
176174
(Error 937, Line 9, Col 10, Line 9, Col 12, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
177175
]
178176

@@ -184,7 +182,6 @@ module CustomAttributes_Basic =
184182
|> verifyCompile
185183
|> shouldFail
186184
|> withDiagnostics [
187-
(Error 842, Line 7, Col 7, Line 7, Col 104, "This attribute is not valid for use on this language element")
188185
(Error 937, Line 8, Col 10, Line 8, Col 12, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
189186
]
190187

tests/fsharp/typecheck/sigs/neg06.bsl

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,12 @@
22
neg06.fs(3,40,3,45): typecheck error FS0039: The type 'Encoding' does not define the field, constructor or member 'Ascii'. Maybe you want one of the following:
33
ASCII
44

5-
neg06.fs(11,3,11,9): typecheck error FS0842: This attribute is not valid for use on this language element
6-
75
neg06.fs(12,6,12,31): typecheck error FS0942: Struct types are always sealed
86

9-
neg06.fs(17,3,17,9): typecheck error FS0842: This attribute is not valid for use on this language element
10-
117
neg06.fs(18,6,18,24): typecheck error FS0948: Interface types cannot be sealed
128

139
neg06.fs(24,6,24,30): typecheck error FS0944: Abbreviated types cannot be given the 'Sealed' attribute
1410

15-
neg06.fs(26,3,26,9): typecheck error FS0842: This attribute is not valid for use on this language element
16-
1711
neg06.fs(27,6,27,33): typecheck error FS0942: Delegate types are always sealed
1812

1913
neg06.fs(31,9,31,29): typecheck error FS0945: Cannot inherit a sealed type
@@ -94,20 +88,14 @@ neg06.fs(223,13,223,21): typecheck error FS0800: Invalid use of a type name
9488

9589
neg06.fs(300,10,300,12): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.
9690

97-
neg06.fs(303,7,303,104): typecheck error FS0842: This attribute is not valid for use on this language element
98-
9991
neg06.fs(304,10,304,12): typecheck error FS0937: Only structs and classes without primary constructors may be given the 'StructLayout' attribute
10092

10193
neg06.fs(310,10,310,12): typecheck error FS0937: Only structs and classes without primary constructors may be given the 'StructLayout' attribute
10294

10395
neg06.fs(314,10,314,12): typecheck error FS0937: Only structs and classes without primary constructors may be given the 'StructLayout' attribute
10496

105-
neg06.fs(316,7,316,104): typecheck error FS0842: This attribute is not valid for use on this language element
106-
10797
neg06.fs(317,10,317,12): typecheck error FS0937: Only structs and classes without primary constructors may be given the 'StructLayout' attribute
10898

109-
neg06.fs(319,7,319,104): typecheck error FS0842: This attribute is not valid for use on this language element
110-
11199
neg06.fs(320,10,320,12): typecheck error FS0937: Only structs and classes without primary constructors may be given the 'StructLayout' attribute
112100

113101
neg06.fs(326,10,326,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation

0 commit comments

Comments
 (0)