Skip to content

Commit

Permalink
Account for Sealed and StructLayout attributes when checking attr…
Browse files Browse the repository at this point in the history
…ibute targets (#17609)
  • Loading branch information
edgarfgp committed Aug 27, 2024
1 parent 11c3b9c commit 6c96fc7
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 17 deletions.
4 changes: 4 additions & 0 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2856,12 +2856,16 @@ module EstablishTypeDefinitionCores =
let hasStructAttr = HasFSharpAttribute g g.attrib_StructAttribute attrs
let hasCLIMutable = HasFSharpAttribute g g.attrib_CLIMutableAttribute attrs
let hasAllowNullLiteralAttr = HasFSharpAttribute g g.attrib_AllowNullLiteralAttribute attrs
let hasSealedAttr = HasFSharpAttribute g g.attrib_SealedAttribute attrs
let structLayoutAttr = HasFSharpAttribute g g.attrib_StructLayoutAttribute attrs

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

let noCLIMutableAttributeCheck() =
if hasCLIMutable then errorR (Error(FSComp.SR.tcThisTypeMayNotHaveACLIMutableAttribute(), m))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -846,4 +846,60 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
compilation
|> withLangVersionPreview
|> verifyCompile
|> shouldSucceed
|> shouldSucceed

// SOURCE= E_SealedAttribute01.fs # E_SealedAttribute01.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_SealedAttribute01.fs"|])>]
let ``E_SealedAttribute01 9.0`` compilation =
compilation
|> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 942, Line 2, Col 6, Line 2, Col 31, "Struct types are always sealed")
(Error 948, Line 8, Col 6, Line 8, Col 24, "Interface types cannot be sealed")
(Error 942, Line 14, Col 6, Line 14, Col 33, "Delegate types are always sealed")
]

// SOURCE=E_SealedAttribute01.fs # E_SealedAttribute01.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_SealedAttribute01.fs"|])>]
let ``E_SealedAttribute01 preview`` compilation =
compilation
|> withLangVersionPreview
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 942, Line 2, Col 6, Line 2, Col 31, "Struct types are always sealed")
(Error 948, Line 8, Col 6, Line 8, Col 24, "Interface types cannot be sealed")
(Error 942, Line 14, Col 6, Line 14, Col 33, "Delegate types are always sealed")
]

// SOURCE= E_StructLayout01.fs # E_StructLayout01.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_StructLayout01.fs"|])>]
let ``E_StructLayout01 9.0`` compilation =
compilation
|> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 937, Line 2, Col 6, Line 2, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
(Error 937, Line 7, Col 6, Line 7, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
(Error 937, Line 11, Col 6, Line 11, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
(Error 937, Line 14, Col 6, Line 14, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
(Error 937, Line 17, Col 6, Line 17, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
]

// SOURCE=E_StructLayout01.fs # E_StructLayout01.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_StructLayout01.fs"|])>]
let ``E_StructLayout01 preview`` compilation =
compilation
|> withLangVersionPreview
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 937, Line 2, Col 6, Line 2, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
(Error 937, Line 7, Col 6, Line 7, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
(Error 937, Line 11, Col 6, Line 11, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
(Error 937, Line 14, Col 6, Line 14, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
(Error 937, Line 17, Col 6, Line 17, Col 8, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[<Sealed>]
type UnnecessarilySealedStruct =
struct
member x.P = 1
end

[<Sealed>]
type BadSealedInterface =
interface
abstract P : int
end

[<Sealed>]
type UnnecessarilySealedDelegate = delegate of int -> int
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
type X1 =
abstract M : unit -> 'a

[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
[<AbstractClass>]
type X2() =
abstract M : unit -> 'a

[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
type X4 = R1 | R2

[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
type X5 = R1 = 1 | R2 = 2

[<System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)>]
type X6 = delegate of int -> int
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,7 @@ module CustomAttributes_Basic =
|> withLangVersionPreview
|> verifyCompile
|> shouldFail
|> withDiagnostics[
(Error 842, Line 8, Col 7, Line 8, Col 104, "This attribute is not valid for use on this language element")
|> withDiagnostics [
(Error 937, Line 9, Col 10, Line 9, Col 12, "Only structs and classes without primary constructors may be given the 'StructLayout' attribute")
]

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

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

Expand Down
12 changes: 0 additions & 12 deletions tests/fsharp/typecheck/sigs/neg06.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@
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:
ASCII

neg06.fs(11,3,11,9): typecheck error FS0842: This attribute is not valid for use on this language element

neg06.fs(12,6,12,31): typecheck error FS0942: Struct types are always sealed

neg06.fs(17,3,17,9): typecheck error FS0842: This attribute is not valid for use on this language element

neg06.fs(18,6,18,24): typecheck error FS0948: Interface types cannot be sealed

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

neg06.fs(26,3,26,9): typecheck error FS0842: This attribute is not valid for use on this language element

neg06.fs(27,6,27,33): typecheck error FS0942: Delegate types are always sealed

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

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"'.

neg06.fs(303,7,303,104): typecheck error FS0842: This attribute is not valid for use on this language element

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

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

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

neg06.fs(316,7,316,104): typecheck error FS0842: This attribute is not valid for use on this language element

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

neg06.fs(319,7,319,104): typecheck error FS0842: This attribute is not valid for use on this language element

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

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

0 comments on commit 6c96fc7

Please sign in to comment.