diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs
index 072dc76a100..db54e06faf6 100644
--- a/src/Compiler/Checking/NicePrint.fs
+++ b/src/Compiler/Checking/NicePrint.fs
@@ -1795,7 +1795,7 @@ module TastDefinitionPrinting =
let overallL = staticL ^^ WordL.keywordMember ^^ (nameL |> addColonL) ^^ typL
layoutXmlDocOfEventInfo denv infoReader einfo overallL
- let layoutPropInfo denv (infoReader: InfoReader) m (pinfo: PropInfo) =
+ let layoutPropInfo denv (infoReader: InfoReader) m (pinfo: PropInfo) : Layout list =
let amap = infoReader.amap
let isPublicGetterSetter (getter: MethInfo) (setter: MethInfo) =
@@ -1804,13 +1804,33 @@ module TastDefinitionPrinting =
| Some gRef, Some sRef -> isPublicAccess gRef.Accessibility && isPublicAccess sRef.Accessibility
| _ -> false
+ let (|MixedAccessibilityGetterAndSetter|_|) (pinfo: PropInfo) =
+ if not (pinfo.HasGetter && pinfo.HasSetter) then
+ None
+ else
+ match pinfo.GetterMethod.ArbitraryValRef, pinfo.SetterMethod.ArbitraryValRef with
+ | Some getValRef, Some setValRef ->
+ if getValRef.Accessibility = setValRef.Accessibility then
+ None
+ else
+ Some (getValRef, setValRef)
+ | _ -> None
+
match pinfo.ArbitraryValRef with
| Some vref ->
- let propL = PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv infoReader vref
- if pinfo.HasGetter && pinfo.HasSetter && not pinfo.IsIndexer && isPublicGetterSetter pinfo.GetterMethod pinfo.SetterMethod then
- propL ^^ wordL (tagKeyword "with") ^^ wordL (tagText "get, set")
- else
- propL
+ match pinfo with
+ | MixedAccessibilityGetterAndSetter(getValRef, setValRef) ->
+ let getSuffix = if pinfo.IsIndexer then emptyL else wordL (tagKeyword "with") ^^ wordL (tagText "get")
+ [
+ PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv infoReader getValRef ^^ getSuffix
+ PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv infoReader setValRef
+ ]
+ | _ ->
+ let propL = PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv infoReader vref
+ if pinfo.HasGetter && pinfo.HasSetter && not pinfo.IsIndexer && isPublicGetterSetter pinfo.GetterMethod pinfo.SetterMethod then
+ [ propL ^^ wordL (tagKeyword "with") ^^ wordL (tagText "get, set") ]
+ else
+ [ propL ]
| None ->
let modifierAndMember =
@@ -1822,7 +1842,7 @@ module TastDefinitionPrinting =
let nameL = ConvertValLogicalNameToDisplayLayout false (tagProperty >> tagNavArbValRef pinfo.ArbitraryValRef >> wordL) pinfo.PropertyName
let typL = layoutType denv (pinfo.GetPropertyType(amap, m))
let overallL = modifierAndMember ^^ (nameL |> addColonL) ^^ typL
- layoutXmlDocOfPropInfo denv infoReader pinfo overallL
+ [ layoutXmlDocOfPropInfo denv infoReader pinfo overallL ]
let layoutTyconDefn (denv: DisplayEnv) (infoReader: InfoReader) ad m simplified isFirstType (tcref: TyconRef) =
let g = denv.g
@@ -1993,7 +2013,9 @@ module TastDefinitionPrinting =
let propLs =
props
- |> List.map (fun x -> (true, x.IsStatic, x.PropertyName, 0, 0), layoutPropInfo denv infoReader m x)
+ |> List.collect (fun x ->
+ layoutPropInfo denv infoReader m x
+ |> List.map (fun layout -> (true, x.IsStatic, x.PropertyName, 0, 0), layout))
|> List.sortBy fst
|> List.map snd
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 93ff861fe68..0145bcfa609 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -252,6 +252,7 @@
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/MemberTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/MemberTests.fs
new file mode 100644
index 00000000000..2452a900881
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/MemberTests.fs
@@ -0,0 +1,52 @@
+module Signatures.MemberTests
+
+open Xunit
+open FsUnit
+open FSharp.Test.Compiler
+open Signatures.TestHelpers
+
+[]
+let ``Verify that the visibility difference between the getter and setter results in two distinct member signatures`` () =
+ FSharp
+ """
+module Foo
+
+type Foo() =
+ member f.X with internal get (key1, key2) = true and public set (key1, key2) value = ()
+"""
+ |> printSignatures
+ |> should
+ equal
+ """
+module Foo
+
+type Foo =
+
+ new: unit -> Foo
+
+ member internal X: key1: obj * key2: obj -> bool with get
+
+ member X: key1: obj * key2: obj -> obj with set"""
+
+[]
+let ``Getter should have explicit with get suffix`` () =
+ FSharp
+ """
+module Foo
+
+type Foo() =
+ member f.Y with public get () = 'y' and internal set y = ignore y
+"""
+ |> printSignatures
+ |> should
+ equal
+ """
+module Foo
+
+type Foo =
+
+ new: unit -> Foo
+
+ member Y: char with get
+
+ member internal Y: char with set"""
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/setters.fsx b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/setters.fsx
new file mode 100644
index 00000000000..47f7601baba
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/setters.fsx
@@ -0,0 +1,3 @@
+type Foo() =
+ member f.X with internal get (key1, key2) = true and public set (key1, key2) value = ()
+ member f.Y with public get () = 'y' and internal set y = ignore y