Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/9.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@

* Change compiler default setting realsig+ when building assemblies ([Issue #17384](https://github.com/dotnet/fsharp/issues/17384), [PR #17378](https://github.com/dotnet/fsharp/pull/17385))
* Change compiler default setting for compressedMetadata ([Issue #17379](https://github.com/dotnet/fsharp/issues/17379), [PR #17383](https://github.com/dotnet/fsharp/pull/17383))
* Enforce `AttributeTargets` on unions. ([PR #17389](https://github.com/dotnet/fsharp/pull/17389))

### Breaking Changes
6 changes: 6 additions & 0 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2879,6 +2879,12 @@ module EstablishTypeDefinitionCores =

// Run InferTyconKind to raise errors on inconsistent attribute sets
InferTyconKind g (SynTypeDefnKind.Union, attrs, [], [], inSig, true, m) |> ignore

if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) then
if hasStructAttr then
TcAttributesWithPossibleTargets false cenv envinner AttributeTargets.Struct synAttrs |> ignore
else
TcAttributesWithPossibleTargets false cenv envinner AttributeTargets.Class synAttrs |> ignore

// Note: the table of union cases is initially empty
Construct.MakeUnionRepr []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,21 @@ type ILTableName(idx: int) =
type Record = { Prop: string }

[<RequireQualifiedAccess>]
[<Struct>]
type StructRecord = { Prop: string }
[<CustomClass>]
type Record2 = { Prop: string }

[<RequireQualifiedAccess>]
type ClassUnion =
| StructUnionCase of int
| StructUnionCase2 of string

[<RequireQualifiedAccess>]
type ClassUnionId = Id

[<CustomClass>]
type ClassUnionId2 = Id

[<CustomClass>]
type UnionCase =
| UnionCase of int
| UnionCase2 of string
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,33 @@ type SemanticClassificationItem =
type ILTableName(idx: int) =
member __.Index = idx
static member FromIndex n = ILTableName n

[<RequireQualifiedAccess>]
[<Struct>]
type StructRecord = { Prop: string }

[<RequireQualifiedAccess>]
[<Struct>]
type StructUnion =
| StructUnionCase of a: int
| StructUnionCase2 of string

[<RequireQualifiedAccess>]
[<Struct>]
type StructUnionId = Id

[<CustomStruct>]
[<Struct>]
type StructUnionId2 = Id

[<CustomStruct>]
[<Struct>]
type Union1 =
| UnionCase of a: int
| UnionCase2 of string

[<CustomStruct>]
[<Struct>]
type Union2 =
| UnionCase of a: int * b: int
| UnionCase2 of c: string * d: string
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,14 @@ module CustomAttributes_AttributeUsage =
(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")
(Error 842, Line 34, Col 3, Line 34, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 35, Col 3, Line 35, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 40, Col 3, Line 40, Col 14, "This attribute is not valid for use on this language element")
(Error 842, Line 41, Col 3, Line 41, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 49, Col 3, Line 49, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 50, Col 3, Line 50, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 53, Col 3, Line 53, Col 14, "This attribute is not valid for use on this language element")
(Error 842, Line 54, Col 3, Line 54, Col 18, "This attribute is not valid for use on this language element")
]

// SOURCE=E_AttributeTargetIsClass.fs # E_AttributeTargetIsClass.fs
Expand Down Expand Up @@ -655,8 +663,16 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 842, Line 15, Col 3, Line 15, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 15, Col 3, Line 15, Col 18, "This attribute is not valid for use on this language element");
(Error 842, Line 16, Col 3, Line 16, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 20, Col 3, Line 20, Col 14, "This attribute is not valid for use on this language element")
(Error 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 26, Col 3, Line 26, Col 14, "This attribute is not valid for use on this language element")
(Error 842, Line 27, Col 3, Line 27, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 34, Col 3, Line 34, Col 14, "This attribute is not valid for use on this language element")
(Error 842, Line 35, Col 3, Line 35, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 43, Col 3, Line 43, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 44, Col 3, Line 44, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 47, Col 3, Line 47, Col 14, "This attribute is not valid for use on this language element")
(Error 842, Line 48, Col 3, Line 48, Col 18, "This attribute is not valid for use on this language element")
]
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,31 @@ type Record = { Prop: string }
[<InterfaceTarget>]
[<StructTarget>]
[<Struct>]
type StructRecord = { Prop: string }
type StructRecord = { Prop: string }

[<ClassTarget>]
[<InterfaceTarget>]
[<StructTarget>]
[<Struct>]
type UnionCase =
| UnionCase of a: int
| UnionCase2 of string

[<ClassTarget>]
[<InterfaceTarget>]
[<StructTarget>]
[<Struct>]
type UnionCase2 =
| UnionCase of a: int * b: int
| UnionCase2 of c: string * d: string

[<ClassTarget>]
[<InterfaceTarget>]
[<StructTarget>]
type StructUnionId = Id

[<ClassTarget>]
[<InterfaceTarget>]
[<StructTarget>]
[<Struct>]
type StructUnionId2 = Id
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,34 @@ type Struct4 = struct end

[<CustomClass>]
[<Struct>]
type Struct5 = struct end
type Struct5 = struct end

[<AttributeUsage(AttributeTargets.Interface)>]
type InterfaceTargetAttribute() =
inherit Attribute()

[<CustomClass>]
[<InterfaceTarget>]
[<CustomStruct>]
type UnionCase =
| UnionCase of int
| UnionCase2 of string

[<CustomClass>]
[<InterfaceTarget>]
[<CustomStruct>]
[<Struct>]
type UnionCase2 =
| UnionCase of a: int * b: int
| UnionCase2 of c: string * d: string

[<CustomClass>]
[<InterfaceTarget>]
[<CustomStruct>]
type StructUnionId = Id

[<CustomClass>]
[<InterfaceTarget>]
[<CustomStruct>]
[<Struct>]
type StructUnionId2 = Id
53 changes: 28 additions & 25 deletions tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5075,31 +5075,34 @@ let ``Test Project40 all symbols`` () =
let allSymbolUsesInfo = [ for s in allSymbolUses -> s.Symbol.DisplayName, tups s.Range, attribsOfSymbol s.Symbol ]
allSymbolUsesInfo |> shouldEqual
[("option", ((4, 10), (4, 16)), ["abbrev"]); ("x", ((4, 7), (4, 8)), []);
("x", ((4, 23), (4, 24)), []);
("IsSome", ((4, 23), (4, 31)), ["member"; "prop"; "funky"]);
("x", ((4, 33), (4, 34)), []);
("IsNone", ((4, 33), (4, 41)), ["member"; "prop"; "funky"]);
("f", ((4, 4), (4, 5)), ["val"]);
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["class"]);
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["member"]);
("CompilationRepresentationFlags", ((6, 28), (6, 58)),
["enum"; "valuetype"]);
("UseNullAsTrueValue", ((6, 28), (6, 77)), ["field"; "static"; "8"]);
("string", ((9, 11), (9, 17)), ["abbrev"]);
("string", ((9, 11), (9, 17)), ["abbrev"]); ("A", ((8, 6), (8, 7)), []);
("B", ((9, 6), (9, 7)), []); ("C", ((7, 5), (7, 6)), ["union"]);
("IsItAnA", ((10, 13), (10, 20)), ["member"; "getter"; "funky"]);
("IsItAnAMethod", ((11, 13), (11, 26)), ["member"; "funky"]);
("x", ((10, 11), (10, 12)), []); ("x", ((10, 29), (10, 30)), []);
("A", ((10, 36), (10, 37)), []); ("B", ((10, 48), (10, 49)), []);
("x", ((11, 11), (11, 12)), []); ("x", ((11, 37), (11, 38)), []);
("A", ((11, 44), (11, 45)), []); ("B", ((11, 56), (11, 57)), []);
("C", ((13, 10), (13, 11)), ["union"]); ("x", ((13, 7), (13, 8)), []);
("x", ((13, 15), (13, 16)), []);
("IsItAnA", ((13, 15), (13, 24)), ["member"; "prop"; "funky"]);
("x", ((13, 25), (13, 26)), []);
("IsItAnAMethod", ((13, 25), (13, 40)), ["member"; "funky"]);
("g", ((13, 4), (13, 5)), ["val"]); ("M", ((2, 7), (2, 8)), ["module"])]
("x", ((4, 23), (4, 24)), []);
("IsSome", ((4, 23), (4, 31)), ["member"; "prop"; "funky"]);
("x", ((4, 33), (4, 34)), []);
("IsNone", ((4, 33), (4, 41)), ["member"; "prop"; "funky"]);
("f", ((4, 4), (4, 5)), ["val"]);
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["class"]);
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["member"]);
("CompilationRepresentationFlags", ((6, 28), (6, 58)), ["enum"; "valuetype"]);
("UseNullAsTrueValue", ((6, 28), (6, 77)), ["field"; "static"; "8"]);
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["class"]);
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["member"]);
("CompilationRepresentationFlags", ((6, 28), (6, 58)), ["enum"; "valuetype"]);
("UseNullAsTrueValue", ((6, 28), (6, 77)), ["field"; "static"; "8"]);
("string", ((9, 11), (9, 17)), ["abbrev"]);
("string", ((9, 11), (9, 17)), ["abbrev"]); ("A", ((8, 6), (8, 7)), []);
("B", ((9, 6), (9, 7)), []); ("C", ((7, 5), (7, 6)), ["union"]);
("IsItAnA", ((10, 13), (10, 20)), ["member"; "getter"; "funky"]);
("IsItAnAMethod", ((11, 13), (11, 26)), ["member"; "funky"]);
("x", ((10, 11), (10, 12)), []); ("x", ((10, 29), (10, 30)), []);
("A", ((10, 36), (10, 37)), []); ("B", ((10, 48), (10, 49)), []);
("x", ((11, 11), (11, 12)), []); ("x", ((11, 37), (11, 38)), []);
("A", ((11, 44), (11, 45)), []); ("B", ((11, 56), (11, 57)), []);
("C", ((13, 10), (13, 11)), ["union"]); ("x", ((13, 7), (13, 8)), []);
("x", ((13, 15), (13, 16)), []);
("IsItAnA", ((13, 15), (13, 24)), ["member"; "prop"; "funky"]);
("x", ((13, 25), (13, 26)), []);
("IsItAnAMethod", ((13, 25), (13, 40)), ["member"; "funky"]);
("g", ((13, 4), (13, 5)), ["val"]); ("M", ((2, 7), (2, 8)), ["module"])]

//--------------------------------------------

Expand Down