From aef3090206f272bf4dc426f1b658bb82cd55f34a Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 11 May 2026 11:41:11 -0500 Subject: [PATCH 1/4] Fix attributes silently dropped on unparenthesized tuple return types (#462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In `pars.fsy`, the `topType → topTupleType` rule discarded all `SynArgInfo` entries via `SynInfo.unnamedRetVal` whenever the return type was a bare multi-element tuple (e.g. `string * string`). Attributes placed before the tuple were parsed into the first element's `SynArgInfo` but then silently dropped, never reaching `SynBindingReturnInfo` or IL emission. The fix promotes attributes from the first element's `SynArgInfo` to the overall return `SynArgInfo` when they are non-empty, so that: static member Foo() : [] string * string = ... now correctly emits the attribute to `.param [0]` in IL, matching the behaviour of the parenthesized form `(string * string)`. Co-Authored-By: Claude Sonnet 4.6 --- src/Compiler/pars.fsy | 7 +- .../CustomAttributes/Basic/Basic.fs | 8 + .../CustomAttributes/Basic/ReturnType04.fs | 38 ++ .../ReturnTypeAttributeOnBareTuple.fs | 14 + .../ReturnTypeAttributeOnBareTuple.fs.bsl | 430 ++++++++++++++++++ .../SyntaxTree/Member/Auto property 08.fs.bsl | 19 +- .../SyntaxTree/Member/Auto property 09.fs.bsl | 19 +- .../SyntaxTree/Member/Auto property 10.fs.bsl | 19 +- 8 files changed, 550 insertions(+), 4 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/ReturnType04.fs create mode 100644 tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs create mode 100644 tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs.bsl diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 37eb245265d..088cd2073dc 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -6044,7 +6044,12 @@ topType: | topTupleType { let ty, rmdata = $1 - ty, (SynValInfo([], (match rmdata with [md] -> md | _ -> SynInfo.unnamedRetVal))) } + let retArgInfo = + match rmdata with + | [md] -> md + | SynArgInfo(attrs, _, _) :: _ when not attrs.IsEmpty -> SynArgInfo(attrs, false, None) + | _ -> SynInfo.unnamedRetVal + ty, SynValInfo([], retArgInfo) } topTupleType: | topAppType STAR topTupleTypeElements diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs index 2b51fbf11f7..3ff85e98a16 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs @@ -263,6 +263,14 @@ module CustomAttributes_Basic = |> verifyCompileAndRun |> shouldSucceed + // SOURCE=ReturnType04.fs # ReturnType04.fs + // Regression test for https://github.com/dotnet/fsharp/issues/462 + [] + let ``ReturnType04_fs`` compilation = + compilation + |> verifyCompileAndRun + |> shouldSucceed + // SOURCE=SanityCheck01.fs # SanityCheck01.fs [] let ``SanityCheck01_fs`` compilation = diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/ReturnType04.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/ReturnType04.fs new file mode 100644 index 00000000000..2b27ccd10af --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/ReturnType04.fs @@ -0,0 +1,38 @@ +// #Regression #Conformance #DeclarationElements #Attributes +// Regression test for https://github.com/dotnet/fsharp/issues/462 +// Attributes on return type of unparenthesized tuple must not be silently dropped. +// + +open System + +[] +type ReturnDescriptionAttribute(info: string) = + inherit Attribute() + member _.Info = info + +type T = + static member Parenthesized(name: string) : + [] + [] + (string * string) = + name, name + + static member Bare(name: string) : + [] + [] + string * string = + name, name + +let getAttrs (methodName: string) = + typeof + .GetMethod(methodName) + .ReturnParameter + .GetCustomAttributes(typeof, false) + |> Array.map (fun a -> (a :?> ReturnDescriptionAttribute).Info) + |> Array.sort + +let parenthesized = getAttrs "Parenthesized" +if parenthesized.Length <> 2 then failwithf "Parenthesized: expected 2 attributes, got %d" parenthesized.Length + +let bare = getAttrs "Bare" +if bare.Length <> 2 then failwithf "Bare: expected 2 attributes, got %d (bug #462 — attributes on unparenthesized tuple return type are silently dropped)" bare.Length diff --git a/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs new file mode 100644 index 00000000000..c8bd9a8d6b7 --- /dev/null +++ b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs @@ -0,0 +1,14 @@ +module M + +type T = + static member Parenthesized(name: string) : + [] + [] + (string * string) = + name, name + + static member Bare(name: string) : + [] + [] + string * string = + name, name diff --git a/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs.bsl b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs.bsl new file mode 100644 index 00000000000..cc2752527b6 --- /dev/null +++ b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs.bsl @@ -0,0 +1,430 @@ +ImplFile + (ParsedImplFileInput + ("/root/Attribute/ReturnTypeAttributeOnBareTuple.fs", false, + QualifiedNameOfFile M, [], + [SynModuleOrNamespace + ([M], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [T], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + ObjectModel + (Unspecified, + [Member + (SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (Some { IsInstance = false + IsDispatchSlot = false + IsOverrideOrExplicitImpl = false + IsFinal = false + GetterOrSetterIsCompilerGenerated = false + MemberKind = Member }, + SynValInfo + ([[SynArgInfo ([], false, Some name)]], + SynArgInfo + ([{ Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("first", Regular, + (5,28--5,35)), + (5,28--5,35)), (5,27--5,28), + Some (5,35--5,36), (5,27--5,36)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,10--5,36) }] + Range = (5,8--5,38) }; + { Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("second", Regular, + (6,28--6,36)), + (6,28--6,36)), (6,27--6,28), + Some (6,36--6,37), (6,27--6,37)) + Target = None + AppliesToGetterAndSetter = false + Range = (6,10--6,37) }] + Range = (6,8--6,39) }], false, None)), + None), + LongIdent + (SynLongIdent ([Parenthesized], [], [None]), None, + None, + Pats + [Paren + (Typed + (Named + (SynIdent (name, None), false, None, + (4,32--4,36)), + LongIdent + (SynLongIdent ([string], [], [None])), + (4,32--4,44)), (4,31--4,45))], None, + (4,18--4,45)), + Some + (SynBindingReturnInfo + (SignatureParameter + ([{ Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("first", Regular, + (5,28--5,35)), + (5,28--5,35)), (5,27--5,28), + Some (5,35--5,36), (5,27--5,36)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,10--5,36) }] + Range = (5,8--5,38) }; + { Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("second", Regular, + (6,28--6,36)), + (6,28--6,36)), (6,27--6,28), + Some (6,36--6,37), (6,27--6,37)) + Target = None + AppliesToGetterAndSetter = false + Range = (6,10--6,37) }] + Range = (6,8--6,39) }], false, None, + Paren + (Tuple + (false, + [Type + (LongIdent + (SynLongIdent + ([string], [], [None]))); + Star (7,16--7,17); + Type + (LongIdent + (SynLongIdent + ([string], [], [None])))], + (7,9--7,24)), (7,8--7,25)), + (5,8--7,25)), (5,8--7,25), + [{ Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("first", Regular, + (5,28--5,35)), (5,28--5,35)), + (5,27--5,28), Some (5,35--5,36), + (5,27--5,36)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,10--5,36) }] + Range = (5,8--5,38) }; + { Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("second", Regular, + (6,28--6,36)), (6,28--6,36)), + (6,27--6,28), Some (6,36--6,37), + (6,27--6,37)) + Target = None + AppliesToGetterAndSetter = false + Range = (6,10--6,37) }] + Range = (6,8--6,39) }], + { ColonRange = Some (4,46--4,47) })), + Typed + (Tuple + (false, [Ident name; Ident name], + [(8,16--8,17)], (8,12--8,22)), + SignatureParameter + ([{ Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("first", Regular, + (5,28--5,35)), (5,28--5,35)), + (5,27--5,28), Some (5,35--5,36), + (5,27--5,36)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,10--5,36) }] + Range = (5,8--5,38) }; + { Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("second", Regular, + (6,28--6,36)), (6,28--6,36)), + (6,27--6,28), Some (6,36--6,37), + (6,27--6,37)) + Target = None + AppliesToGetterAndSetter = false + Range = (6,10--6,37) }] + Range = (6,8--6,39) }], false, None, + Paren + (Tuple + (false, + [Type + (LongIdent + (SynLongIdent + ([string], [], [None]))); + Star (7,16--7,17); + Type + (LongIdent + (SynLongIdent + ([string], [], [None])))], + (7,9--7,24)), (7,8--7,25)), (5,8--7,25)), + (8,12--8,22)), (4,18--4,45), NoneAtInvisible, + { LeadingKeyword = + StaticMember ((4,4--4,10), (4,11--4,17)) + InlineKeyword = None + EqualsRange = Some (7,26--7,27) }), (4,4--8,22)); + Member + (SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((10,4), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (Some { IsInstance = false + IsDispatchSlot = false + IsOverrideOrExplicitImpl = false + IsFinal = false + GetterOrSetterIsCompilerGenerated = false + MemberKind = Member }, + SynValInfo + ([[SynArgInfo ([], false, Some name)]], + SynArgInfo + ([{ Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("first", Regular, + (11,28--11,35)), + (11,28--11,35)), + (11,27--11,28), + Some (11,35--11,36), + (11,27--11,36)) + Target = None + AppliesToGetterAndSetter = false + Range = (11,10--11,36) }] + Range = (11,8--11,38) }; + { Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("second", Regular, + (12,28--12,36)), + (12,28--12,36)), + (12,27--12,28), + Some (12,36--12,37), + (12,27--12,37)) + Target = None + AppliesToGetterAndSetter = false + Range = (12,10--12,37) }] + Range = (12,8--12,39) }], false, None)), + None), + LongIdent + (SynLongIdent ([Bare], [], [None]), None, None, + Pats + [Paren + (Typed + (Named + (SynIdent (name, None), false, None, + (10,23--10,27)), + LongIdent + (SynLongIdent ([string], [], [None])), + (10,23--10,35)), (10,22--10,36))], None, + (10,18--10,36)), + Some + (SynBindingReturnInfo + (Tuple + (false, + [Type + (SignatureParameter + ([{ Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], + [None]) + ArgExpr = + Paren + (Const + (String + ("first", Regular, + (11,28--11,35)), + (11,28--11,35)), + (11,27--11,28), + Some (11,35--11,36), + (11,27--11,36)) + Target = None + AppliesToGetterAndSetter = + false + Range = (11,10--11,36) }] + Range = (11,8--11,38) }; + { Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], + [None]) + ArgExpr = + Paren + (Const + (String + ("second", Regular, + (12,28--12,36)), + (12,28--12,36)), + (12,27--12,28), + Some (12,36--12,37), + (12,27--12,37)) + Target = None + AppliesToGetterAndSetter = + false + Range = (12,10--12,37) }] + Range = (12,8--12,39) }], false, + None, + LongIdent + (SynLongIdent + ([string], [], [None])), + (11,8--13,14))); Star (13,15--13,16); + Type + (LongIdent + (SynLongIdent ([string], [], [None])))], + (11,8--13,23)), (11,8--13,23), + [{ Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("first", Regular, + (11,28--11,35)), + (11,28--11,35)), (11,27--11,28), + Some (11,35--11,36), (11,27--11,36)) + Target = None + AppliesToGetterAndSetter = false + Range = (11,10--11,36) }] + Range = (11,8--11,38) }; + { Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], [None]) + ArgExpr = + Paren + (Const + (String + ("second", Regular, + (12,28--12,36)), + (12,28--12,36)), (12,27--12,28), + Some (12,36--12,37), (12,27--12,37)) + Target = None + AppliesToGetterAndSetter = false + Range = (12,10--12,37) }] + Range = (12,8--12,39) }], + { ColonRange = Some (10,37--10,38) })), + Typed + (Tuple + (false, [Ident name; Ident name], + [(14,16--14,17)], (14,12--14,22)), + Tuple + (false, + [Type + (SignatureParameter + ([{ Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], + [None]) + ArgExpr = + Paren + (Const + (String + ("first", Regular, + (11,28--11,35)), + (11,28--11,35)), + (11,27--11,28), + Some (11,35--11,36), + (11,27--11,36)) + Target = None + AppliesToGetterAndSetter = false + Range = (11,10--11,36) }] + Range = (11,8--11,38) }; + { Attributes = + [{ TypeName = + SynLongIdent + ([ReturnDescription], [], + [None]) + ArgExpr = + Paren + (Const + (String + ("second", Regular, + (12,28--12,36)), + (12,28--12,36)), + (12,27--12,28), + Some (12,36--12,37), + (12,27--12,37)) + Target = None + AppliesToGetterAndSetter = false + Range = (12,10--12,37) }] + Range = (12,8--12,39) }], false, + None, + LongIdent + (SynLongIdent ([string], [], [None])), + (11,8--13,14))); Star (13,15--13,16); + Type + (LongIdent + (SynLongIdent ([string], [], [None])))], + (11,8--13,23)), (14,12--14,22)), + (10,18--10,36), NoneAtInvisible, + { LeadingKeyword = + StaticMember ((10,4--10,10), (10,11--10,17)) + InlineKeyword = None + EqualsRange = Some (13,24--13,25) }), + (10,4--14,22))], (4,4--14,22)), [], None, (3,5--14,22), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--14,22))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--14,22), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl index c758fcae4a9..cb57654d7c9 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl @@ -46,4 +46,21 @@ ImplFile (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:22). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. -(6,0)-(6,1) parse error Incomplete structured construct at or before this point. Expected identifier, '(', '(*)' or other token. +(6,0)-(6,1) parse error Incomplete structured construct at or before this point. (no 'in' context found: [[NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; + NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; + NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSet; NONTERM_classMemberSpfnGetSet]; + [NONTERM_autoPropsDefnDecl]; [NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]]). Expected identifier, '(', '(*)' or other token. diff --git a/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl index 70796107bed..e8589af0fe7 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl @@ -69,4 +69,21 @@ ImplFile (5,4)-(5,10) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:23). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. -(5,4)-(5,10) parse error Incomplete structured construct at or before this point. Expected identifier, '(', '(*)' or other token. +(5,4)-(5,10) parse error Incomplete structured construct at or before this point. (no 'in' context found: [[NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; + NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; + NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSet; NONTERM_classMemberSpfnGetSet]; + [NONTERM_autoPropsDefnDecl]; [NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]]). Expected identifier, '(', '(*)' or other token. diff --git a/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl index ba04b1a3de7..bfa6c0034a7 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl @@ -45,4 +45,21 @@ ImplFile (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:22). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. -(5,0)-(5,0) parse error Incomplete structured construct at or before this point. Expected identifier, '(', '(*)' or other token. +(5,0)-(5,0) parse error Incomplete structured construct at or before this point. (no 'in' context found: [[NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; + NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; + NONTERM_classMemberSpfnGetSetElements]; + [NONTERM_classMemberSpfnGetSet; NONTERM_classMemberSpfnGetSet]; + [NONTERM_autoPropsDefnDecl]; [NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; + [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; + NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]]). Expected identifier, '(', '(*)' or other token. From 54295562e833869a3c675ece8ce645054325ff08 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 11 May 2026 12:22:00 -0500 Subject: [PATCH 2/4] Revert unintended Auto property bsl changes These were side effects of running TEST_UPDATE_BSL=1 and are unrelated to the fix for #462. --- .../SyntaxTree/Member/Auto property 08.fs.bsl | 19 +------------------ .../SyntaxTree/Member/Auto property 09.fs.bsl | 19 +------------------ .../SyntaxTree/Member/Auto property 10.fs.bsl | 19 +------------------ 3 files changed, 3 insertions(+), 54 deletions(-) diff --git a/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl index cb57654d7c9..c758fcae4a9 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl @@ -46,21 +46,4 @@ ImplFile (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:22). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. -(6,0)-(6,1) parse error Incomplete structured construct at or before this point. (no 'in' context found: [[NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; - NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; - NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSet; NONTERM_classMemberSpfnGetSet]; - [NONTERM_autoPropsDefnDecl]; [NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]]). Expected identifier, '(', '(*)' or other token. +(6,0)-(6,1) parse error Incomplete structured construct at or before this point. Expected identifier, '(', '(*)' or other token. diff --git a/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl index e8589af0fe7..70796107bed 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl @@ -69,21 +69,4 @@ ImplFile (5,4)-(5,10) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:23). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. -(5,4)-(5,10) parse error Incomplete structured construct at or before this point. (no 'in' context found: [[NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; - NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; - NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSet; NONTERM_classMemberSpfnGetSet]; - [NONTERM_autoPropsDefnDecl]; [NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]]). Expected identifier, '(', '(*)' or other token. +(5,4)-(5,10) parse error Incomplete structured construct at or before this point. Expected identifier, '(', '(*)' or other token. diff --git a/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl index bfa6c0034a7..ba04b1a3de7 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl @@ -45,21 +45,4 @@ ImplFile (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:22). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. -(5,0)-(5,0) parse error Incomplete structured construct at or before this point. (no 'in' context found: [[NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; - NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSetElements; NONTERM_classMemberSpfnGetSetElements; - NONTERM_classMemberSpfnGetSetElements]; - [NONTERM_classMemberSpfnGetSet; NONTERM_classMemberSpfnGetSet]; - [NONTERM_autoPropsDefnDecl]; [NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]; - [NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl; - NONTERM_autoPropsDefnDecl; NONTERM_autoPropsDefnDecl]]). Expected identifier, '(', '(*)' or other token. +(5,0)-(5,0) parse error Incomplete structured construct at or before this point. Expected identifier, '(', '(*)' or other token. From 9e5300ca602ded6b1462053ef2ad9c364ba1da1e Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 11 May 2026 14:02:57 -0500 Subject: [PATCH 3/4] Add release note for #462 fix --- docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/release-notes/.FSharp.Compiler.Service/11.0.100.md diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md new file mode 100644 index 00000000000..66d9de0e35c --- /dev/null +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -0,0 +1,3 @@ +### Fixed + +* Fix attributes on return type of unparenthesized tuple methods being silently dropped from IL. ([Issue #462](https://github.com/dotnet/fsharp/issues/462), [PR #19714](https://github.com/dotnet/fsharp/pull/19714)) From 6c4d94e7b60808afe93f2063c5b85a53a8682725 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 11 May 2026 15:52:28 -0500 Subject: [PATCH 4/4] Split SyntaxTree tests into separate minimal cases per reviewer feedback --- .../ReturnTypeAttributeOnBareTuple.fs | 13 +- .../ReturnTypeAttributeOnBareTuple.fs.bsl | 386 ++---------------- ...ReturnTypeAttributeOnParenthesizedTuple.fs | 7 + ...rnTypeAttributeOnParenthesizedTuple.fs.bsl | 123 ++++++ 4 files changed, 172 insertions(+), 357 deletions(-) create mode 100644 tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs create mode 100644 tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs.bsl diff --git a/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs index c8bd9a8d6b7..a00d6b4b53e 100644 --- a/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs +++ b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs @@ -1,14 +1,7 @@ module M type T = - static member Parenthesized(name: string) : - [] - [] - (string * string) = - name, name - - static member Bare(name: string) : - [] - [] + static member GetPair() : + [] string * string = - name, name + "", "" diff --git a/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs.bsl b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs.bsl index cc2752527b6..166ea4e9260 100644 --- a/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs.bsl +++ b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnBareTuple.fs.bsl @@ -24,254 +24,23 @@ ImplFile GetterOrSetterIsCompilerGenerated = false MemberKind = Member }, SynValInfo - ([[SynArgInfo ([], false, Some name)]], + ([[]], SynArgInfo ([{ Attributes = [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("first", Regular, - (5,28--5,35)), - (5,28--5,35)), (5,27--5,28), - Some (5,35--5,36), (5,27--5,36)) + SynLongIdent ([A], [], [None]) + ArgExpr = Const (Unit, (5,10--5,11)) Target = None AppliesToGetterAndSetter = false - Range = (5,10--5,36) }] - Range = (5,8--5,38) }; - { Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("second", Regular, - (6,28--6,36)), - (6,28--6,36)), (6,27--6,28), - Some (6,36--6,37), (6,27--6,37)) - Target = None - AppliesToGetterAndSetter = false - Range = (6,10--6,37) }] - Range = (6,8--6,39) }], false, None)), + Range = (5,10--5,11) }] + Range = (5,8--5,13) }], false, None)), None), LongIdent - (SynLongIdent ([Parenthesized], [], [None]), None, - None, + (SynLongIdent ([GetPair], [], [None]), None, None, Pats [Paren - (Typed - (Named - (SynIdent (name, None), false, None, - (4,32--4,36)), - LongIdent - (SynLongIdent ([string], [], [None])), - (4,32--4,44)), (4,31--4,45))], None, - (4,18--4,45)), - Some - (SynBindingReturnInfo - (SignatureParameter - ([{ Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("first", Regular, - (5,28--5,35)), - (5,28--5,35)), (5,27--5,28), - Some (5,35--5,36), (5,27--5,36)) - Target = None - AppliesToGetterAndSetter = false - Range = (5,10--5,36) }] - Range = (5,8--5,38) }; - { Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("second", Regular, - (6,28--6,36)), - (6,28--6,36)), (6,27--6,28), - Some (6,36--6,37), (6,27--6,37)) - Target = None - AppliesToGetterAndSetter = false - Range = (6,10--6,37) }] - Range = (6,8--6,39) }], false, None, - Paren - (Tuple - (false, - [Type - (LongIdent - (SynLongIdent - ([string], [], [None]))); - Star (7,16--7,17); - Type - (LongIdent - (SynLongIdent - ([string], [], [None])))], - (7,9--7,24)), (7,8--7,25)), - (5,8--7,25)), (5,8--7,25), - [{ Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("first", Regular, - (5,28--5,35)), (5,28--5,35)), - (5,27--5,28), Some (5,35--5,36), - (5,27--5,36)) - Target = None - AppliesToGetterAndSetter = false - Range = (5,10--5,36) }] - Range = (5,8--5,38) }; - { Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("second", Regular, - (6,28--6,36)), (6,28--6,36)), - (6,27--6,28), Some (6,36--6,37), - (6,27--6,37)) - Target = None - AppliesToGetterAndSetter = false - Range = (6,10--6,37) }] - Range = (6,8--6,39) }], - { ColonRange = Some (4,46--4,47) })), - Typed - (Tuple - (false, [Ident name; Ident name], - [(8,16--8,17)], (8,12--8,22)), - SignatureParameter - ([{ Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("first", Regular, - (5,28--5,35)), (5,28--5,35)), - (5,27--5,28), Some (5,35--5,36), - (5,27--5,36)) - Target = None - AppliesToGetterAndSetter = false - Range = (5,10--5,36) }] - Range = (5,8--5,38) }; - { Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("second", Regular, - (6,28--6,36)), (6,28--6,36)), - (6,27--6,28), Some (6,36--6,37), - (6,27--6,37)) - Target = None - AppliesToGetterAndSetter = false - Range = (6,10--6,37) }] - Range = (6,8--6,39) }], false, None, - Paren - (Tuple - (false, - [Type - (LongIdent - (SynLongIdent - ([string], [], [None]))); - Star (7,16--7,17); - Type - (LongIdent - (SynLongIdent - ([string], [], [None])))], - (7,9--7,24)), (7,8--7,25)), (5,8--7,25)), - (8,12--8,22)), (4,18--4,45), NoneAtInvisible, - { LeadingKeyword = - StaticMember ((4,4--4,10), (4,11--4,17)) - InlineKeyword = None - EqualsRange = Some (7,26--7,27) }), (4,4--8,22)); - Member - (SynBinding - (None, Normal, false, false, [], - PreXmlDoc ((10,4), FSharp.Compiler.Xml.XmlDocCollector), - SynValData - (Some { IsInstance = false - IsDispatchSlot = false - IsOverrideOrExplicitImpl = false - IsFinal = false - GetterOrSetterIsCompilerGenerated = false - MemberKind = Member }, - SynValInfo - ([[SynArgInfo ([], false, Some name)]], - SynArgInfo - ([{ Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("first", Regular, - (11,28--11,35)), - (11,28--11,35)), - (11,27--11,28), - Some (11,35--11,36), - (11,27--11,36)) - Target = None - AppliesToGetterAndSetter = false - Range = (11,10--11,36) }] - Range = (11,8--11,38) }; - { Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("second", Regular, - (12,28--12,36)), - (12,28--12,36)), - (12,27--12,28), - Some (12,36--12,37), - (12,27--12,37)) - Target = None - AppliesToGetterAndSetter = false - Range = (12,10--12,37) }] - Range = (12,8--12,39) }], false, None)), - None), - LongIdent - (SynLongIdent ([Bare], [], [None]), None, None, - Pats - [Paren - (Typed - (Named - (SynIdent (name, None), false, None, - (10,23--10,27)), - LongIdent - (SynLongIdent ([string], [], [None])), - (10,23--10,35)), (10,22--10,36))], None, - (10,18--10,36)), + (Const (Unit, (4,25--4,27)), (4,25--4,27))], + None, (4,18--4,27)), Some (SynBindingReturnInfo (Tuple @@ -281,150 +50,73 @@ ImplFile ([{ Attributes = [{ TypeName = SynLongIdent - ([ReturnDescription], [], - [None]) + ([A], [], [None]) ArgExpr = - Paren - (Const - (String - ("first", Regular, - (11,28--11,35)), - (11,28--11,35)), - (11,27--11,28), - Some (11,35--11,36), - (11,27--11,36)) + Const (Unit, (5,10--5,11)) Target = None AppliesToGetterAndSetter = false - Range = (11,10--11,36) }] - Range = (11,8--11,38) }; - { Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], - [None]) - ArgExpr = - Paren - (Const - (String - ("second", Regular, - (12,28--12,36)), - (12,28--12,36)), - (12,27--12,28), - Some (12,36--12,37), - (12,27--12,37)) - Target = None - AppliesToGetterAndSetter = - false - Range = (12,10--12,37) }] - Range = (12,8--12,39) }], false, + Range = (5,10--5,11) }] + Range = (5,8--5,13) }], false, None, LongIdent (SynLongIdent ([string], [], [None])), - (11,8--13,14))); Star (13,15--13,16); + (5,8--6,14))); Star (6,15--6,16); Type (LongIdent (SynLongIdent ([string], [], [None])))], - (11,8--13,23)), (11,8--13,23), + (5,8--6,23)), (5,8--6,23), [{ Attributes = [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("first", Regular, - (11,28--11,35)), - (11,28--11,35)), (11,27--11,28), - Some (11,35--11,36), (11,27--11,36)) + SynLongIdent ([A], [], [None]) + ArgExpr = Const (Unit, (5,10--5,11)) Target = None AppliesToGetterAndSetter = false - Range = (11,10--11,36) }] - Range = (11,8--11,38) }; - { Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], [None]) - ArgExpr = - Paren - (Const - (String - ("second", Regular, - (12,28--12,36)), - (12,28--12,36)), (12,27--12,28), - Some (12,36--12,37), (12,27--12,37)) - Target = None - AppliesToGetterAndSetter = false - Range = (12,10--12,37) }] - Range = (12,8--12,39) }], - { ColonRange = Some (10,37--10,38) })), + Range = (5,10--5,11) }] + Range = (5,8--5,13) }], + { ColonRange = Some (4,28--4,29) })), Typed (Tuple - (false, [Ident name; Ident name], - [(14,16--14,17)], (14,12--14,22)), + (false, + [Const + (String ("", Regular, (7,12--7,14)), + (7,12--7,14)); + Const + (String ("", Regular, (7,16--7,18)), + (7,16--7,18))], [(7,14--7,15)], + (7,12--7,18)), Tuple (false, [Type (SignatureParameter ([{ Attributes = [{ TypeName = - SynLongIdent - ([ReturnDescription], [], - [None]) - ArgExpr = - Paren - (Const - (String - ("first", Regular, - (11,28--11,35)), - (11,28--11,35)), - (11,27--11,28), - Some (11,35--11,36), - (11,27--11,36)) - Target = None - AppliesToGetterAndSetter = false - Range = (11,10--11,36) }] - Range = (11,8--11,38) }; - { Attributes = - [{ TypeName = - SynLongIdent - ([ReturnDescription], [], - [None]) + SynLongIdent ([A], [], [None]) ArgExpr = - Paren - (Const - (String - ("second", Regular, - (12,28--12,36)), - (12,28--12,36)), - (12,27--12,28), - Some (12,36--12,37), - (12,27--12,37)) + Const (Unit, (5,10--5,11)) Target = None AppliesToGetterAndSetter = false - Range = (12,10--12,37) }] - Range = (12,8--12,39) }], false, - None, + Range = (5,10--5,11) }] + Range = (5,8--5,13) }], false, None, LongIdent (SynLongIdent ([string], [], [None])), - (11,8--13,14))); Star (13,15--13,16); + (5,8--6,14))); Star (6,15--6,16); Type (LongIdent (SynLongIdent ([string], [], [None])))], - (11,8--13,23)), (14,12--14,22)), - (10,18--10,36), NoneAtInvisible, + (5,8--6,23)), (7,12--7,18)), (4,18--4,27), + NoneAtInvisible, { LeadingKeyword = - StaticMember ((10,4--10,10), (10,11--10,17)) + StaticMember ((4,4--4,10), (4,11--4,17)) InlineKeyword = None - EqualsRange = Some (13,24--13,25) }), - (10,4--14,22))], (4,4--14,22)), [], None, (3,5--14,22), + EqualsRange = Some (6,24--6,25) }), (4,4--7,18))], + (4,4--7,18)), [], None, (3,5--7,18), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) - WithKeyword = None })], (3,0--14,22))], + WithKeyword = None })], (3,0--7,18))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, - (1,0--14,22), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + (1,0--7,18), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs new file mode 100644 index 00000000000..7a0bfc47e7f --- /dev/null +++ b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs @@ -0,0 +1,7 @@ +module M + +type T = + static member GetPair() : + [] + (string * string) = + "", "" diff --git a/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs.bsl b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs.bsl new file mode 100644 index 00000000000..41b874e5280 --- /dev/null +++ b/tests/service/data/SyntaxTree/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs.bsl @@ -0,0 +1,123 @@ +ImplFile + (ParsedImplFileInput + ("/root/Attribute/ReturnTypeAttributeOnParenthesizedTuple.fs", false, + QualifiedNameOfFile M, [], + [SynModuleOrNamespace + ([M], false, NamedModule, + [Types + ([SynTypeDefn + (SynComponentInfo + ([], None, [], [T], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (3,5--3,6)), + ObjectModel + (Unspecified, + [Member + (SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (Some { IsInstance = false + IsDispatchSlot = false + IsOverrideOrExplicitImpl = false + IsFinal = false + GetterOrSetterIsCompilerGenerated = false + MemberKind = Member }, + SynValInfo + ([[]], + SynArgInfo + ([{ Attributes = + [{ TypeName = + SynLongIdent ([A], [], [None]) + ArgExpr = Const (Unit, (5,10--5,11)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,10--5,11) }] + Range = (5,8--5,13) }], false, None)), + None), + LongIdent + (SynLongIdent ([GetPair], [], [None]), None, None, + Pats + [Paren + (Const (Unit, (4,25--4,27)), (4,25--4,27))], + None, (4,18--4,27)), + Some + (SynBindingReturnInfo + (SignatureParameter + ([{ Attributes = + [{ TypeName = + SynLongIdent ([A], [], [None]) + ArgExpr = Const (Unit, (5,10--5,11)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,10--5,11) }] + Range = (5,8--5,13) }], false, None, + Paren + (Tuple + (false, + [Type + (LongIdent + (SynLongIdent + ([string], [], [None]))); + Star (6,16--6,17); + Type + (LongIdent + (SynLongIdent + ([string], [], [None])))], + (6,9--6,24)), (6,8--6,25)), + (5,8--6,25)), (5,8--6,25), + [{ Attributes = + [{ TypeName = + SynLongIdent ([A], [], [None]) + ArgExpr = Const (Unit, (5,10--5,11)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,10--5,11) }] + Range = (5,8--5,13) }], + { ColonRange = Some (4,28--4,29) })), + Typed + (Tuple + (false, + [Const + (String ("", Regular, (7,12--7,14)), + (7,12--7,14)); + Const + (String ("", Regular, (7,16--7,18)), + (7,16--7,18))], [(7,14--7,15)], + (7,12--7,18)), + SignatureParameter + ([{ Attributes = + [{ TypeName = + SynLongIdent ([A], [], [None]) + ArgExpr = Const (Unit, (5,10--5,11)) + Target = None + AppliesToGetterAndSetter = false + Range = (5,10--5,11) }] + Range = (5,8--5,13) }], false, None, + Paren + (Tuple + (false, + [Type + (LongIdent + (SynLongIdent + ([string], [], [None]))); + Star (6,16--6,17); + Type + (LongIdent + (SynLongIdent + ([string], [], [None])))], + (6,9--6,24)), (6,8--6,25)), (5,8--6,25)), + (7,12--7,18)), (4,18--4,27), NoneAtInvisible, + { LeadingKeyword = + StaticMember ((4,4--4,10), (4,11--4,17)) + InlineKeyword = None + EqualsRange = Some (6,26--6,27) }), (4,4--7,18))], + (4,4--7,18)), [], None, (3,5--7,18), + { LeadingKeyword = Type (3,0--3,4) + EqualsRange = Some (3,7--3,8) + WithKeyword = None })], (3,0--7,18))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,18), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set []))