From a4246f0575534c17d58dc4d8913d2cdd925343d3 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 5 May 2025 15:42:02 +0100 Subject: [PATCH 01/13] Add new rules --- src/Compiler/pars.fsy | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 7cac0ad0dc0..42f74f7649c 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4416,6 +4416,16 @@ declExpr: { let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } SynExpr.YieldOrReturn(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) } + | YIELD declExpr COLON typ + { let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } + let typedExpr = SynExpr.Typed($2, $4, unionRanges $2.Range $4.Range) + SynExpr.YieldOrReturn(($1, not $1), typedExpr, (unionRanges (rhs parseState 1) $4.Range), trivia) } + + | YIELD_BANG declExpr COLON typ + { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } + let typedExpr = SynExpr.Typed($2, $4, unionRanges $2.Range $4.Range) + SynExpr.YieldOrReturnFrom(($1, not $1), typedExpr, (unionRanges (rhs parseState 1) $2.Range), trivia) } + | YIELD_BANG declExpr { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } SynExpr.YieldOrReturnFrom(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) } From 5fe09e08c6b2ccff02924d86ac9e59e9fe32151f Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 5 May 2025 15:42:19 +0100 Subject: [PATCH 02/13] Add syntax tree tests --- .../data/SyntaxTree/Expression/Return 01.fs | 7 ++++ .../SyntaxTree/Expression/Return 01.fs.bsl | 36 +++++++++++++++++ .../data/SyntaxTree/Expression/Return 02.fs | 7 ++++ .../SyntaxTree/Expression/Return 02.fs.bsl | 39 ++++++++++++++++++ .../data/SyntaxTree/Expression/Return 03.fs | 7 ++++ .../SyntaxTree/Expression/Return 03.fs.bsl | 36 +++++++++++++++++ .../data/SyntaxTree/Expression/Return 04.fs | 7 ++++ .../SyntaxTree/Expression/Return 04.fs.bsl | 39 ++++++++++++++++++ .../data/SyntaxTree/Expression/Return 05.fs | 7 ++++ .../SyntaxTree/Expression/Return 05.fs.bsl | 32 +++++++++++++++ .../data/SyntaxTree/Expression/Return 06.fs | 7 ++++ .../SyntaxTree/Expression/Return 06.fs.bsl | 34 ++++++++++++++++ .../SyntaxTree/Expression/ReturnBang 01.fs | 7 ++++ .../Expression/ReturnBang 01.fs.bsl | 37 +++++++++++++++++ .../SyntaxTree/Expression/ReturnBang 02.fs | 7 ++++ .../Expression/ReturnBang 02.fs.bsl | 40 +++++++++++++++++++ .../data/SyntaxTree/Expression/Yield 01.fs | 4 ++ .../SyntaxTree/Expression/Yield 01.fs.bsl | 24 +++++++++++ .../data/SyntaxTree/Expression/Yield 02.fs | 6 +++ .../SyntaxTree/Expression/Yield 02.fs.bsl | 31 ++++++++++++++ .../data/SyntaxTree/Expression/Yield 03.fs | 6 +++ .../SyntaxTree/Expression/Yield 03.fs.bsl | 34 ++++++++++++++++ .../data/SyntaxTree/Expression/Yield 04.fs | 4 ++ .../SyntaxTree/Expression/Yield 04.fs.bsl | 26 ++++++++++++ .../SyntaxTree/Expression/YieldBang 01.fs | 5 +++ .../SyntaxTree/Expression/YieldBang 01.fs.bsl | 25 ++++++++++++ .../SyntaxTree/Expression/YieldBang 02.fs | 4 ++ .../SyntaxTree/Expression/YieldBang 02.fs.bsl | 27 +++++++++++++ .../SyntaxTree/Expression/YieldBang 03.fs | 6 +++ .../SyntaxTree/Expression/YieldBang 03.fs.bsl | 32 +++++++++++++++ .../SyntaxTree/Expression/YieldBang 04.fs | 7 ++++ .../SyntaxTree/Expression/YieldBang 04.fs.bsl | 35 ++++++++++++++++ 32 files changed, 625 insertions(+) create mode 100644 tests/service/data/SyntaxTree/Expression/Return 01.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Return 02.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Return 03.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Return 04.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Return 05.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Return 06.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs create mode 100644 tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs create mode 100644 tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 01.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 02.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 03.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 04.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 01.fs create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 02.fs create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 03.fs create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 04.fs create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl diff --git a/tests/service/data/SyntaxTree/Expression/Return 01.fs b/tests/service/data/SyntaxTree/Expression/Return 01.fs new file mode 100644 index 00000000000..51695776a55 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 01.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return new MyType() : IDisposable + } + diff --git a/tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl new file mode 100644 index 00000000000..2e14fc025c9 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl @@ -0,0 +1,36 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Return 01.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), + Typed + (New + (false, + LongIdent (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,25--5,27)), (5,15--5,27)), + LongIdent + (SynLongIdent ([IDisposable], [], [None])), + (5,15--5,41)), (5,8--5,41), + { YieldOrReturnKeyword = (5,8--5,14) }), (4,10--6,5)), + (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 02.fs b/tests/service/data/SyntaxTree/Expression/Return 02.fs new file mode 100644 index 00000000000..2bfa5ecf136 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 02.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return (new MyType() : IDisposable) + } + diff --git a/tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl new file mode 100644 index 00000000000..59ab0dac633 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl @@ -0,0 +1,39 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Return 02.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), + Paren + (Typed + (New + (false, + LongIdent + (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,26--5,28)), (5,16--5,28)), + LongIdent + (SynLongIdent ([IDisposable], [], [None])), + (5,16--5,42)), (5,15--5,16), Some (5,42--5,43), + (5,15--5,43)), (5,8--5,43), + { YieldOrReturnKeyword = (5,8--5,14) }), (4,10--6,5)), + (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 03.fs b/tests/service/data/SyntaxTree/Expression/Return 03.fs new file mode 100644 index 00000000000..ddf6e531468 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 03.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return new MyType() :> IDisposable + } + diff --git a/tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl new file mode 100644 index 00000000000..68d17129ef3 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl @@ -0,0 +1,36 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Return 03.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), + Upcast + (New + (false, + LongIdent (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,25--5,27)), (5,15--5,27)), + LongIdent + (SynLongIdent ([IDisposable], [], [None])), + (5,15--5,42)), (5,8--5,42), + { YieldOrReturnKeyword = (5,8--5,14) }), (4,10--6,5)), + (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 04.fs b/tests/service/data/SyntaxTree/Expression/Return 04.fs new file mode 100644 index 00000000000..933a72820cc --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 04.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return (new MyType() :> IDisposable) + } + diff --git a/tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl new file mode 100644 index 00000000000..00afeeaa092 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl @@ -0,0 +1,39 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Return 04.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), + Paren + (Upcast + (New + (false, + LongIdent + (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,26--5,28)), (5,16--5,28)), + LongIdent + (SynLongIdent ([IDisposable], [], [None])), + (5,16--5,43)), (5,15--5,16), Some (5,43--5,44), + (5,15--5,44)), (5,8--5,44), + { YieldOrReturnKeyword = (5,8--5,14) }), (4,10--6,5)), + (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 05.fs b/tests/service/data/SyntaxTree/Expression/Return 05.fs new file mode 100644 index 00000000000..bd1ef865815 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 05.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return new MyType() + } + diff --git a/tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl new file mode 100644 index 00000000000..06b83071496 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl @@ -0,0 +1,32 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Return 05.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), + New + (false, + LongIdent (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,25--5,27)), (5,15--5,27)), + (5,8--5,27), { YieldOrReturnKeyword = (5,8--5,14) }), + (4,10--6,5)), (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 06.fs b/tests/service/data/SyntaxTree/Expression/Return 06.fs new file mode 100644 index 00000000000..95941f09646 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 06.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return (new MyType()) + } + diff --git a/tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl new file mode 100644 index 00000000000..fc57c66f5db --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl @@ -0,0 +1,34 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Return 06.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), + Paren + (New + (false, + LongIdent (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,26--5,28)), (5,16--5,28)), + (5,15--5,16), Some (5,28--5,29), (5,15--5,29)), + (5,8--5,29), { YieldOrReturnKeyword = (5,8--5,14) }), + (4,10--6,5)), (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs b/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs new file mode 100644 index 00000000000..009a45b4c08 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return! new MyType() : IDisposable + } + diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl new file mode 100644 index 00000000000..537dde46f62 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl @@ -0,0 +1,37 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/ReturnBang 01.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturnFrom + ((false, true), + Typed + (New + (false, + LongIdent (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,26--5,28)), (5,16--5,28)), + LongIdent + (SynLongIdent ([IDisposable], [], [None])), + (5,16--5,42)), (5,8--5,28), + { YieldOrReturnFromKeyword = (5,8--5,15) }), + (4,10--6,5)), (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs b/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs new file mode 100644 index 00000000000..91fd750a01b --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return! (new MyType() : IDisposable) + } + diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl new file mode 100644 index 00000000000..aa1df37ee9a --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl @@ -0,0 +1,40 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/ReturnBang 02.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturnFrom + ((false, true), + Paren + (Typed + (New + (false, + LongIdent + (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,27--5,29)), (5,17--5,29)), + LongIdent + (SynLongIdent ([IDisposable], [], [None])), + (5,17--5,43)), (5,16--5,17), Some (5,43--5,44), + (5,16--5,44)), (5,8--5,44), + { YieldOrReturnFromKeyword = (5,8--5,15) }), + (4,10--6,5)), (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Yield 01.fs b/tests/service/data/SyntaxTree/Expression/Yield 01.fs new file mode 100644 index 00000000000..8f3656d8fcb --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 01.fs @@ -0,0 +1,4 @@ +module Module + +yield [ 1 .. 10 ]: int list + diff --git a/tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl new file mode 100644 index 00000000000..97efec2aec0 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl @@ -0,0 +1,24 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Yield 01.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (YieldOrReturn + ((true, false), + Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (3,8--3,9))), (3,10--3,12), + Some (Const (Int32 10, (3,13--3,15))), (3,8--3,9), + (3,13--3,15), (3,8--3,15)), (3,6--3,17)), + App + (LongIdent (SynLongIdent ([list], [], [None])), None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], None, + true, (3,19--3,27)), (3,6--3,27)), (3,0--3,27), + { YieldOrReturnKeyword = (3,0--3,5) }), (3,0--3,27))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,27), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Yield 02.fs b/tests/service/data/SyntaxTree/Expression/Yield 02.fs new file mode 100644 index 00000000000..0573f7af70a --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 02.fs @@ -0,0 +1,6 @@ +module Module + +seq { + yield [ 1 .. 10 ]: int list +} + diff --git a/tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl new file mode 100644 index 00000000000..a08ff30db77 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl @@ -0,0 +1,31 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Yield 02.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident seq, + ComputationExpr + (false, + YieldOrReturn + ((true, false), + Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (4,12--4,13))), + (4,14--4,16), + Some (Const (Int32 10, (4,17--4,19))), + (4,12--4,13), (4,17--4,19), (4,12--4,19)), + (4,10--4,21)), + App + (LongIdent (SynLongIdent ([list], [], [None])), None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (4,23--4,31)), (4,10--4,31)), + (4,4--4,31), { YieldOrReturnKeyword = (4,4--4,9) }), + (3,4--5,1)), (3,0--5,1)), (3,0--5,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Yield 03.fs b/tests/service/data/SyntaxTree/Expression/Yield 03.fs new file mode 100644 index 00000000000..d5c1f13e24f --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 03.fs @@ -0,0 +1,6 @@ +module Module + +seq { + yield ([ 1 .. 10 ]: int list) +} + diff --git a/tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl new file mode 100644 index 00000000000..a5710c8bb9c --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl @@ -0,0 +1,34 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Yield 03.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident seq, + ComputationExpr + (false, + YieldOrReturn + ((true, false), + Paren + (Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (4,13--4,14))), + (4,15--4,17), + Some (Const (Int32 10, (4,18--4,20))), + (4,13--4,14), (4,18--4,20), (4,13--4,20)), + (4,11--4,22)), + App + (LongIdent (SynLongIdent ([list], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], + [], None, true, (4,24--4,32)), (4,11--4,32)), + (4,10--4,11), Some (4,32--4,33), (4,10--4,33)), + (4,4--4,33), { YieldOrReturnKeyword = (4,4--4,9) }), + (3,4--5,1)), (3,0--5,1)), (3,0--5,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Yield 04.fs b/tests/service/data/SyntaxTree/Expression/Yield 04.fs new file mode 100644 index 00000000000..e31740cb322 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 04.fs @@ -0,0 +1,4 @@ +module Module + +yield ([ 1 .. 10 ]: int list) + diff --git a/tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl new file mode 100644 index 00000000000..2363fe76684 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl @@ -0,0 +1,26 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Yield 04.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (YieldOrReturn + ((true, false), + Paren + (Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (3,9--3,10))), (3,11--3,13), + Some (Const (Int32 10, (3,14--3,16))), (3,9--3,10), + (3,14--3,16), (3,9--3,16)), (3,7--3,18)), + App + (LongIdent (SynLongIdent ([list], [], [None])), None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (3,20--3,28)), (3,7--3,28)), (3,6--3,7), + Some (3,28--3,29), (3,6--3,29)), (3,0--3,29), + { YieldOrReturnKeyword = (3,0--3,5) }), (3,0--3,29))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,29), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs b/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs new file mode 100644 index 00000000000..dbfd3f4beef --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs @@ -0,0 +1,5 @@ +module Module + +yield! [ 1 .. 10 ]: int list + + diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl new file mode 100644 index 00000000000..a469799bff8 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl @@ -0,0 +1,25 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/YieldBang 01.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (YieldOrReturnFrom + ((true, false), + Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (3,9--3,10))), (3,11--3,13), + Some (Const (Int32 10, (3,14--3,16))), (3,9--3,10), + (3,14--3,16), (3,9--3,16)), (3,7--3,18)), + App + (LongIdent (SynLongIdent ([list], [], [None])), None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], None, + true, (3,20--3,28)), (3,7--3,28)), (3,0--3,18), + { YieldOrReturnFromKeyword = (3,0--3,6) }), (3,0--3,18))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,18), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs b/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs new file mode 100644 index 00000000000..ed1bd0fea97 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs @@ -0,0 +1,4 @@ +module Module + +yield! ([ 1 .. 10 ]: int list) + diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl new file mode 100644 index 00000000000..3f7d1e2526b --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl @@ -0,0 +1,27 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/YieldBang 02.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (YieldOrReturnFrom + ((true, false), + Paren + (Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (3,10--3,11))), (3,12--3,14), + Some (Const (Int32 10, (3,15--3,17))), (3,10--3,11), + (3,15--3,17), (3,10--3,17)), (3,8--3,19)), + App + (LongIdent (SynLongIdent ([list], [], [None])), None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (3,21--3,29)), (3,8--3,29)), (3,7--3,8), + Some (3,29--3,30), (3,7--3,30)), (3,0--3,30), + { YieldOrReturnFromKeyword = (3,0--3,6) }), (3,0--3,30))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,30), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs b/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs new file mode 100644 index 00000000000..c80ceb053c5 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs @@ -0,0 +1,6 @@ +module Module + +seq { + yield! [ 1 .. 10 ]: int list +} + diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl new file mode 100644 index 00000000000..431a5f04e38 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl @@ -0,0 +1,32 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/YieldBang 03.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident seq, + ComputationExpr + (false, + YieldOrReturnFrom + ((true, false), + Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (4,13--4,14))), + (4,15--4,17), + Some (Const (Int32 10, (4,18--4,20))), + (4,13--4,14), (4,18--4,20), (4,13--4,20)), + (4,11--4,22)), + App + (LongIdent (SynLongIdent ([list], [], [None])), None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (4,24--4,32)), (4,11--4,32)), + (4,4--4,22), { YieldOrReturnFromKeyword = (4,4--4,10) }), + (3,4--5,1)), (3,0--5,1)), (3,0--5,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs b/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs new file mode 100644 index 00000000000..e80aee60891 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs @@ -0,0 +1,7 @@ +module Module + +seq { + yield! ([ 1 .. 10 ]: int list) +} + + diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl new file mode 100644 index 00000000000..1a4dcede9c9 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl @@ -0,0 +1,35 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/YieldBang 04.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident seq, + ComputationExpr + (false, + YieldOrReturnFrom + ((true, false), + Paren + (Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (4,14--4,15))), + (4,16--4,18), + Some (Const (Int32 10, (4,19--4,21))), + (4,14--4,15), (4,19--4,21), (4,14--4,21)), + (4,12--4,23)), + App + (LongIdent (SynLongIdent ([list], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], + [], None, true, (4,25--4,33)), (4,12--4,33)), + (4,11--4,12), Some (4,33--4,34), (4,11--4,34)), + (4,4--4,34), { YieldOrReturnFromKeyword = (4,4--4,10) }), + (3,4--5,1)), (3,0--5,1)), (3,0--5,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) From caeb72fdd50789c46a2f5d3592f8bd6e1b0c3aeb Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 5 May 2025 15:42:37 +0100 Subject: [PATCH 03/13] Add a component test --- .../Language/ComputationExpressionTests.fs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index 6b0a260a42f..b5ad5d638ab 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -23,6 +23,41 @@ let x = lb {1; 2;} |> shouldSucceed |> ignore + [] + let ``Allow CE return and type annotations to play well together without needing parentheses``() = + FSharp """ +module ComputationExpressionTests +open System + +type MyType() = + interface IDisposable with + member this.Dispose () = () + +let f () = + async { + return new MyType() : IDisposable + } + +let f1 () = + async { + return new MyType() :> IDisposable + } + +let f2 () : Async = + async { + return new MyType() + } + +let f3 () = + async { + return (new MyType() : IDisposable) + } + """ + |> asExe + |> withOptions ["--nowarn:988"] + |> compileAndRun + |> shouldSucceed + [] let ``A CE explicitly using Zero fails without a defined Zero``() = FSharp """ From 76e5921b6eb1ada87fc31c556d796cb07d335ddd Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 6 May 2025 20:07:34 +0100 Subject: [PATCH 04/13] ad recovery rules --- src/Compiler/pars.fsy | 18 +++++++++ .../data/SyntaxTree/Expression/Return 07.fs | 6 +++ .../SyntaxTree/Expression/Return 07.fs.bsl | 36 ++++++++++++++++++ .../SyntaxTree/Expression/ReturnBang 03.fs | 7 ++++ .../Expression/ReturnBang 03.fs.bsl | 38 +++++++++++++++++++ .../data/SyntaxTree/Expression/Yield 05.fs | 6 +++ .../SyntaxTree/Expression/Yield 05.fs.bsl | 30 +++++++++++++++ .../data/SyntaxTree/Expression/Yield 06.fs | 6 +++ .../SyntaxTree/Expression/Yield 06.fs.bsl | 30 +++++++++++++++ .../SyntaxTree/Expression/YieldBang 05.fs | 6 +++ .../SyntaxTree/Expression/YieldBang 05.fs.bsl | 31 +++++++++++++++ .../SyntaxTree/Expression/YieldBang 06.fs | 4 ++ .../SyntaxTree/Expression/YieldBang 06.fs.bsl | 24 ++++++++++++ 13 files changed, 242 insertions(+) create mode 100644 tests/service/data/SyntaxTree/Expression/Return 07.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs create mode 100644 tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 05.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 06.fs create mode 100644 tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 05.fs create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 06.fs create mode 100644 tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 42f74f7649c..a080bd9e529 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4421,11 +4421,29 @@ declExpr: let typedExpr = SynExpr.Typed($2, $4, unionRanges $2.Range $4.Range) SynExpr.YieldOrReturn(($1, not $1), typedExpr, (unionRanges (rhs parseState 1) $4.Range), trivia) } + | YIELD declExpr opt_topReturnTypeWithTypeConstraints + { let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } + let expr = + match $3 with + | None -> $2 + | Some(_, SynReturnInfo((ty, _), m)) -> + SynExpr.Typed($2, ty, unionRanges $2.Range m) + SynExpr.YieldOrReturn(($1, not $1), expr, (unionRanges (rhs parseState 1) expr.Range), trivia) } + | YIELD_BANG declExpr COLON typ { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } let typedExpr = SynExpr.Typed($2, $4, unionRanges $2.Range $4.Range) SynExpr.YieldOrReturnFrom(($1, not $1), typedExpr, (unionRanges (rhs parseState 1) $2.Range), trivia) } + | YIELD_BANG declExpr opt_topReturnTypeWithTypeConstraints + { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } + let expr = + match $3 with + | None -> $2 + | Some(_, SynReturnInfo((ty, _), m)) -> + SynExpr.Typed($2, ty, unionRanges $2.Range m) + SynExpr.YieldOrReturnFrom(($1, not $1), expr, (unionRanges (rhs parseState 1) $2.Range), trivia) } + | YIELD_BANG declExpr { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } SynExpr.YieldOrReturnFrom(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) } diff --git a/tests/service/data/SyntaxTree/Expression/Return 07.fs b/tests/service/data/SyntaxTree/Expression/Return 07.fs new file mode 100644 index 00000000000..19e68b27e5c --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 07.fs @@ -0,0 +1,6 @@ +module Module + +let _ = + async { + return new MyType() : + } diff --git a/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl new file mode 100644 index 00000000000..497892fd340 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl @@ -0,0 +1,36 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Return 07.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), + Typed + (New + (false, + LongIdent (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,25--5,27)), (5,15--5,27)), + FromParseError (5,29--5,29), (5,15--5,29)), + (5,8--5,29), { YieldOrReturnKeyword = (5,8--5,14) }), + (4,10--6,5)), (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(6,4)-(6,5) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs b/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs new file mode 100644 index 00000000000..dcb7b9c149a --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs @@ -0,0 +1,7 @@ +module Module + +let _ = + async { + return! new MyType() : + } + diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl new file mode 100644 index 00000000000..8958970b100 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl @@ -0,0 +1,38 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/ReturnBang 03.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Wild (3,4--3,5), None, + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturnFrom + ((false, true), + Typed + (New + (false, + LongIdent (SynLongIdent ([MyType], [], [None])), + Const (Unit, (5,26--5,28)), (5,16--5,28)), + FromParseError (5,30--5,30), (5,16--5,30)), + (5,8--5,28), + { YieldOrReturnFromKeyword = (5,8--5,15) }), + (4,10--6,5)), (4,4--6,5)), (3,4--3,5), NoneAtLet, + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,6--3,7) })], (3,0--6,5))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(6,4)-(6,5) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/Yield 05.fs b/tests/service/data/SyntaxTree/Expression/Yield 05.fs new file mode 100644 index 00000000000..573d3b81cdc --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 05.fs @@ -0,0 +1,6 @@ +module Module + +seq { + yield [ 1 .. 10 ] : +} + diff --git a/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl new file mode 100644 index 00000000000..2edd1561dda --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl @@ -0,0 +1,30 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Yield 05.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident seq, + ComputationExpr + (false, + YieldOrReturn + ((true, false), + Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (4,12--4,13))), + (4,14--4,16), + Some (Const (Int32 10, (4,17--4,19))), + (4,12--4,13), (4,17--4,19), (4,12--4,19)), + (4,10--4,21)), FromParseError (4,23--4,23), + (4,10--4,23)), (4,4--4,23), + { YieldOrReturnKeyword = (4,4--4,9) }), (3,4--5,1)), + (3,0--5,1)), (3,0--5,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,1) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/Yield 06.fs b/tests/service/data/SyntaxTree/Expression/Yield 06.fs new file mode 100644 index 00000000000..bb699f40621 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 06.fs @@ -0,0 +1,6 @@ +module Module + +seq { + yield [ 1 .. 10 ] : +} + diff --git a/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl new file mode 100644 index 00000000000..8f8900c7ba2 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl @@ -0,0 +1,30 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/Yield 06.fs", false, QualifiedNameOfFile Module, [], [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident seq, + ComputationExpr + (false, + YieldOrReturn + ((true, false), + Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (4,12--4,13))), + (4,14--4,16), + Some (Const (Int32 10, (4,17--4,19))), + (4,12--4,13), (4,17--4,19), (4,12--4,19)), + (4,10--4,21)), FromParseError (4,23--4,23), + (4,10--4,23)), (4,4--4,23), + { YieldOrReturnKeyword = (4,4--4,9) }), (3,4--5,1)), + (3,0--5,1)), (3,0--5,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,1) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs b/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs new file mode 100644 index 00000000000..5870293c0d1 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs @@ -0,0 +1,6 @@ +module Module + +seq { + yield! [ 1 .. 10 ] : +} + diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl new file mode 100644 index 00000000000..ae0b6ad7f2b --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl @@ -0,0 +1,31 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/YieldBang 05.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident seq, + ComputationExpr + (false, + YieldOrReturnFrom + ((true, false), + Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (4,13--4,14))), + (4,15--4,17), + Some (Const (Int32 10, (4,18--4,20))), + (4,13--4,14), (4,18--4,20), (4,13--4,20)), + (4,11--4,22)), FromParseError (4,24--4,24), + (4,11--4,24)), (4,4--4,22), + { YieldOrReturnFromKeyword = (4,4--4,10) }), (3,4--5,1)), + (3,0--5,1)), (3,0--5,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,1) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs b/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs new file mode 100644 index 00000000000..037f709a6e0 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs @@ -0,0 +1,4 @@ +module Module + +yield! [ 1 .. 10 ] : + diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl new file mode 100644 index 00000000000..cc8d49d8071 --- /dev/null +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl @@ -0,0 +1,24 @@ +ImplFile + (ParsedImplFileInput + ("/root/Expression/YieldBang 06.fs", false, QualifiedNameOfFile Module, [], + [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (YieldOrReturnFrom + ((true, false), + Typed + (ArrayOrListComputed + (false, + IndexRange + (Some (Const (Int32 1, (3,9--3,10))), (3,11--3,13), + Some (Const (Int32 10, (3,14--3,16))), (3,9--3,10), + (3,14--3,16), (3,9--3,16)), (3,7--3,18)), + FromParseError (3,20--3,20), (3,7--3,20)), (3,0--3,18), + { YieldOrReturnFromKeyword = (3,0--3,6) }), (3,0--3,18))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,18), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,0) parse error Incomplete structured construct at or before this point in expression From 9d53ca2199b660664eae02a5d8749911a9f76b38 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 6 May 2025 20:09:38 +0100 Subject: [PATCH 05/13] release notes --- docs/release-notes/.FSharp.Compiler.Service/9.0.300.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index e187f285d4b..b0b7b7de407 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -31,6 +31,7 @@ * Fix code completion considers types from own namespace non-imported ([PR #18518](https://github.com/dotnet/fsharp/issues/18518)) * Code completion: fix getting qualifier expression in do statements in type decls ([PR #18524](https://github.com/dotnet/fsharp/pull/18524)) * Fixed: [#18441](https://github.com/dotnet/fsharp/issues/18441) FSI multi-emit unstable. ([PR #18465](https://github.com/dotnet/fsharp/pull/18465)) +* Fixed: Allow `return`, `return!`, `yield`, `yield!` and type annotations without parentheses ([PR #18533](https://github.com/dotnet/fsharp/pull/18533)) ### Added * Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241)) From 31d8b996cf3ab7729165a086fdac6446186d89f1 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 6 May 2025 20:09:38 +0100 Subject: [PATCH 06/13] release notes --- docs/release-notes/.FSharp.Compiler.Service/9.0.300.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index e187f285d4b..7c253f13df1 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -31,6 +31,7 @@ * Fix code completion considers types from own namespace non-imported ([PR #18518](https://github.com/dotnet/fsharp/issues/18518)) * Code completion: fix getting qualifier expression in do statements in type decls ([PR #18524](https://github.com/dotnet/fsharp/pull/18524)) * Fixed: [#18441](https://github.com/dotnet/fsharp/issues/18441) FSI multi-emit unstable. ([PR #18465](https://github.com/dotnet/fsharp/pull/18465)) +* Fixed: Allow `return`, `return!`, `yield`, `yield!` type annotations without parentheses ([PR #18533](https://github.com/dotnet/fsharp/pull/18533)) ### Added * Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241)) From 336fd397f0f234d7d36976b1eb42d43691e055cb Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Thu, 15 May 2025 19:42:36 +0100 Subject: [PATCH 07/13] Update syntax tree tests to include WarnDirectives --- tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl | 2 +- tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl | 2 +- tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl | 2 +- tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl | 3 ++- tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl | 2 +- tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl | 2 +- tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl | 2 +- tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl | 2 +- tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl | 2 +- tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl | 2 +- 22 files changed, 35 insertions(+), 22 deletions(-) diff --git a/tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl index 2e14fc025c9..86c81fa6d87 100644 --- a/tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Return 01.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Return 01.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Return 01.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -33,4 +33,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl index 59ab0dac633..678e228062b 100644 --- a/tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Return 02.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Return 02.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Return 02.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -36,4 +36,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl index 68d17129ef3..467a5f86141 100644 --- a/tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Return 03.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Return 03.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Return 03.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -33,4 +33,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl index 00afeeaa092..bc6451d72ab 100644 --- a/tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Return 04.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Return 04.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Return 04.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -36,4 +36,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl index 06b83071496..beaaf365ecc 100644 --- a/tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Return 05.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Return 05.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Return 05.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -29,4 +29,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl index fc57c66f5db..04d0ad024e7 100644 --- a/tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Return 06.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Return 06.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Return 06.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -31,4 +31,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl index 497892fd340..0bf151be5bb 100644 --- a/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Return 07.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Return 07.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -31,6 +31,7 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) (6,4)-(6,5) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl index 537dde46f62..4890e673c4c 100644 --- a/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 01.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/ReturnBang 01.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -34,4 +33,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl index aa1df37ee9a..4ff6f08be18 100644 --- a/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 02.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/ReturnBang 02.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -37,4 +36,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl index 8958970b100..e23e8ccde38 100644 --- a/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/ReturnBang 03.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Let @@ -33,6 +32,7 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--6,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) (6,4)-(6,5) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl index 97efec2aec0..f6aabb5d447 100644 --- a/tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Yield 01.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Yield 01.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Yield 01.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -21,4 +21,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,27), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl index a08ff30db77..0948c6de6b3 100644 --- a/tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Yield 02.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Yield 02.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Yield 02.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -28,4 +28,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl index a5710c8bb9c..a064eecfdc1 100644 --- a/tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Yield 03.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Yield 03.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Yield 03.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -31,4 +31,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl index 2363fe76684..d3e1a1510ed 100644 --- a/tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Yield 04.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Yield 04.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Yield 04.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -23,4 +23,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,29), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl index 2edd1561dda..1deada75f94 100644 --- a/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Yield 05.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Yield 05.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -25,6 +25,7 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl index 8f8900c7ba2..ced49e682d6 100644 --- a/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl @@ -1,6 +1,6 @@ ImplFile (ParsedImplFileInput - ("/root/Expression/Yield 06.fs", false, QualifiedNameOfFile Module, [], [], + ("/root/Expression/Yield 06.fs", false, QualifiedNameOfFile Module, [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -25,6 +25,7 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl index a469799bff8..3d1e71f4894 100644 --- a/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 01.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/YieldBang 01.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -22,4 +21,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,18), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl index 3f7d1e2526b..08d1db3d26e 100644 --- a/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 02.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/YieldBang 02.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -24,4 +23,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,30), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl index 431a5f04e38..09804abe660 100644 --- a/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 03.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/YieldBang 03.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -29,4 +28,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl index 1a4dcede9c9..a5fde092fb8 100644 --- a/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 04.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/YieldBang 04.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -32,4 +31,5 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl index ae0b6ad7f2b..595f455632d 100644 --- a/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/YieldBang 05.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -26,6 +25,7 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected symbol '}' in expression diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl index cc8d49d8071..de83602e2d5 100644 --- a/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl @@ -1,7 +1,6 @@ ImplFile (ParsedImplFileInput ("/root/Expression/YieldBang 06.fs", false, QualifiedNameOfFile Module, [], - [], [SynModuleOrNamespace ([Module], false, NamedModule, [Expr @@ -19,6 +18,7 @@ ImplFile PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,18), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] + WarnDirectives = [] CodeComments = [] }, set [])) (5,0)-(5,0) parse error Incomplete structured construct at or before this point in expression From 1168259f77c85ae34e2f72235298f844e36b6c4a Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Thu, 15 May 2025 19:43:49 +0100 Subject: [PATCH 08/13] release notes --- docs/release-notes/.FSharp.Compiler.Service/10.0.100.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/release-notes/.FSharp.Compiler.Service/10.0.100.md diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md new file mode 100644 index 00000000000..f28ee555662 --- /dev/null +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md @@ -0,0 +1,2 @@ +### Fixed +* Fixed: Allow `return`, `return!`, `yield`, `yield!` type annotations without parentheses ([PR #18533](https://github.com/dotnet/fsharp/pull/18533)) From 032606734ae6a6b2b0255af56e9aabda66b1dd6e Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Fri, 16 May 2025 17:27:49 +0100 Subject: [PATCH 09/13] LanguageFeature.AllowTypedLetOrUseBang --- src/Compiler/pars.fsy | 2 + .../Language/ComputationExpressionTests.fs | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index c94f73d3e51..2cfb95e2cbb 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4433,6 +4433,7 @@ declExpr: | YIELD declExpr COLON typ { let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } let typedExpr = SynExpr.Typed($2, $4, unionRanges $2.Range $4.Range) + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang typedExpr.Range SynExpr.YieldOrReturn(($1, not $1), typedExpr, (unionRanges (rhs parseState 1) $4.Range), trivia) } | YIELD declExpr opt_topReturnTypeWithTypeConstraints @@ -4442,6 +4443,7 @@ declExpr: | None -> $2 | Some(_, SynReturnInfo((ty, _), m)) -> SynExpr.Typed($2, ty, unionRanges $2.Range m) + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang expr.Range SynExpr.YieldOrReturn(($1, not $1), expr, (unionRanges (rhs parseState 1) expr.Range), trivia) } | YIELD_BANG declExpr COLON typ diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index b5ad5d638ab..2dee3f01fb4 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -53,6 +53,43 @@ let f3 () = return (new MyType() : IDisposable) } """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 11, Col 16, Line 11, Col 42, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + + [] + let ``Preview: Allow CE return and type annotations to play well together without needing parentheses``() = + FSharp """ +module ComputationExpressionTests +open System + +type MyType() = + interface IDisposable with + member this.Dispose () = () + +let f () = + async { + return new MyType() : IDisposable + } + +let f1 () = + async { + return new MyType() :> IDisposable + } + +let f2 () : Async = + async { + return new MyType() + } + +let f3 () = + async { + return (new MyType() : IDisposable) + } + """ + |> withLangVersionPreview |> asExe |> withOptions ["--nowarn:988"] |> compileAndRun From 5aad7227960480f65bdb0bbd9218e0c347e9594a Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 19 May 2025 20:18:25 +0100 Subject: [PATCH 10/13] fixCheckLanguageFeatureAndRecover placement --- src/Compiler/pars.fsy | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 2cfb95e2cbb..b90b1dbef88 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4441,9 +4441,9 @@ declExpr: let expr = match $3 with | None -> $2 - | Some(_, SynReturnInfo((ty, _), m)) -> + | Some(_, SynReturnInfo((ty, _), m)) -> + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang m SynExpr.Typed($2, ty, unionRanges $2.Range m) - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang expr.Range SynExpr.YieldOrReturn(($1, not $1), expr, (unionRanges (rhs parseState 1) expr.Range), trivia) } | YIELD_BANG declExpr COLON typ @@ -4456,7 +4456,8 @@ declExpr: let expr = match $3 with | None -> $2 - | Some(_, SynReturnInfo((ty, _), m)) -> + | Some(_, SynReturnInfo((ty, _), m)) -> + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang m SynExpr.Typed($2, ty, unionRanges $2.Range m) SynExpr.YieldOrReturnFrom(($1, not $1), expr, (unionRanges (rhs parseState 1) $2.Range), trivia) } From 31c5eb27467d3a6454228483d0defa2eb0880361 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 19 May 2025 20:18:52 +0100 Subject: [PATCH 11/13] place YIELD rules together --- src/Compiler/pars.fsy | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index b90b1dbef88..43cf40464b1 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4446,6 +4446,16 @@ declExpr: SynExpr.Typed($2, ty, unionRanges $2.Range m) SynExpr.YieldOrReturn(($1, not $1), expr, (unionRanges (rhs parseState 1) expr.Range), trivia) } + | YIELD recover + { let mYieldAll = rhs parseState 1 + let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } + SynExpr.YieldOrReturn(($1, not $1), arbExpr ("yield", mYieldAll), mYieldAll, trivia) } + + | YIELD_BANG recover + { let mYieldAll = rhs parseState 1 + let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } + SynExpr.YieldOrReturnFrom(($1, not $1), arbExpr ("yield!", mYieldAll), mYieldAll, trivia) } + | YIELD_BANG declExpr COLON typ { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } let typedExpr = SynExpr.Typed($2, $4, unionRanges $2.Range $4.Range) @@ -4461,20 +4471,6 @@ declExpr: SynExpr.Typed($2, ty, unionRanges $2.Range m) SynExpr.YieldOrReturnFrom(($1, not $1), expr, (unionRanges (rhs parseState 1) $2.Range), trivia) } - | YIELD_BANG declExpr - { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } - SynExpr.YieldOrReturnFrom(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) } - - | YIELD recover - { let mYieldAll = rhs parseState 1 - let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } - SynExpr.YieldOrReturn(($1, not $1), arbExpr ("yield", mYieldAll), mYieldAll, trivia) } - - | YIELD_BANG recover - { let mYieldAll = rhs parseState 1 - let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } - SynExpr.YieldOrReturnFrom(($1, not $1), arbExpr ("yield!", mYieldAll), mYieldAll, trivia) } - | BINDER headBindingPattern EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let { (* This rule handles the 'use!' and 'let!' binding expressions in computation expressions *) (* The BINDER token represents keywords like 'use!' or 'let!' *) From 2c06b5c7f4125b0edb105474d38cebfb9238f75d Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 19 May 2025 21:23:41 +0100 Subject: [PATCH 12/13] update tests --- src/Compiler/pars.fsy | 9 +- .../Language/ComputationExpressionTests.fs | 70 ++++++++++++++- .../SequenceExpressionTests.fs | 90 +++++++++++++++++++ 3 files changed, 163 insertions(+), 6 deletions(-) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 43cf40464b1..76fedb8dcc8 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4442,8 +4442,9 @@ declExpr: match $3 with | None -> $2 | Some(_, SynReturnInfo((ty, _), m)) -> + let m = unionRanges $2.Range m parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang m - SynExpr.Typed($2, ty, unionRanges $2.Range m) + SynExpr.Typed($2, ty, m) SynExpr.YieldOrReturn(($1, not $1), expr, (unionRanges (rhs parseState 1) expr.Range), trivia) } | YIELD recover @@ -4459,6 +4460,7 @@ declExpr: | YIELD_BANG declExpr COLON typ { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 } let typedExpr = SynExpr.Typed($2, $4, unionRanges $2.Range $4.Range) + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang typedExpr.Range SynExpr.YieldOrReturnFrom(($1, not $1), typedExpr, (unionRanges (rhs parseState 1) $2.Range), trivia) } | YIELD_BANG declExpr opt_topReturnTypeWithTypeConstraints @@ -4467,8 +4469,9 @@ declExpr: match $3 with | None -> $2 | Some(_, SynReturnInfo((ty, _), m)) -> - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang m - SynExpr.Typed($2, ty, unionRanges $2.Range m) + let m = unionRanges $2.Range m + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang m + SynExpr.Typed($2, ty, m) SynExpr.YieldOrReturnFrom(($1, not $1), expr, (unionRanges (rhs parseState 1) $2.Range), trivia) } | BINDER headBindingPattern EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index 2dee3f01fb4..da918ffc00a 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. namespace Language @@ -24,7 +24,7 @@ let x = lb {1; 2;} |> ignore [] - let ``Allow CE return and type annotations to play well together without needing parentheses``() = + let ``Version 9.0: Allow CE return and type annotations don't play well together needing parentheses``() = FSharp """ module ComputationExpressionTests open System @@ -53,12 +53,45 @@ let f3 () = return (new MyType() : IDisposable) } """ + |> withLangVersion90 |> typecheck |> shouldFail |> withDiagnostics [ (Error 3350, Line 11, Col 16, Line 11, Col 42, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") ] + [] + let ``Version 9.0: Allow CE return! and type annotations don't to play well together needing parentheses``() = + FSharp """ +module ComputationExpressionTests + +type ResultBuilder() = + member _.Return(x) = Ok x + member _.ReturnFrom(x) = x + member _.Bind(m, f) = + match m with + | Ok a -> f a + | Error e -> Error e + +let result = ResultBuilder() + +let f() = + result { + return! Ok 1 : Result + } + +let f1() = + result { + return! (Ok 1 : Result) + } + """ + |> withLangVersion90 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 16, Col 17, Line 16, Col 43, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + [] let ``Preview: Allow CE return and type annotations to play well together without needing parentheses``() = FSharp """ @@ -91,7 +124,38 @@ let f3 () = """ |> withLangVersionPreview |> asExe - |> withOptions ["--nowarn:988"] + |> ignoreWarnings + |> compileAndRun + |> shouldSucceed + + [] + let ``Preview: Allow CE return! and type annotations to play well together without needing parentheses``() = + FSharp """ +module ComputationExpressionTests + +type ResultBuilder() = + member _.Return(x) = Ok x + member _.ReturnFrom(x) = x + member _.Bind(m, f) = + match m with + | Ok a -> f a + | Error e -> Error e + +let result = ResultBuilder() + +let f() = + result { + return! Ok 1 : Result + } + +let f1() = + result { + return! (Ok 1 : Result) + } + """ + |> withLangVersionPreview + |> asExe + |> ignoreWarnings |> compileAndRun |> shouldSucceed diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressionTests.fs index d64262e856b..8490b41a750 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressionTests.fs @@ -644,4 +644,94 @@ let c = [ { 1;10 } ] |> withOptions [ "--nowarn:0020" ] |> withLangVersionPreview |> typecheck + |> shouldSucceed + + [] + let ``Version 9.0: Allow SE yield and type annotations don't play well together needing parentheses``() = + FSharp """ +module SequenceExpressionTests +open System + +let f() = + seq { + yield 1 : int + } + +let f1() = + seq { + yield (1 : int) + } + """ + |> withLangVersion90 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 7, Col 15, Line 7, Col 22, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + + [] + let ``Preview: Allow SE yield and type annotations to play well together without needing parentheses``() = + FSharp """ +module SequenceExpressionTests +open System + +let f() = + seq { + yield 1 : int + } + +let f1() = + seq { + yield (1 : int) + } + """ + |> withLangVersionPreview + |> asExe + |> ignoreWarnings + |> compileAndRun + |> shouldSucceed + + [] + let ``Version 9.0: Allow SE yield! and type annotations don't play well together needing parentheses``() = + FSharp """ +module SequenceExpressionTests +open System + +let f() = + seq { + yield! [1;2] : int list + } + +let f1() = + seq { + yield! ([1;2] : int list) + } + """ + |> withLangVersion90 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 7, Col 16, Line 7, Col 32, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + + [] + let ``Preview: Allow SE yield! and type annotations to play well together without needing parentheses``() = + FSharp """ +module SequenceExpressionTests +open System + +let f() = + seq { + yield! [1;2] : int list + } + +let f1() = + seq { + yield! ([1;2] : int list) + } + """ + |> withLangVersionPreview + |> asExe + |> ignoreWarnings + |> compileAndRun |> shouldSucceed \ No newline at end of file From 5cd90b0160e559a580ea4d01c9088ee10cdf4cb8 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Wed, 21 May 2025 09:09:35 +0100 Subject: [PATCH 13/13] remove redundant rule --- src/Compiler/pars.fsy | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 76fedb8dcc8..bbfca699064 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4426,10 +4426,6 @@ declExpr: let mForLoopAll = rhs2 parseState 1 2 exprFromParseError (SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, $2, arbExpr ("forLoopCollection", mFor), arbExpr ("forLoopBody3", mForLoopBodyArb), mForLoopAll)) } - | YIELD declExpr - { let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } - SynExpr.YieldOrReturn(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) } - | YIELD declExpr COLON typ { let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 } let typedExpr = SynExpr.Typed($2, $4, unionRanges $2.Range $4.Range)