From 1799aaf29034f01357684c7716b6eed8fc76468a Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 23 Apr 2025 15:27:24 +0100 Subject: [PATCH 01/22] make attribute targets mismatches a warning and not an error. --- .../Checking/Expressions/CheckExpressions.fs | 2 +- .../AttributeUsage/AttributeUsage.fs | 215 +++++++++--------- .../CustomAttributes/Basic/Basic.fs | 7 +- .../EntryPoint/EntryPoint.fs | 2 +- .../LetBindings/Basic/Basic.fs | 4 +- .../ErrorMessages/TailCallAttribute.fs | 32 +-- 6 files changed, 125 insertions(+), 137 deletions(-) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 5f390038e35..e2d21975311 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -11367,7 +11367,7 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn if (directedTgts = AttributeTargets.Assembly || directedTgts = AttributeTargets.Module) then error(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElementUseDo(), mAttr)) else - error(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElement(), mAttr)) + warning(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElement(), mAttr)) match ResolveObjectConstructor cenv.nameResolver env.DisplayEnv mAttr ad ty with | Exception _ when canFail = TcCanFail.IgnoreAllErrors || canFail = TcCanFail.IgnoreMemberResoutionError -> [ ], true diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs index c7c2cf72eca..f027745b73e 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -104,10 +104,10 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 21, Col 21, Line 21, Col 22, "This attribute is not valid for use on this language element") - (Error 842, Line 24, Col 21, Line 24, Col 29, "This attribute is not valid for use on this language element") - (Error 842, Line 27, Col 7, Line 27, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 18, Col 7, Line 18, Col 8, "This attribute is not valid for use on this language element") + (Warning 842, Line 21, Col 21, Line 21, Col 22, "This attribute is not valid for use on this language element") + (Warning 842, Line 24, Col 21, Line 24, Col 29, "This attribute is not valid for use on this language element") + (Warning 842, Line 27, Col 7, Line 27, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 18, Col 7, Line 18, Col 8, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargets02.fs # E_AttributeTargets02.fs @@ -117,9 +117,10 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 14, Col 7, Line 14, Col 34, "This attribute is not valid for use on this language element") - (Error 842, Line 24, Col 7, Line 24, Col 36, "This attribute is not valid for use on this language element") - (Error 842, Line 29, Col 15, Line 29, Col 47, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 7, Line 14, Col 34, "This attribute is not valid for use on this language element") + (Warning 842, Line 24, Col 7, Line 24, Col 36, "This attribute is not valid for use on this language element") + (Warning 842, Line 29, Col 15, Line 29, Col 47, "This attribute is not valid for use on this language element") + (Error 3172, Line 28, Col 14, Line 28, Col 17, "A property's getter and setter must have the same type. Property 'Foo' has getter of type 'int' but setter of type 'obj'.") ] // SOURCE=E_AttributeTargetIsField01.fs # E_AttributeTargetIsField01.fs @@ -140,23 +141,23 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 9, Col 3, Line 9, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 12, Col 3, Line 12, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 15, Col 3, Line 15, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 18, Col 3, Line 18, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 21, Col 3, Line 21, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 24, Col 3, Line 24, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 27, Col 3, Line 27, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 30, Col 3, Line 30, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 33, Col 3, Line 33, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 36, Col 3, Line 36, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 39, Col 3, Line 39, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 42, Col 3, Line 42, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 45, Col 3, Line 45, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 49, Col 3, Line 49, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 56, Col 3, Line 56, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 64, Col 3, Line 64, Col 12, "This attribute is not valid for use on this language element") - (Error 842, Line 66, Col 7, Line 66, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 9, Col 3, Line 9, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 12, Col 3, Line 12, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 15, Col 3, Line 15, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 18, Col 3, Line 18, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 21, Col 3, Line 21, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 24, Col 3, Line 24, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 27, Col 3, Line 27, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 30, Col 3, Line 30, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 33, Col 3, Line 33, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 36, Col 3, Line 36, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 39, Col 3, Line 39, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 42, Col 3, Line 42, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 45, Col 3, Line 45, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 49, Col 3, Line 49, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 56, Col 3, Line 56, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 64, Col 3, Line 64, Col 12, "This attribute is not valid for use on this language element") + (Warning 842, Line 66, Col 7, Line 66, Col 16, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargetIsField02.fs # E_AttributeTargetIsField02.fs @@ -194,17 +195,17 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 9, Col 3, Line 9, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 12, Col 3, Line 12, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 15, Col 3, Line 15, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 18, Col 3, Line 18, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 21, Col 3, Line 21, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 24, Col 3, Line 24, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 26, Col 7, Line 26, Col 17, "This attribute is not valid for use on this language element") - (Error 842, Line 28, Col 3, Line 28, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 31, Col 3, Line 31, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 34, Col 3, Line 34, Col 13, "This attribute is not valid for use on this language element") - (Error 842, Line 39, Col 3, Line 39, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 9, Col 3, Line 9, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 12, Col 3, Line 12, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 15, Col 3, Line 15, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 18, Col 3, Line 18, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 21, Col 3, Line 21, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 24, Col 3, Line 24, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 26, Col 7, Line 26, Col 17, "This attribute is not valid for use on this language element") + (Warning 842, Line 28, Col 3, Line 28, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 31, Col 3, Line 31, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 34, Col 3, Line 34, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 39, Col 3, Line 39, Col 13, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargetIsMethod03.fs # E_AttributeTargetIsMethod03.fs @@ -225,21 +226,21 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 12, Col 6, Line 12, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 15, Col 6, Line 15, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 18, Col 6, Line 18, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 20, Col 10, Line 20, Col 20, "This attribute is not valid for use on this language element") - (Error 842, Line 22, Col 6, Line 22, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 25, Col 6, Line 25, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 28, Col 6, Line 28, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 31, Col 6, Line 31, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 34, Col 6, Line 34, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 37, Col 6, Line 37, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 39, Col 10, Line 39, Col 20, "This attribute is not valid for use on this language element") - (Error 842, Line 41, Col 6, Line 41, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 44, Col 6, Line 44, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 47, Col 6, Line 47, Col 16, "This attribute is not valid for use on this language element") - (Error 842, Line 52, Col 6, Line 52, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 12, Col 6, Line 12, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 15, Col 6, Line 15, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 18, Col 6, Line 18, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 20, Col 10, Line 20, Col 20, "This attribute is not valid for use on this language element") + (Warning 842, Line 22, Col 6, Line 22, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 25, Col 6, Line 25, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 28, Col 6, Line 28, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 31, Col 6, Line 31, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 34, Col 6, Line 34, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 37, Col 6, Line 37, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 39, Col 10, Line 39, Col 20, "This attribute is not valid for use on this language element") + (Warning 842, Line 41, Col 6, Line 41, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 44, Col 6, Line 44, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 47, Col 6, Line 47, Col 16, "This attribute is not valid for use on this language element") + (Warning 842, Line 52, Col 6, Line 52, Col 16, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargetIsMethod04.fs # E_AttributeTargetIsMethod04.fs @@ -250,8 +251,8 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 10, Col 3, Line 10, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 13, Col 3, Line 13, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 10, Col 3, Line 10, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 13, Col 3, Line 13, Col 15, "This attribute is not valid for use on this language element") ] // SOURCE=E_ConditionalAttribute.fs SCFLAGS="--test:ErrorRanges" # E_ConditionalAttribute.fs @@ -293,7 +294,7 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 12, Col 3, Line 12, Col 6, "This attribute is not valid for use on this language element") + (Warning 842, Line 12, Col 3, Line 12, Col 6, "This attribute is not valid for use on this language element") ] // SOURCE=AttributeTargetIsStruct.fs # AttributeTargetIsStruct.fs @@ -342,18 +343,18 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 13, Col 3, Line 13, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 19, Col 3, Line 19, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 22, Col 11, Line 22, Col 22, "This attribute is not valid for use on this language element") - (Error 842, Line 25, Col 3, Line 25, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 34, Col 3, Line 34, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 35, Col 3, Line 35, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 40, Col 3, Line 40, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 41, Col 3, Line 41, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 49, Col 3, Line 49, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 50, Col 3, Line 50, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 53, Col 3, Line 53, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 54, Col 3, Line 54, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 13, Col 3, Line 13, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 19, Col 3, Line 19, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 22, Col 11, Line 22, Col 22, "This attribute is not valid for use on this language element") + (Warning 842, Line 25, Col 3, Line 25, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 34, Col 3, Line 34, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 35, Col 3, Line 35, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 40, Col 3, Line 40, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 41, Col 3, Line 41, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 49, Col 3, Line 49, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 50, Col 3, Line 50, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 53, Col 3, Line 53, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 54, Col 3, Line 54, Col 18, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargetIsClass.fs # E_AttributeTargetIsClass.fs @@ -372,9 +373,9 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 13, Col 3, Line 13, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 19, Col 3, Line 19, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 22, Col 10, Line 22, Col 22, "This attribute is not valid for use on this language element") + (Warning 842, Line 13, Col 3, Line 13, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 19, Col 3, Line 19, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 22, Col 10, Line 22, Col 22, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargetIsClass01.fs # E_AttributeTargetIsClass01.fs @@ -393,8 +394,8 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 7, Col 3, Line 7, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 10, Col 10, Line 10, Col 25, "This attribute is not valid for use on this language element") + (Warning 842, Line 7, Col 3, Line 7, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 10, Col 10, Line 10, Col 25, "This attribute is not valid for use on this language element") ] // SOURCE=MarshalAsAttribute.fs # MarshalAsAttribute.fs @@ -480,7 +481,7 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 14, Col 5, Line 14, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 5, Line 14, Col 15, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargetIsField03.fs # E_AttributeTargetIsField03.fs @@ -491,8 +492,8 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 14, Col 5, Line 14, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 15, Col 5, Line 15, Col 25, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 5, Line 14, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 15, Col 5, Line 15, Col 25, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargetIsProperty01.fs # E_AttributeTargetIsField03.fs @@ -511,8 +512,8 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 14, Col 5, Line 14, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 15, Col 5, Line 15, Col 25, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 5, Line 14, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 15, Col 5, Line 15, Col 25, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargetIsCtor01.fs # E_AttributeTargetIsCtor01.fs @@ -531,10 +532,10 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 9, Col 15, Line 9, Col 27, "This attribute is not valid for use on this language element") - (Error 842, Line 11, Col 16, Line 11, Col 28, "This attribute is not valid for use on this language element") - (Error 842, Line 14, Col 15, Line 14, Col 27, "This attribute is not valid for use on this language element") - (Error 842, Line 17, Col 16, Line 17, Col 28, "This attribute is not valid for use on this language element") + (Warning 842, Line 9, Col 15, Line 9, Col 27, "This attribute is not valid for use on this language element") + (Warning 842, Line 11, Col 16, Line 11, Col 28, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 15, Line 14, Col 27, "This attribute is not valid for use on this language element") + (Warning 842, Line 17, Col 16, Line 17, Col 28, "This attribute is not valid for use on this language element") ] // SOURCE=AttributeTargetsIsEnum01.fs # AttributeTargetsIsEnum01.fs @@ -568,10 +569,10 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 19, Col 3, Line 19, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 20, Col 3, Line 20, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 22, Col 3, Line 22, Col 17, "This attribute is not valid for use on this language element") + (Warning 842, Line 19, Col 3, Line 19, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 20, Col 3, Line 20, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 22, Col 3, Line 22, Col 17, "This attribute is not valid for use on this language element") ] // SOURCE=AttributeTargetsIsDelegate01.fs # AttributeTargetsIsDelegate01.fs @@ -605,10 +606,10 @@ module CustomAttributes_AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 19, Col 3, Line 19, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 20, Col 3, Line 20, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 22, Col 3, Line 22, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 19, Col 3, Line 19, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 20, Col 3, Line 20, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 22, Col 3, Line 22, Col 13, "This attribute is not valid for use on this language element") ] [] @@ -654,10 +655,10 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 11, Col 3, Line 11, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 14, Col 3, Line 14, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 18, Col 3, Line 18, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 19, Col 3, Line 19, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 11, Col 3, Line 11, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 3, Line 14, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 18, Col 3, Line 18, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 19, Col 3, Line 19, Col 15, "This attribute is not valid for use on this language element") ] // SOURCE= E_AttributeTargetIsClass02.fs # E_AttributeTargetIsClass02.fs @@ -676,18 +677,18 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 15, Col 3, Line 15, Col 18, "This attribute is not valid for use on this language element"); - (Error 842, Line 16, Col 3, Line 16, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 20, Col 3, Line 20, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 26, Col 3, Line 26, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 27, Col 3, Line 27, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 34, Col 3, Line 34, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 35, Col 3, Line 35, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 43, Col 3, Line 43, Col 18, "This attribute is not valid for use on this language element") - (Error 842, Line 44, Col 3, Line 44, Col 15, "This attribute is not valid for use on this language element") - (Error 842, Line 47, Col 3, Line 47, Col 14, "This attribute is not valid for use on this language element") - (Error 842, Line 48, Col 3, Line 48, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 15, Col 3, Line 15, Col 18, "This attribute is not valid for use on this language element"); + (Warning 842, Line 16, Col 3, Line 16, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 20, Col 3, Line 20, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 26, Col 3, Line 26, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 27, Col 3, Line 27, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 34, Col 3, Line 34, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 35, Col 3, Line 35, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 43, Col 3, Line 43, Col 18, "This attribute is not valid for use on this language element") + (Warning 842, Line 44, Col 3, Line 44, Col 15, "This attribute is not valid for use on this language element") + (Warning 842, Line 47, Col 3, Line 47, Col 14, "This attribute is not valid for use on this language element") + (Warning 842, Line 48, Col 3, Line 48, Col 18, "This attribute is not valid for use on this language element") ] // SOURCE= CLIMutableAttribute01.fs # CLIMutableAttribute01.fs @@ -756,8 +757,8 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) = (Error 934, Line 33, Col 10, Line 33, Col 11, "Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute") (Error 934, Line 36, Col 10, Line 36, Col 11, "Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute") (Error 934, Line 39, Col 10, Line 39, Col 13, "Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute") - (Error 842, Line 41, Col 7, Line 41, Col 23, "This attribute is not valid for use on this language element") - (Error 842, Line 44, Col 7, Line 44, Col 23, "This attribute is not valid for use on this language element") + (Warning 842, Line 41, Col 7, Line 41, Col 23, "This attribute is not valid for use on this language element") + (Warning 842, Line 44, Col 7, Line 44, Col 23, "This attribute is not valid for use on this language element") (Error 935, Line 54, Col 10, Line 54, Col 11, "Types with the 'AllowNullLiteral' attribute may only inherit from or implement types which also allow the use of the null literal") ] @@ -775,8 +776,8 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) = (Error 934, Line 33, Col 10, Line 33, Col 11, "Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute") (Error 934, Line 36, Col 10, Line 36, Col 11, "Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute") (Error 934, Line 39, Col 10, Line 39, Col 13, "Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute") - (Error 842, Line 41, Col 7, Line 41, Col 23, "This attribute is not valid for use on this language element") - (Error 842, Line 44, Col 7, Line 44, Col 23, "This attribute is not valid for use on this language element") + (Warning 842, Line 41, Col 7, Line 41, Col 23, "This attribute is not valid for use on this language element") + (Warning 842, Line 44, Col 7, Line 44, Col 23, "This attribute is not valid for use on this language element") (Error 935, Line 54, Col 10, Line 54, Col 11, "Types with the 'AllowNullLiteral' attribute may only inherit from or implement types which also allow the use of the null literal") ] 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 1e3c99dc8a5..44ee388af9d 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs @@ -61,7 +61,7 @@ module CustomAttributes_Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 15, Col 7, Line 15, Col 17, "This attribute is not valid for use on this language element") + (Warning 842, Line 15, Col 7, Line 15, Col 17, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeApplication04.fs SCFLAGS="--test:ErrorRanges" # E_AttributeApplication04.fs @@ -71,7 +71,7 @@ module CustomAttributes_Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 14, Col 3, Line 14, Col 13, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 3, Line 14, Col 13, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeApplication05.fs SCFLAGS="--test:ErrorRanges" # E_AttributeApplication05.fs @@ -81,7 +81,8 @@ module CustomAttributes_Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 8, Col 7, Line 8, Col 8, "This attribute is not valid for use on this language element") + (Warning 842, Line 8, Col 7, Line 8, Col 8, "This attribute is not valid for use on this language element") + (Error 824, Line 8, Col 7, Line 8, Col 8, "Attributes are not permitted on 'let' bindings in expressions") (Warning 20, Line 8, Col 1, Line 8, Col 31, "The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.") ] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/EntryPoint/EntryPoint.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/EntryPoint/EntryPoint.fs index ce51bcf6c14..38b84fb6498 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/EntryPoint/EntryPoint.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/EntryPoint/EntryPoint.fs @@ -75,7 +75,7 @@ module EntryPoint = |> compile |> shouldFail |> withDiagnostics [ - (Error 842, Line 9, Col 3, Line 9, Col 13, """This attribute is not valid for use on this language element""") + (Warning 842, Line 9, Col 3, Line 9, Col 13, """This attribute is not valid for use on this language element""") ] // SOURCE=E_twoattributesonsamefunction001.fs SCFLAGS="--test:ErrorRanges" # E_twoattributesonsamefunction001.fs diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs index c0a19c9ad3e..b59d28cbdd2 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs @@ -53,9 +53,9 @@ module LetBindings_Basic = |> shouldFail |> withDiagnostics [ (Error 683, Line 14, Col 6, Line 14, Col 27, "Attributes are not allowed within patterns") - (Error 842, Line 14, Col 8, Line 14, Col 25, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 8, Line 14, Col 25, "This attribute is not valid for use on this language element") (Error 683, Line 14, Col 42, Line 14, Col 63, "Attributes are not allowed within patterns") - (Error 842, Line 14, Col 44, Line 14, Col 61, "This attribute is not valid for use on this language element") + (Warning 842, Line 14, Col 44, Line 14, Col 61, "This attribute is not valid for use on this language element") ] // SOURCE=E_ErrorsForInlineValue.fs SCFLAGS="--test:ErrorRanges" # E_ErrorsForInlineValue.fs diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 1b68505ab1e..81ce04fc05a 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -245,7 +245,7 @@ namespace N [] let ``Warn successfully for invalid tailcalls in type methods`` () = - """ + FSharp """ namespace N module M = @@ -261,29 +261,12 @@ namespace N printfn "M2 called" this.M1() + 2 // should warn """ - |> FSharp |> withLangVersion80 |> compile |> shouldFail - |> withResults [ - { Error = Warning 3569 - Range = { StartLine = 10 - StartColumn = 17 - EndLine = 10 - EndColumn = 26 } - Message = - "The member or function 'M2' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } - { Error = Warning 3569 - Range = { StartLine = 15 - StartColumn = 17 - EndLine = 15 - EndColumn = 26 } - Message = -#if Debug - "The member or function 'M2' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } -#else - "The member or function 'M1' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } -#endif + |> withDiagnostics [ + (Warning 3569, Line 10, Col 17, Line 10, Col 26, "The member or function 'M2' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way."); + (Warning 3569, Line 15, Col 17, Line 15, Col 26, "The member or function 'M1' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way.") ] [] @@ -1481,7 +1464,10 @@ namespace N |> withLangVersionPreview |> compile |> shouldFail - |> withSingleDiagnostic (Error 842, Line 6, Col 11, Line 6, Col 19, "This attribute is not valid for use on this language element") + |> withDiagnostics [ + (Warning 842, Line 6, Col 11, Line 6, Col 19, "This attribute is not valid for use on this language element") + (Warning 3861, Line 7, Col 13, Line 7, Col 18, "The TailCall attribute should only be applied to recursive functions.") + ] [] let ``Error about attribute on recursive let-bound value`` () = @@ -1497,7 +1483,7 @@ namespace N |> withLangVersionPreview |> compile |> shouldFail - |> withSingleDiagnostic (Error 842, Line 6, Col 11, Line 6, Col 19, "This attribute is not valid for use on this language element") + |> withSingleDiagnostic (Warning 842, Line 6, Col 11, Line 6, Col 19, "This attribute is not valid for use on this language element") [] let ``Warn about self-defined attribute`` () = // is the analysis available for users of older FSharp.Core versions From 55507e9e7e98e640678932f96a25cb3bacc82904 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 23 Apr 2025 15:39:04 +0100 Subject: [PATCH 02/22] 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 16f5721e22a..05e15a667dd 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -48,6 +48,7 @@ * Warning for "useless null handling" works with piped syntax constructs now ([PR #18331](https://github.com/dotnet/fsharp/pull/18331)) * Make indent in generated overridden member code depend on the context, not fix to 4. ([PR #18341](https://github.com/dotnet/fsharp/pull/18341)) * Adjust caller info attribute error message range ([PR #18388](https://github.com/dotnet/fsharp/pull/18388)) +* Make attribute targets mismatch a warning and not an error ([PR #18492](https://github.com/dotnet/fsharp/pull/18492)) ### Breaking Changes * Struct unions with overlapping fields now generate mappings needed for reading via reflection ([Issue #18121](https://github.com/dotnet/fsharp/issues/17797), [PR #18274](https://github.com/dotnet/fsharp/pull/17877)) From 17380183feebe6a1cf30a8f678965b6cd689de82 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 23 Apr 2025 16:19:59 +0100 Subject: [PATCH 03/22] update tests --- .../PatternMatchCompilationTests.fs | 1 + .../Language/StructActivePatternTests.fs | 2 +- tests/fsharp/typecheck/sigs/neg16.bsl | 4 +- tests/fsharp/typecheck/sigs/neg20.bsl | 46 +++++++++---------- tests/fsharp/typecheck/sigs/neg32.bsl | 2 +- .../fsharp/typecheck/sigs/version50/neg20.bsl | 46 +++++++++---------- .../UnitsOfMeasure/WithOOP/E_GenericUOM01.fs | 2 +- 7 files changed, 52 insertions(+), 51 deletions(-) diff --git a/tests/FSharp.Compiler.Service.Tests/PatternMatchCompilationTests.fs b/tests/FSharp.Compiler.Service.Tests/PatternMatchCompilationTests.fs index 1b6d54d3577..cf870698077 100644 --- a/tests/FSharp.Compiler.Service.Tests/PatternMatchCompilationTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/PatternMatchCompilationTests.fs @@ -41,6 +41,7 @@ match () with dumpDiagnostics checkResults |> shouldEqual [ "(3,2--3,25): Attributes are not allowed within patterns" "(3,4--3,23): This attribute is not valid for use on this language element" + "(3,17--3,22): This is not a valid constant expression or custom attribute value" ] diff --git a/tests/fsharp/Compiler/Language/StructActivePatternTests.fs b/tests/fsharp/Compiler/Language/StructActivePatternTests.fs index aac654f549c..4c2451142fa 100644 --- a/tests/fsharp/Compiler/Language/StructActivePatternTests.fs +++ b/tests/fsharp/Compiler/Language/StructActivePatternTests.fs @@ -176,7 +176,7 @@ let (|Foo|_|) x = ValueNone [] let (|Foo|_|) x = ValueNone """ - [|(FSharpDiagnosticSeverity.Error, 842, (2, 3, 2, 9), + [|(FSharpDiagnosticSeverity.Warning, 842, (2, 3, 2, 9), "This attribute is not valid for use on this language element"); (FSharpDiagnosticSeverity.Error, 3350, (3, 6, 3, 13), "Feature 'Boolean-returning and return-type-directed partial active patterns' is not available in F# 8.0. Please use language version 9.0 or greater.")|] diff --git a/tests/fsharp/typecheck/sigs/neg16.bsl b/tests/fsharp/typecheck/sigs/neg16.bsl index 4c2300470f7..448ca9127be 100644 --- a/tests/fsharp/typecheck/sigs/neg16.bsl +++ b/tests/fsharp/typecheck/sigs/neg16.bsl @@ -13,9 +13,9 @@ neg16.fs(44,10,44,11): typecheck error FS0934: Records, union, abbreviations and neg16.fs(47,10,47,13): typecheck error FS0934: Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute -neg16.fs(49,7,49,23): typecheck error FS0842: This attribute is not valid for use on this language element +neg16.fs(49,7,49,23): typecheck warning FS0842: This attribute is not valid for use on this language element -neg16.fs(52,7,52,23): typecheck error FS0842: This attribute is not valid for use on this language element +neg16.fs(52,7,52,23): typecheck warning FS0842: This attribute is not valid for use on this language element neg16.fs(59,8,59,17): typecheck error FS0001: This expression was expected to have type 'Choice<'a,'b>' diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl index 5229dcaacf6..28fa11b53f7 100644 --- a/tests/fsharp/typecheck/sigs/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/neg20.bsl @@ -213,53 +213,53 @@ neg20.fs(190,34,190,39): typecheck error FS0001: This expression was expected to but here has type 'objnull' -neg20.fs(195,5,195,10): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(195,5,195,10): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(198,5,198,11): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(198,5,198,11): typecheck warning FS0842: This attribute is not valid for use on this language element neg20.fs(202,7,202,9): typecheck error FS0825: The 'DefaultValue' attribute may only be used on 'val' declarations -neg20.fs(204,5,204,14): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(204,5,204,14): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(207,5,207,11): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(207,5,207,11): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(210,5,210,12): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(210,5,210,12): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(213,5,213,33): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(213,5,213,33): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(216,5,216,12): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(216,5,216,12): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(219,5,219,15): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(219,5,219,15): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(222,5,222,31): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(222,5,222,31): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(225,5,225,22): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(225,5,225,22): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(228,5,228,23): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(228,5,228,23): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(231,5,231,21): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(231,5,231,21): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(234,5,234,34): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(234,5,234,34): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(237,5,237,34): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(237,5,237,34): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(240,5,240,23): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(240,5,240,23): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(243,5,243,23): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(243,5,243,23): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(249,9,249,27): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(249,9,249,27): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(255,5,255,28): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(255,5,255,28): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(258,5,258,38): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(258,5,258,38): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(261,5,261,17): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(261,5,261,17): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(265,5,265,24): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(265,5,265,24): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(268,5,268,27): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(268,5,268,27): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(271,5,271,15): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(271,5,271,15): typecheck warning FS0842: This attribute is not valid for use on this language element neg20.fs(278,14,278,95): typecheck error FS0507: No accessible member or object constructor named 'ProcessStartInfo' takes 0 arguments. Note the call to this member also provides 2 named arguments. diff --git a/tests/fsharp/typecheck/sigs/neg32.bsl b/tests/fsharp/typecheck/sigs/neg32.bsl index 87fbc723312..376138c1858 100644 --- a/tests/fsharp/typecheck/sigs/neg32.bsl +++ b/tests/fsharp/typecheck/sigs/neg32.bsl @@ -1,5 +1,5 @@ -neg32.fs(17,11,17,56): typecheck error FS0842: This attribute is not valid for use on this language element +neg32.fs(17,11,17,56): typecheck warning FS0842: This attribute is not valid for use on this language element neg32.fs(24,15,24,16): typecheck error FS0043: The member or object constructor 'TryParse' does not take 1 argument(s). An overload was found taking 2 arguments. diff --git a/tests/fsharp/typecheck/sigs/version50/neg20.bsl b/tests/fsharp/typecheck/sigs/version50/neg20.bsl index 394f7777b2a..f85f1d5d14f 100644 --- a/tests/fsharp/typecheck/sigs/version50/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/version50/neg20.bsl @@ -261,53 +261,53 @@ neg20.fs(190,34,190,39): typecheck error FS0001: This expression was expected to but here has type 'objnull' -neg20.fs(195,5,195,10): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(195,5,195,10): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(198,5,198,11): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(198,5,198,11): typecheck warning FS0842: This attribute is not valid for use on this language element neg20.fs(202,7,202,9): typecheck error FS0825: The 'DefaultValue' attribute may only be used on 'val' declarations -neg20.fs(204,5,204,14): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(204,5,204,14): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(207,5,207,11): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(207,5,207,11): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(210,5,210,12): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(210,5,210,12): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(213,5,213,33): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(213,5,213,33): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(216,5,216,12): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(216,5,216,12): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(219,5,219,15): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(219,5,219,15): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(222,5,222,31): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(222,5,222,31): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(225,5,225,22): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(225,5,225,22): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(228,5,228,23): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(228,5,228,23): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(231,5,231,21): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(231,5,231,21): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(234,5,234,34): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(234,5,234,34): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(237,5,237,34): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(237,5,237,34): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(240,5,240,23): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(240,5,240,23): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(243,5,243,23): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(243,5,243,23): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(249,9,249,27): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(249,9,249,27): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(255,5,255,28): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(255,5,255,28): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(258,5,258,38): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(258,5,258,38): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(261,5,261,17): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(261,5,261,17): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(265,5,265,24): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(265,5,265,24): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(268,5,268,27): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(268,5,268,27): typecheck warning FS0842: This attribute is not valid for use on this language element -neg20.fs(271,5,271,15): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(271,5,271,15): typecheck warning FS0842: This attribute is not valid for use on this language element neg20.fs(278,14,278,95): typecheck error FS0507: No accessible member or object constructor named 'ProcessStartInfo' takes 0 arguments. Note the call to this member also provides 2 named arguments. diff --git a/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/WithOOP/E_GenericUOM01.fs b/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/WithOOP/E_GenericUOM01.fs index 369697935e3..0f27193b5a7 100644 --- a/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/WithOOP/E_GenericUOM01.fs +++ b/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/WithOOP/E_GenericUOM01.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #UnitsOfMeasure #ObjectOrientedTypes // Verify error when putting invalid attributes on type arguments // (We should only allow [].) -//This attribute is not valid for use on this language element +//This attribute is not valid for use on this language element open System From 6f2b7064781a2c33c254f17ffac1a31a8cd3f41e Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 29 Apr 2025 09:43:56 +0100 Subject: [PATCH 04/22] update baselines --- tests/fsharp/typecheck/sigs/neg16.bsl | 4 +- tests/fsharp/typecheck/sigs/neg20.bsl | 48 ++++++++++--------- tests/fsharp/typecheck/sigs/neg32.bsl | 4 +- .../fsharp/typecheck/sigs/version50/neg20.bsl | 48 ++++++++++--------- 4 files changed, 54 insertions(+), 50 deletions(-) diff --git a/tests/fsharp/typecheck/sigs/neg16.bsl b/tests/fsharp/typecheck/sigs/neg16.bsl index 448ca9127be..4c2300470f7 100644 --- a/tests/fsharp/typecheck/sigs/neg16.bsl +++ b/tests/fsharp/typecheck/sigs/neg16.bsl @@ -13,9 +13,9 @@ neg16.fs(44,10,44,11): typecheck error FS0934: Records, union, abbreviations and neg16.fs(47,10,47,13): typecheck error FS0934: Records, union, abbreviations and struct types cannot have the 'AllowNullLiteral' attribute -neg16.fs(49,7,49,23): typecheck warning FS0842: This attribute is not valid for use on this language element +neg16.fs(49,7,49,23): typecheck error FS0842: This attribute is not valid for use on this language element -neg16.fs(52,7,52,23): typecheck warning FS0842: This attribute is not valid for use on this language element +neg16.fs(52,7,52,23): typecheck error FS0842: This attribute is not valid for use on this language element neg16.fs(59,8,59,17): typecheck error FS0001: This expression was expected to have type 'Choice<'a,'b>' diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl index 28fa11b53f7..2ff8515a78a 100644 --- a/tests/fsharp/typecheck/sigs/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/neg20.bsl @@ -213,53 +213,53 @@ neg20.fs(190,34,190,39): typecheck error FS0001: This expression was expected to but here has type 'objnull' -neg20.fs(195,5,195,10): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(195,5,195,10): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(198,5,198,11): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(198,5,198,11): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(202,7,202,9): typecheck error FS0825: The 'DefaultValue' attribute may only be used on 'val' declarations -neg20.fs(204,5,204,14): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(204,5,204,14): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(207,5,207,11): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(207,5,207,11): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(210,5,210,12): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(210,5,210,12): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(213,5,213,33): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(213,5,213,33): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(216,5,216,12): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(216,5,216,12): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(219,5,219,15): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(219,5,219,15): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(222,5,222,31): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(222,5,222,31): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(225,5,225,22): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(225,5,225,22): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(228,5,228,23): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(228,5,228,23): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(231,5,231,21): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(231,5,231,21): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(234,5,234,34): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(234,5,234,34): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(237,5,237,34): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(237,5,237,34): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(240,5,240,23): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(240,5,240,23): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(243,5,243,23): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(243,5,243,23): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(249,9,249,27): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(249,9,249,27): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(255,5,255,28): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(255,5,255,28): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(258,5,258,38): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(258,5,258,38): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(261,5,261,17): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(261,5,261,17): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(265,5,265,24): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(265,5,265,24): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(268,5,268,27): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(268,5,268,27): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(271,5,271,15): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(271,5,271,15): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(278,14,278,95): typecheck error FS0507: No accessible member or object constructor named 'ProcessStartInfo' takes 0 arguments. Note the call to this member also provides 2 named arguments. @@ -294,6 +294,7 @@ neg20.fs(335,11,335,24): typecheck error FS0041: A unique overload for method 'S Known type of argument: 'a0 Candidates: + - System.String(value: System.ReadOnlySpan) : System.String - System.String(value: char array) : System.String - System.String(value: nativeptr) : System.String - System.String(value: nativeptr) : System.String @@ -303,6 +304,7 @@ neg20.fs(336,11,336,22): typecheck error FS0041: A unique overload for method 'G Known type of argument: 'a0 Candidates: + - System.Guid(b: System.ReadOnlySpan) : System.Guid - System.Guid(b: byte array) : System.Guid - System.Guid(g: string) : System.Guid diff --git a/tests/fsharp/typecheck/sigs/neg32.bsl b/tests/fsharp/typecheck/sigs/neg32.bsl index 376138c1858..7649c0719b5 100644 --- a/tests/fsharp/typecheck/sigs/neg32.bsl +++ b/tests/fsharp/typecheck/sigs/neg32.bsl @@ -1,7 +1,7 @@ -neg32.fs(17,11,17,56): typecheck warning FS0842: This attribute is not valid for use on this language element +neg32.fs(17,11,17,56): typecheck error FS0842: This attribute is not valid for use on this language element -neg32.fs(24,15,24,16): typecheck error FS0043: The member or object constructor 'TryParse' does not take 1 argument(s). An overload was found taking 2 arguments. +neg32.fs(24,15,24,16): typecheck error FS0043: The member or object constructor 'TryParse' does not take 1 argument(s). An overload was found taking 4 arguments. neg32.fs(43,17,43,19): typecheck error FS0039: The type parameter 'T is not defined. diff --git a/tests/fsharp/typecheck/sigs/version50/neg20.bsl b/tests/fsharp/typecheck/sigs/version50/neg20.bsl index f85f1d5d14f..d5de8268fab 100644 --- a/tests/fsharp/typecheck/sigs/version50/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/version50/neg20.bsl @@ -261,53 +261,53 @@ neg20.fs(190,34,190,39): typecheck error FS0001: This expression was expected to but here has type 'objnull' -neg20.fs(195,5,195,10): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(195,5,195,10): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(198,5,198,11): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(198,5,198,11): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(202,7,202,9): typecheck error FS0825: The 'DefaultValue' attribute may only be used on 'val' declarations -neg20.fs(204,5,204,14): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(204,5,204,14): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(207,5,207,11): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(207,5,207,11): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(210,5,210,12): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(210,5,210,12): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(213,5,213,33): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(213,5,213,33): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(216,5,216,12): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(216,5,216,12): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(219,5,219,15): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(219,5,219,15): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(222,5,222,31): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(222,5,222,31): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(225,5,225,22): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(225,5,225,22): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(228,5,228,23): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(228,5,228,23): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(231,5,231,21): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(231,5,231,21): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(234,5,234,34): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(234,5,234,34): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(237,5,237,34): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(237,5,237,34): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(240,5,240,23): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(240,5,240,23): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(243,5,243,23): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(243,5,243,23): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(249,9,249,27): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(249,9,249,27): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(255,5,255,28): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(255,5,255,28): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(258,5,258,38): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(258,5,258,38): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(261,5,261,17): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(261,5,261,17): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(265,5,265,24): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(265,5,265,24): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(268,5,268,27): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(268,5,268,27): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(271,5,271,15): typecheck warning FS0842: This attribute is not valid for use on this language element +neg20.fs(271,5,271,15): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(278,14,278,95): typecheck error FS0507: No accessible member or object constructor named 'ProcessStartInfo' takes 0 arguments. Note the call to this member also provides 2 named arguments. @@ -342,6 +342,7 @@ neg20.fs(335,11,335,24): typecheck error FS0041: A unique overload for method 'S Known type of argument: 'a0 Candidates: + - System.String(value: System.ReadOnlySpan) : System.String - System.String(value: char array) : System.String - System.String(value: nativeptr) : System.String - System.String(value: nativeptr) : System.String @@ -351,6 +352,7 @@ neg20.fs(336,11,336,22): typecheck error FS0041: A unique overload for method 'G Known type of argument: 'a0 Candidates: + - System.Guid(b: System.ReadOnlySpan) : System.Guid - System.Guid(b: byte array) : System.Guid - System.Guid(g: string) : System.Guid From 75d8f5ef637741991df6c15ae75d202b8412dd65 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 29 Apr 2025 19:33:38 +0100 Subject: [PATCH 05/22] Update baselines --- tests/fsharp/typecheck/sigs/neg20.bsl | 2 -- tests/fsharp/typecheck/sigs/neg32.bsl | 2 +- tests/fsharp/typecheck/sigs/version50/neg20.bsl | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl index 2ff8515a78a..5229dcaacf6 100644 --- a/tests/fsharp/typecheck/sigs/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/neg20.bsl @@ -294,7 +294,6 @@ neg20.fs(335,11,335,24): typecheck error FS0041: A unique overload for method 'S Known type of argument: 'a0 Candidates: - - System.String(value: System.ReadOnlySpan) : System.String - System.String(value: char array) : System.String - System.String(value: nativeptr) : System.String - System.String(value: nativeptr) : System.String @@ -304,7 +303,6 @@ neg20.fs(336,11,336,22): typecheck error FS0041: A unique overload for method 'G Known type of argument: 'a0 Candidates: - - System.Guid(b: System.ReadOnlySpan) : System.Guid - System.Guid(b: byte array) : System.Guid - System.Guid(g: string) : System.Guid diff --git a/tests/fsharp/typecheck/sigs/neg32.bsl b/tests/fsharp/typecheck/sigs/neg32.bsl index 7649c0719b5..87fbc723312 100644 --- a/tests/fsharp/typecheck/sigs/neg32.bsl +++ b/tests/fsharp/typecheck/sigs/neg32.bsl @@ -1,7 +1,7 @@ neg32.fs(17,11,17,56): typecheck error FS0842: This attribute is not valid for use on this language element -neg32.fs(24,15,24,16): typecheck error FS0043: The member or object constructor 'TryParse' does not take 1 argument(s). An overload was found taking 4 arguments. +neg32.fs(24,15,24,16): typecheck error FS0043: The member or object constructor 'TryParse' does not take 1 argument(s). An overload was found taking 2 arguments. neg32.fs(43,17,43,19): typecheck error FS0039: The type parameter 'T is not defined. diff --git a/tests/fsharp/typecheck/sigs/version50/neg20.bsl b/tests/fsharp/typecheck/sigs/version50/neg20.bsl index d5de8268fab..394f7777b2a 100644 --- a/tests/fsharp/typecheck/sigs/version50/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/version50/neg20.bsl @@ -342,7 +342,6 @@ neg20.fs(335,11,335,24): typecheck error FS0041: A unique overload for method 'S Known type of argument: 'a0 Candidates: - - System.String(value: System.ReadOnlySpan) : System.String - System.String(value: char array) : System.String - System.String(value: nativeptr) : System.String - System.String(value: nativeptr) : System.String @@ -352,7 +351,6 @@ neg20.fs(336,11,336,22): typecheck error FS0041: A unique overload for method 'G Known type of argument: 'a0 Candidates: - - System.Guid(b: System.ReadOnlySpan) : System.Guid - System.Guid(b: byte array) : System.Guid - System.Guid(g: string) : System.Guid From 4248f2a9225b2533cb4137d1e1b4311ce9e3cad1 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 30 Apr 2025 21:58:10 +0100 Subject: [PATCH 06/22] Move attribute form logic to an AP --- .../Checking/Expressions/CheckExpressions.fs | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index e2d21975311..567e1da0310 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -3187,6 +3187,24 @@ let BuildRecdFieldSet g m objExpr (rfinfo: RecdFieldInfo) argExpr = let wrap, objExpr, _readonly, _writeonly = mkExprAddrOfExpr g boxity false DefinitelyMutates objExpr None m wrap (mkRecdFieldSetViaExprAddr (objExpr, rfinfo.RecdFieldRef, rfinfo.TypeInst, argExpr, m) ) +// This is used to check the target of an attribute with the form of +// Long Form: [] +// Short Form: [] +let (|LongFormAttrTarget|UnrecognizedLongAttrTarget|ShortFormAttributeTarget|) (targetIndicator: Ident option) = + match targetIndicator with + | Some id when id.idText = "assembly" -> LongFormAttrTarget AttributeTargets.Assembly + | Some id when id.idText = "module" -> LongFormAttrTarget AttributeTargets.Module + | Some id when id.idText = "return" -> LongFormAttrTarget AttributeTargets.ReturnValue + | Some id when id.idText = "field" -> LongFormAttrTarget AttributeTargets.Field + | Some id when id.idText = "property" -> LongFormAttrTarget AttributeTargets.Property + | Some id when id.idText = "method" -> LongFormAttrTarget AttributeTargets.Method + | Some id when id.idText = "param" -> LongFormAttrTarget AttributeTargets.Parameter + | Some id when id.idText = "type" -> LongFormAttrTarget AttributeTargets.TyconDecl + | Some id when id.idText = "constructor" -> LongFormAttrTarget AttributeTargets.Constructor + | Some id when id.idText = "event" -> LongFormAttrTarget AttributeTargets.Event + | Some id -> UnrecognizedLongAttrTarget id + | None -> ShortFormAttributeTarget + //------------------------------------------------------------------------- // Helpers dealing with named and optional args at callsites //------------------------------------------------------------------------- @@ -11344,27 +11362,18 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn (validOnDefault, inheritedDefault) | _ -> (validOnDefault, inheritedDefault) - let possibleTgts = enum validOn &&& attrTgt - let directedTgts = + let attributeTargets = enum validOn &&& attrTgt + let directedTargets = match targetIndicator with - | Some id when id.idText = "assembly" -> AttributeTargets.Assembly - | Some id when id.idText = "module" -> AttributeTargets.Module - | Some id when id.idText = "return" -> AttributeTargets.ReturnValue - | Some id when id.idText = "field" -> AttributeTargets.Field - | Some id when id.idText = "property" -> AttributeTargets.Property - | Some id when id.idText = "method" -> AttributeTargets.Method - | Some id when id.idText = "param" -> AttributeTargets.Parameter - | Some id when id.idText = "type" -> AttributeTargets.TyconDecl - | Some id when id.idText = "constructor" -> AttributeTargets.Constructor - | Some id when id.idText = "event" -> AttributeTargets.Event - | Some id -> - errorR(Error(FSComp.SR.tcUnrecognizedAttributeTarget(), id.idRange)) - possibleTgts - // mask explicit targets - | _ -> possibleTgts &&& ~~~ attrEx - let constrainedTgts = possibleTgts &&& directedTgts - if constrainedTgts = enum 0 then - if (directedTgts = AttributeTargets.Assembly || directedTgts = AttributeTargets.Module) then + | LongFormAttrTarget attrTarget -> attrTarget + | UnrecognizedLongAttrTarget attrTarget -> + errorR(Error(FSComp.SR.tcUnrecognizedAttributeTarget(), attrTarget.idRange)) + attributeTargets + | ShortFormAttributeTarget -> attributeTargets &&& ~~~ attrEx + + let constrainedTargets = attributeTargets &&& directedTargets + if constrainedTargets = enum 0 then + if (directedTargets = AttributeTargets.Assembly || directedTargets = AttributeTargets.Module) then error(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElementUseDo(), mAttr)) else warning(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElement(), mAttr)) @@ -11428,11 +11437,11 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn if isStruct then error (Error(FSComp.SR.tcCustomAttributeMustBeReferenceType(), m)) if args.Length <> ilMethRef.ArgTypes.Length then error (Error(FSComp.SR.tcCustomAttributeArgumentMismatch(), m)) let args = args |> List.map mkAttribExpr - Attrib(tcref, ILAttrib ilMethRef, args, namedAttribArgMap, isAppliedToGetterOrSetter, Some constrainedTgts, m) + Attrib(tcref, ILAttrib ilMethRef, args, namedAttribArgMap, isAppliedToGetterOrSetter, Some constrainedTargets, m) | Expr.App (InnerExprPat(ExprValWithPossibleTypeInst(vref, _, _, _)), _, _, args, _) -> let args = args |> List.collect (function Expr.Const (Const.Unit, _, _) -> [] | expr -> tryDestRefTupleExpr expr) |> List.map mkAttribExpr - Attrib(tcref, FSAttrib vref, args, namedAttribArgMap, isAppliedToGetterOrSetter, Some constrainedTgts, mAttr) + Attrib(tcref, FSAttrib vref, args, namedAttribArgMap, isAppliedToGetterOrSetter, Some constrainedTargets, mAttr) | _ -> error (Error(FSComp.SR.tcCustomAttributeMustInvokeConstructor(), mAttr)) @@ -11440,7 +11449,7 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn | _ -> error(Error(FSComp.SR.tcAttributeExpressionsMustBeConstructorCalls(), mAttr)) - [ (constrainedTgts, attrib) ], false + [ (constrainedTargets, attrib) ], false and TcAttributesWithPossibleTargetsEx canFail (cenv: cenv) env attrTgt attrEx synAttribs = From 549f961d937e05ecee0672b560be26d4ca0acdda Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 10 Jun 2025 20:56:43 +0100 Subject: [PATCH 07/22] Add new parser rule and syntax tree tests --- src/Compiler/pars.fsy | 32 ++++++++++ .../SynType/Typed LetBang AndBang 01.fs | 7 +++ .../SynType/Typed LetBang AndBang 01.fs.bsl | 56 +++++++++++++++++ .../SynType/Typed LetBang AndBang 02.fs | 7 +++ .../SynType/Typed LetBang AndBang 02.fs.bsl | 60 +++++++++++++++++++ 5 files changed, 162 insertions(+) create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 01.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 01.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs.bsl diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index f4c291ce262..33691a95c86 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4107,6 +4107,22 @@ moreBinders: let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = Some mIn } SynExprAndBang(spBind, $1, true, $2, $4, m, trivia) :: $6 } + | AND_BANG headBindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock IN moreBinders %prec expr_let + { // Handle type annotations on patterns in and! bindings + // Example: and! y: string = asyncString() + let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 6) + let pat = + match $3 with + | None -> $2 + | Some (_, SynReturnInfo((ty, _), _)) -> + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang ty.Range + SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) + let mEquals = rhs parseState 4 + let m = unionRanges (rhs parseState 1) $5.Range + let mIn = rhs parseState 6 + let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = Some mIn } + SynExprAndBang(spBind, false, true, pat, $5, m, trivia) :: $7 } + | OAND_BANG headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let { let report, mIn, _ = $5 report "and!" (rhs parseState 1) // report unterminated error @@ -4116,6 +4132,22 @@ moreBinders: let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = mIn } SynExprAndBang(spBind, $1, true, $2, $4, m, trivia) :: $7 } + | OAND_BANG headBindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let + { // Handle type annotations on patterns in and! bindings (offside-sensitive version) + let report, mIn, _ = $6 + report "and!" (rhs parseState 1) // report unterminated error + let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $5.Range) + let pat = + match $3 with + | None -> $2 + | Some (_, SynReturnInfo((ty, _), _)) -> + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang ty.Range + SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) + let mEquals = rhs parseState 4 + let m = unionRanges (rhs parseState 1) $5.Range + let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = mIn } + SynExprAndBang(spBind, false, true, pat, $5, m, trivia) :: $8 } + | %prec prec_no_more_attr_bindings { [] } diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 01.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 01.fs new file mode 100644 index 00000000000..5ec258108d5 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 01.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! res: int = async { return 1 } + and! res2: int = async { return 2 } + return res +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 01.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 01.fs.bsl new file mode 100644 index 00000000000..0aa056d6da5 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 01.fs.bsl @@ -0,0 +1,56 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 01.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,38), false, true, + Typed + (Named (SynIdent (res, None), false, None, (4,9--4,12)), + LongIdent (SynLongIdent ([int], [], [None])), + (4,9--4,17)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 1, (4,35--4,36)), + (4,28--4,36), + { YieldOrReturnKeyword = (4,28--4,34) }), + (4,26--4,38)), (4,20--4,38)), + [SynExprAndBang + (Yes (5,4--5,39), false, true, + Typed + (Named + (SynIdent (res2, None), false, None, (5,9--5,13)), + LongIdent (SynLongIdent ([int], [], [None])), + (5,9--5,18)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 2, (5,36--5,37)), + (5,29--5,37), + { YieldOrReturnKeyword = (5,29--5,35) }), + (5,27--5,39)), (5,21--5,39)), (5,4--5,39), + { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,19--5,20) + InKeyword = None })], + YieldOrReturn + ((false, true), Ident res, (6,4--6,14), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,14), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,18--4,19) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs new file mode 100644 index 00000000000..9e1d620a319 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (res: int) = async { return 1 } + and! (res2: int) = async { return 2 } + return res +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs.bsl new file mode 100644 index 00000000000..c6ad9a45417 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs.bsl @@ -0,0 +1,60 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 02.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,40), false, true, + Paren + (Typed + (Named + (SynIdent (res, None), false, None, (4,10--4,13)), + LongIdent (SynLongIdent ([int], [], [None])), + (4,10--4,18)), (4,9--4,19)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 1, (4,37--4,38)), + (4,30--4,38), + { YieldOrReturnKeyword = (4,30--4,36) }), + (4,28--4,40)), (4,22--4,40)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + Paren + (Typed + (Named + (SynIdent (res2, None), false, None, + (5,10--5,14)), + LongIdent (SynLongIdent ([int], [], [None])), + (5,10--5,19)), (5,9--5,20)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 2, (5,38--5,39)), + (5,31--5,39), + { YieldOrReturnKeyword = (5,31--5,37) }), + (5,29--5,41)), (5,23--5,41)), (5,4--5,41), + { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,21--5,22) + InKeyword = None })], + YieldOrReturn + ((false, true), Ident res, (6,4--6,14), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,14), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,20--4,21) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) From b3f4baa14d6824a2b6d23be48f16cf6a173a476c Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 10 Jun 2025 21:22:58 +0100 Subject: [PATCH 08/22] Add CE test that uses let! and and! --- .../Language/ComputationExpressionTests.fs | 120 +++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index da918ffc00a..04ef2492fc3 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -1521,4 +1521,122 @@ let fooTask () : Task = task { is not compatible with type 'TaskCode' ") - ] \ No newline at end of file + ] + + [] + let ``Version 9.0: and! with type annotations requires parentheses`` () = + FSharp """ +module Test + +type ParallelBuilder() = + member _.Return(x) = async { return x } + member _.ReturnFrom(computation: Async<'T>) = computation + member _.Bind(computation: Async<'T>, binder: 'T -> Async<'U>) = + async { + let! x = computation + return! binder x + } + member _.Bind2(comp1: Async<'T1>, comp2: Async<'T2>, binder: 'T1 * 'T2 -> Async<'U>) = + async { + let! task1 = Async.StartChild comp1 + let! task2 = Async.StartChild comp2 + let! result1 = task1 + let! result2 = task2 + return! binder (result1, result2) + } + + member _.Zero() = async.Zero() + member _.Combine(comp1, comp2) = async.Combine(comp1, comp2) + member _.Delay(f) = async.Delay(f) + +let parallelCE = ParallelBuilder() + +let testParallel() = + parallelCE { + let! x = async { return 1 } + and! y = async { return 2 } + return x + y + } + +let testParallel2() = + parallelCE { + let! (x: int) = async { return 1 } + and! (y: int) = async { return 2 } + return x + y + } + +let testParallel3() = + parallelCE { + let! x: int = async { return 1 } + and! y: int = async { return 2 } + return x + y + } + """ + |> withLangVersion90 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 44, Col 17, Line 44, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 43, Col 14, Line 43, Col 20, "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: and! with type annotations works without parentheses`` () = + FSharp """ +module Test + +type ParallelBuilder() = + member _.Return(x) = async { return x } + member _.ReturnFrom(computation: Async<'T>) = computation + member _.Bind(computation: Async<'T>, binder: 'T -> Async<'U>) = + async { + let! x = computation + return! binder x + } + member _.Bind2(comp1: Async<'T1>, comp2: Async<'T2>, binder: 'T1 * 'T2 -> Async<'U>) = + async { + let! task1 = Async.StartChild comp1 + let! task2 = Async.StartChild comp2 + let! result1 = task1 + let! result2 = task2 + return! binder (result1, result2) + } + + member _.Zero() = async.Zero() + member _.Combine(comp1, comp2) = async.Combine(comp1, comp2) + member _.Delay(f) = async.Delay(f) + +let parallelCE = ParallelBuilder() + +let testParallel() = + parallelCE { + let! x = async { return 1 } + and! y = async { return 2 } + return x + y + } + +let testParallel2() = + parallelCE { + let! (x: int) = async { return 1 } + and! (y: int) = async { return 2 } + return x + y + } + +let testParallel3() = + parallelCE { + let! x: int = async { return 1 } + and! y: int = async { return 2 } + return x + y + } + +let result = testParallel() |> Async.RunSynchronously +let result2 = testParallel2() |> Async.RunSynchronously +let result3 = testParallel3() |> Async.RunSynchronously +if result <> 3 then failwithf $"Expected 3, but got {result}" +if result2 <> 3 then failwithf $"Expected 3, but got {result2}" +if result3 <> 3 then failwithf $"Expected 3, but got {result3}" + """ + |> withLangVersionPreview + |> asExe + |> compileAndRun + |> shouldSucceed \ No newline at end of file From 98937bca64e24f65a172ebd6249e6913ce7b7d24 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 10 Jun 2025 23:06:15 +0100 Subject: [PATCH 09/22] more syntax tree tests --- .../SyntaxTree/SynType/Typed LetBang 07.fs | 7 +++ .../SynType/Typed LetBang 07.fs.bsl | 35 ++++++++++++ .../SyntaxTree/SynType/Typed LetBang 08.fs | 6 ++ .../SynType/Typed LetBang 08.fs.bsl | 34 +++++++++++ .../SynType/Typed LetBang AndBang 03.fs | 7 +++ .../SynType/Typed LetBang AndBang 03.fs.bsl | 57 +++++++++++++++++++ .../SynType/Typed LetBang AndBang 04.fs | 7 +++ .../SynType/Typed LetBang AndBang 04.fs.bsl | 55 ++++++++++++++++++ .../SynType/Typed LetBang AndBang 05.fs | 7 +++ .../SynType/Typed LetBang AndBang 05.fs.bsl | 56 ++++++++++++++++++ 10 files changed, 271 insertions(+) create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 07.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 07.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 08.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 08.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 04.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 04.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 05.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 05.fs.bsl diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 07.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 07.fs new file mode 100644 index 00000000000..5cbe57f4dbe --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 07.fs @@ -0,0 +1,7 @@ +module Module +async { + let! ({ Name = name }: Person) = asyncPerson() + + return name + +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 07.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 07.fs.bsl new file mode 100644 index 00000000000..9493eb7270f --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 07.fs.bsl @@ -0,0 +1,35 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 07.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,50), false, true, + Paren + (Typed + (Record + ([(([], Name), Some (3,17--3,18), + Named + (SynIdent (name, None), false, None, + (3,19--3,23)))], (3,10--3,25)), + LongIdent (SynLongIdent ([Person], [], [None])), + (3,10--3,33)), (3,9--3,34)), + App + (Atomic, false, Ident asyncPerson, + Const (Unit, (3,48--3,50)), (3,37--3,50)), [], + YieldOrReturn + ((false, true), Ident name, (5,4--5,15), + { YieldOrReturnKeyword = (5,4--5,10) }), (3,4--5,15), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,35--3,36) }), (2,6--7,1)), + (2,0--7,1)), (2,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 08.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 08.fs new file mode 100644 index 00000000000..941456b8732 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 08.fs @@ -0,0 +1,6 @@ +module Module +async { + let! { Name = name }: Person = asyncPerson() + return name + +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 08.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 08.fs.bsl new file mode 100644 index 00000000000..62bf5bc63db --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 08.fs.bsl @@ -0,0 +1,34 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 08.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,48), false, true, + Typed + (Record + ([(([], Name), Some (3,16--3,17), + Named + (SynIdent (name, None), false, None, + (3,18--3,22)))], (3,9--3,24)), + LongIdent (SynLongIdent ([Person], [], [None])), + (3,9--3,32)), + App + (Atomic, false, Ident asyncPerson, + Const (Unit, (3,46--3,48)), (3,35--3,48)), [], + YieldOrReturn + ((false, true), Ident name, (4,4--4,15), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,15), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,33--3,34) }), (2,6--6,1)), + (2,0--6,1)), (2,0--6,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs new file mode 100644 index 00000000000..0e211e05966 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! ({ Name = name; Age = age }: Person) = asyncPerson() + and! ({ Id = id }: User) = asyncUser() + return name +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs.bsl new file mode 100644 index 00000000000..77d69da0a0b --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs.bsl @@ -0,0 +1,57 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 03.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,61), false, true, + Paren + (Typed + (Record + ([(([], Name), Some (4,17--4,18), + Named + (SynIdent (name, None), false, None, + (4,19--4,23))); + (([], Age), Some (4,29--4,30), + Named + (SynIdent (age, None), false, None, + (4,31--4,34)))], (4,10--4,36)), + LongIdent (SynLongIdent ([Person], [], [None])), + (4,10--4,44)), (4,9--4,45)), + App + (Atomic, false, Ident asyncPerson, + Const (Unit, (4,59--4,61)), (4,48--4,61)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + Paren + (Typed + (Record + ([(([], Id), Some (5,15--5,16), + Named + (SynIdent (id, None), false, None, + (5,17--5,19)))], (5,10--5,21)), + LongIdent (SynLongIdent ([User], [], [None])), + (5,10--5,27)), (5,9--5,28)), + App + (Atomic, false, Ident asyncUser, + Const (Unit, (5,40--5,42)), (5,31--5,42)), + (5,4--5,42), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,29--5,30) + InKeyword = None })], + YieldOrReturn + ((false, true), Ident name, (6,4--6,15), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,15), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,46--4,47) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 04.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 04.fs new file mode 100644 index 00000000000..b7318405b81 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 04.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! { Name = name; Age = age }: Person = asyncPerson() + and! { Id = id }: User = asyncUser() + return name +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 04.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 04.fs.bsl new file mode 100644 index 00000000000..2377382104e --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 04.fs.bsl @@ -0,0 +1,55 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 04.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,59), false, true, + Typed + (Record + ([(([], Name), Some (4,16--4,17), + Named + (SynIdent (name, None), false, None, + (4,18--4,22))); + (([], Age), Some (4,28--4,29), + Named + (SynIdent (age, None), false, None, + (4,30--4,33)))], (4,9--4,35)), + LongIdent (SynLongIdent ([Person], [], [None])), + (4,9--4,43)), + App + (Atomic, false, Ident asyncPerson, + Const (Unit, (4,57--4,59)), (4,46--4,59)), + [SynExprAndBang + (Yes (5,4--5,40), false, true, + Typed + (Record + ([(([], Id), Some (5,14--5,15), + Named + (SynIdent (id, None), false, None, + (5,16--5,18)))], (5,9--5,20)), + LongIdent (SynLongIdent ([User], [], [None])), + (5,9--5,26)), + App + (Atomic, false, Ident asyncUser, + Const (Unit, (5,38--5,40)), (5,29--5,40)), + (5,4--5,40), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,27--5,28) + InKeyword = None })], + YieldOrReturn + ((false, true), Ident name, (6,4--6,15), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,15), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,44--4,45) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 05.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 05.fs new file mode 100644 index 00000000000..3d99e5c9447 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 05.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! ({ Name = name; Age = age }: Person) = asyncPerson() + and! { Id = id }: User = asyncUser() + return name +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 05.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 05.fs.bsl new file mode 100644 index 00000000000..2309e7f9490 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 05.fs.bsl @@ -0,0 +1,56 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 05.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,61), false, true, + Paren + (Typed + (Record + ([(([], Name), Some (4,17--4,18), + Named + (SynIdent (name, None), false, None, + (4,19--4,23))); + (([], Age), Some (4,29--4,30), + Named + (SynIdent (age, None), false, None, + (4,31--4,34)))], (4,10--4,36)), + LongIdent (SynLongIdent ([Person], [], [None])), + (4,10--4,44)), (4,9--4,45)), + App + (Atomic, false, Ident asyncPerson, + Const (Unit, (4,59--4,61)), (4,48--4,61)), + [SynExprAndBang + (Yes (5,4--5,40), false, true, + Typed + (Record + ([(([], Id), Some (5,14--5,15), + Named + (SynIdent (id, None), false, None, + (5,16--5,18)))], (5,9--5,20)), + LongIdent (SynLongIdent ([User], [], [None])), + (5,9--5,26)), + App + (Atomic, false, Ident asyncUser, + Const (Unit, (5,38--5,40)), (5,29--5,40)), + (5,4--5,40), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,27--5,28) + InKeyword = None })], + YieldOrReturn + ((false, true), Ident name, (6,4--6,15), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,15), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,46--4,47) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) From a020505e619e6779eb64ee4feac6b1347b4aec5e Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 10 Jun 2025 23:43:11 +0100 Subject: [PATCH 10/22] more syntax tree tests --- .../SyntaxTree/SynType/Typed LetBang 09.fs | 5 ++ .../SynType/Typed LetBang 09.fs.bsl | 34 +++++++++ .../SyntaxTree/SynType/Typed LetBang 10.fs | 5 ++ .../SynType/Typed LetBang 10.fs.bsl | 32 ++++++++ .../SyntaxTree/SynType/Typed LetBang 11.fs | 5 ++ .../SynType/Typed LetBang 11.fs.bsl | 40 ++++++++++ .../SyntaxTree/SynType/Typed LetBang 12.fs | 5 ++ .../SynType/Typed LetBang 12.fs.bsl | 38 ++++++++++ .../SynType/Typed LetBang AndBang 06.fs | 7 ++ .../SynType/Typed LetBang AndBang 06.fs.bsl | 62 +++++++++++++++ .../SynType/Typed LetBang AndBang 07.fs | 7 ++ .../SynType/Typed LetBang AndBang 07.fs.bsl | 58 ++++++++++++++ .../SynType/Typed LetBang AndBang 08.fs | 7 ++ .../SynType/Typed LetBang AndBang 08.fs.bsl | 75 +++++++++++++++++++ .../SynType/Typed LetBang AndBang 09.fs | 7 ++ .../SynType/Typed LetBang AndBang 09.fs.bsl | 70 +++++++++++++++++ 16 files changed, 457 insertions(+) create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs.bsl diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs new file mode 100644 index 00000000000..ffae5310fb2 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs @@ -0,0 +1,5 @@ +module Module +async { + let! (Union value) = asyncOption() + return value +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs.bsl new file mode 100644 index 00000000000..0516dc630a8 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs.bsl @@ -0,0 +1,34 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 09.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,38), false, true, + Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (3,16--3,21))], None, (3,10--3,21)), + (3,9--3,22)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (3,36--3,38)), (3,25--3,38)), [], + YieldOrReturn + ((false, true), Ident value, (4,4--4,16), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,16), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,23--3,24) }), (2,6--5,1)), + (2,0--5,1)), (2,0--5,1))], + 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/SynType/Typed LetBang 10.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs new file mode 100644 index 00000000000..f96163293b7 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs @@ -0,0 +1,5 @@ +module Module +async { + let! Union value = asyncOption() + return value +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs.bsl new file mode 100644 index 00000000000..f3758aff371 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs.bsl @@ -0,0 +1,32 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 10.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,36), false, true, + LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (3,15--3,20))], None, (3,9--3,20)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (3,34--3,36)), (3,23--3,36)), [], + YieldOrReturn + ((false, true), Ident value, (4,4--4,16), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,16), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,21--3,22) }), (2,6--5,1)), + (2,0--5,1)), (2,0--5,1))], + 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/SynType/Typed LetBang 11.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs new file mode 100644 index 00000000000..48e18bbe04f --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs @@ -0,0 +1,5 @@ +module Module +async { + let! (Union value): int option = asyncOption() + return value +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs.bsl new file mode 100644 index 00000000000..096e0effc20 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs.bsl @@ -0,0 +1,40 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 11.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,50), false, true, + Typed + (Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (3,16--3,21))], None, (3,10--3,21)), + (3,9--3,22)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (3,24--3,34)), (3,9--3,34)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (3,48--3,50)), (3,37--3,50)), [], + YieldOrReturn + ((false, true), Ident value, (4,4--4,16), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,16), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,35--3,36) }), (2,6--5,1)), + (2,0--5,1)), (2,0--5,1))], + 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/SynType/Typed LetBang 12.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs new file mode 100644 index 00000000000..4fb0e0b1a5e --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs @@ -0,0 +1,5 @@ +module Module +async { + let! Union value: int option = asyncOption() + return value +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs.bsl new file mode 100644 index 00000000000..b274a8880f3 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs.bsl @@ -0,0 +1,38 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 12.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,48), false, true, + Typed + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (3,15--3,20))], None, (3,9--3,20)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (3,22--3,32)), (3,9--3,32)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (3,46--3,48)), (3,35--3,48)), [], + YieldOrReturn + ((false, true), Ident value, (4,4--4,16), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,16), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,33--3,34) }), (2,6--5,1)), + (2,0--5,1)), (2,0--5,1))], + 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/SynType/Typed LetBang AndBang 06.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs new file mode 100644 index 00000000000..7fa5f22d509 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (Union value) = asyncOption() + and! (Union value2) = asyncOption() + return value + value2 +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl new file mode 100644 index 00000000000..564967a7a33 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl @@ -0,0 +1,62 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 06.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,38), false, true, + Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (4,16--4,21))], None, (4,10--4,21)), + (4,9--4,22)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (4,36--4,38)), (4,25--4,38)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value2, None), false, None, + (5,16--5,22))], None, (5,10--5,22)), + (5,9--5,23)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (5,37--5,39)), (5,26--5,39)), + (5,4--5,39), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,24--5,25) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,17--6,18)), Ident value, (6,11--6,18)), + Ident value2, (6,11--6,25)), (6,4--6,25), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,25), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,23--4,24) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs new file mode 100644 index 00000000000..4a8cdf52b91 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! Union value = asyncOption() + and! Union value2 = asyncOption() + return value + value2 +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl new file mode 100644 index 00000000000..8fab57b3ca4 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl @@ -0,0 +1,58 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 07.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,36), false, true, + LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (4,15--4,20))], None, (4,9--4,20)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (4,34--4,36)), (4,23--4,36)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value2, None), false, None, + (5,15--5,21))], None, (5,9--5,21)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (5,35--5,37)), (5,24--5,37)), + (5,4--5,37), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,22--5,23) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,17--6,18)), Ident value, (6,11--6,18)), + Ident value2, (6,11--6,25)), (6,4--6,25), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,25), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,21--4,22) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs new file mode 100644 index 00000000000..730c2d82016 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (Union value): int option = asyncOption() + and! (Union value2): int option = asyncOption() + return value + value2 +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs.bsl new file mode 100644 index 00000000000..7ca03b4f9e3 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs.bsl @@ -0,0 +1,75 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 08.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,50), false, true, + Typed + (Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (4,16--4,21))], None, (4,10--4,21)), + (4,9--4,22)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (4,24--4,34)), (4,9--4,34)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (4,48--4,50)), (4,37--4,50)), + [SynExprAndBang + (Yes (5,4--5,51), false, true, + Typed + (Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, + None, + Pats + [Named + (SynIdent (value2, None), false, None, + (5,16--5,22))], None, (5,10--5,22)), + (5,9--5,23)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], + [], None, true, (5,25--5,35)), (5,9--5,35)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (5,49--5,51)), (5,38--5,51)), + (5,4--5,51), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,36--5,37) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,17--6,18)), Ident value, (6,11--6,18)), + Ident value2, (6,11--6,25)), (6,4--6,25), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,25), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,35--4,36) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs new file mode 100644 index 00000000000..f5221c58c89 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! Union value: int option = asyncOption() + and! Union value2: int option = asyncOption() + return value + value2 +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs.bsl new file mode 100644 index 00000000000..0233ea37538 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs.bsl @@ -0,0 +1,70 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 09.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,48), false, true, + Typed + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (4,15--4,20))], None, (4,9--4,20)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (4,22--4,32)), (4,9--4,32)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (4,46--4,48)), (4,35--4,48)), + [SynExprAndBang + (Yes (5,4--5,49), false, true, + Typed + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value2, None), false, None, + (5,15--5,21))], None, (5,9--5,21)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], + [], None, true, (5,23--5,33)), (5,9--5,33)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (5,47--5,49)), (5,36--5,49)), + (5,4--5,49), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,34--5,35) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,17--6,18)), Ident value, (6,11--6,18)), + Ident value2, (6,11--6,25)), (6,4--6,25), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,25), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,33--4,34) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) From dce81de67c2b59a19e6eb5396109a4f87ee8283b Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Tue, 10 Jun 2025 23:43:11 +0100 Subject: [PATCH 11/22] more syntax tree tests --- .../data/SyntaxTree/SynType/Tuple 15.fs | 3 + .../data/SyntaxTree/SynType/Tuple 15.fs.bsl | 31 ++++++++ .../SyntaxTree/SynType/Typed LetBang 09.fs | 5 ++ .../SynType/Typed LetBang 09.fs.bsl | 34 +++++++++ .../SyntaxTree/SynType/Typed LetBang 10.fs | 5 ++ .../SynType/Typed LetBang 10.fs.bsl | 32 ++++++++ .../SyntaxTree/SynType/Typed LetBang 11.fs | 5 ++ .../SynType/Typed LetBang 11.fs.bsl | 40 ++++++++++ .../SyntaxTree/SynType/Typed LetBang 12.fs | 5 ++ .../SynType/Typed LetBang 12.fs.bsl | 38 ++++++++++ .../SyntaxTree/SynType/Typed LetBang 13.fs | 5 ++ .../SynType/Typed LetBang AndBang 06.fs | 7 ++ .../SynType/Typed LetBang AndBang 06.fs.bsl | 62 +++++++++++++++ .../SynType/Typed LetBang AndBang 07.fs | 7 ++ .../SynType/Typed LetBang AndBang 07.fs.bsl | 58 ++++++++++++++ .../SynType/Typed LetBang AndBang 08.fs | 7 ++ .../SynType/Typed LetBang AndBang 08.fs.bsl | 75 +++++++++++++++++++ .../SynType/Typed LetBang AndBang 09.fs | 7 ++ .../SynType/Typed LetBang AndBang 09.fs.bsl | 70 +++++++++++++++++ .../SynType/Typed LetBang AndBang 10.fs | 7 ++ .../SynType/Typed LetBang AndBang 10.fs.bsl | 67 +++++++++++++++++ .../SynType/Typed LetBang AndBang 11.fs | 7 ++ .../SynType/Typed LetBang AndBang 11.fs.bsl | 64 ++++++++++++++++ .../SynType/Typed LetBang AndBang 12.fs | 7 ++ .../SynType/Typed LetBang AndBang 12.fs.bsl | 56 ++++++++++++++ .../SynType/Typed LetBang AndBang 13.fs | 7 ++ .../SynType/Typed LetBang AndBang 13.fs.bsl | 70 +++++++++++++++++ .../SynType/Typed LetBang AndBang 14.fs | 7 ++ .../SynType/Typed LetBang AndBang 14.fs.bsl | 64 ++++++++++++++++ .../SynType/Typed LetBang AndBang 15.fs | 7 ++ .../SynType/Typed LetBang AndBang 15.fs.bsl | 64 ++++++++++++++++ .../SynType/Typed LetBang AndBang 16.fs | 7 ++ .../SynType/Typed LetBang AndBang 16.fs.bsl | 72 ++++++++++++++++++ .../SynType/Typed LetBang AndBang 17.fs | 7 ++ .../SynType/Typed LetBang AndBang 17.fs.bsl | 75 +++++++++++++++++++ 35 files changed, 1084 insertions(+) create mode 100644 tests/service/data/SyntaxTree/SynType/Tuple 15.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Tuple 15.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 13.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 10.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 10.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 11.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 11.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 14.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 14.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 17.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 17.fs.bsl diff --git a/tests/service/data/SyntaxTree/SynType/Tuple 15.fs b/tests/service/data/SyntaxTree/SynType/Tuple 15.fs new file mode 100644 index 00000000000..eb13b88a326 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Tuple 15.fs @@ -0,0 +1,3 @@ +module Module + +let x: int, y: int = 0, 4 diff --git a/tests/service/data/SyntaxTree/SynType/Tuple 15.fs.bsl b/tests/service/data/SyntaxTree/SynType/Tuple 15.fs.bsl new file mode 100644 index 00000000000..44d8624017b --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Tuple 15.fs.bsl @@ -0,0 +1,31 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Tuple 15.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), + Named (SynIdent (x, None), false, None, (3,4--3,5)), + Some + (SynBindingReturnInfo + (LongIdent (SynLongIdent ([int], [], [None])), + (3,7--3,10), [], { ColonRange = Some (3,5--3,6) })), + Typed + (ArbitraryAfterError ("localBinding2", (3,10--3,10)), + LongIdent (SynLongIdent ([int], [], [None])), (3,10--3,10)), + (3,4--3,5), Yes (3,0--3,10), { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = None })], + (3,0--3,10))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(3,10)-(3,11) parse error Unexpected symbol ',' in binding. Expected '=' or other token. diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs new file mode 100644 index 00000000000..ffae5310fb2 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs @@ -0,0 +1,5 @@ +module Module +async { + let! (Union value) = asyncOption() + return value +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs.bsl new file mode 100644 index 00000000000..0516dc630a8 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 09.fs.bsl @@ -0,0 +1,34 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 09.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,38), false, true, + Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (3,16--3,21))], None, (3,10--3,21)), + (3,9--3,22)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (3,36--3,38)), (3,25--3,38)), [], + YieldOrReturn + ((false, true), Ident value, (4,4--4,16), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,16), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,23--3,24) }), (2,6--5,1)), + (2,0--5,1)), (2,0--5,1))], + 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/SynType/Typed LetBang 10.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs new file mode 100644 index 00000000000..f96163293b7 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs @@ -0,0 +1,5 @@ +module Module +async { + let! Union value = asyncOption() + return value +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs.bsl new file mode 100644 index 00000000000..f3758aff371 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 10.fs.bsl @@ -0,0 +1,32 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 10.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,36), false, true, + LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (3,15--3,20))], None, (3,9--3,20)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (3,34--3,36)), (3,23--3,36)), [], + YieldOrReturn + ((false, true), Ident value, (4,4--4,16), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,16), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,21--3,22) }), (2,6--5,1)), + (2,0--5,1)), (2,0--5,1))], + 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/SynType/Typed LetBang 11.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs new file mode 100644 index 00000000000..48e18bbe04f --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs @@ -0,0 +1,5 @@ +module Module +async { + let! (Union value): int option = asyncOption() + return value +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs.bsl new file mode 100644 index 00000000000..096e0effc20 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 11.fs.bsl @@ -0,0 +1,40 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 11.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,50), false, true, + Typed + (Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (3,16--3,21))], None, (3,10--3,21)), + (3,9--3,22)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (3,24--3,34)), (3,9--3,34)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (3,48--3,50)), (3,37--3,50)), [], + YieldOrReturn + ((false, true), Ident value, (4,4--4,16), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,16), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,35--3,36) }), (2,6--5,1)), + (2,0--5,1)), (2,0--5,1))], + 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/SynType/Typed LetBang 12.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs new file mode 100644 index 00000000000..4fb0e0b1a5e --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs @@ -0,0 +1,5 @@ +module Module +async { + let! Union value: int option = asyncOption() + return value +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs.bsl new file mode 100644 index 00000000000..b274a8880f3 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 12.fs.bsl @@ -0,0 +1,38 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 12.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (3,4--3,48), false, true, + Typed + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (3,15--3,20))], None, (3,9--3,20)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (3,22--3,32)), (3,9--3,32)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (3,46--3,48)), (3,35--3,48)), [], + YieldOrReturn + ((false, true), Ident value, (4,4--4,16), + { YieldOrReturnKeyword = (4,4--4,10) }), (3,4--4,16), + { LetOrUseBangKeyword = (3,4--3,8) + EqualsRange = Some (3,33--3,34) }), (2,6--5,1)), + (2,0--5,1)), (2,0--5,1))], + 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/SynType/Typed LetBang 13.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 13.fs new file mode 100644 index 00000000000..19c127c107f --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 13.fs @@ -0,0 +1,5 @@ +module Module +async { + let! x: int, y: int = asyncInt() + return () +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs new file mode 100644 index 00000000000..7fa5f22d509 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (Union value) = asyncOption() + and! (Union value2) = asyncOption() + return value + value2 +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl new file mode 100644 index 00000000000..564967a7a33 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl @@ -0,0 +1,62 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 06.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,38), false, true, + Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (4,16--4,21))], None, (4,10--4,21)), + (4,9--4,22)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (4,36--4,38)), (4,25--4,38)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value2, None), false, None, + (5,16--5,22))], None, (5,10--5,22)), + (5,9--5,23)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (5,37--5,39)), (5,26--5,39)), + (5,4--5,39), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,24--5,25) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,17--6,18)), Ident value, (6,11--6,18)), + Ident value2, (6,11--6,25)), (6,4--6,25), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,25), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,23--4,24) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs new file mode 100644 index 00000000000..4a8cdf52b91 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! Union value = asyncOption() + and! Union value2 = asyncOption() + return value + value2 +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl new file mode 100644 index 00000000000..8fab57b3ca4 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl @@ -0,0 +1,58 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 07.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,36), false, true, + LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (4,15--4,20))], None, (4,9--4,20)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (4,34--4,36)), (4,23--4,36)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value2, None), false, None, + (5,15--5,21))], None, (5,9--5,21)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (5,35--5,37)), (5,24--5,37)), + (5,4--5,37), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,22--5,23) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,17--6,18)), Ident value, (6,11--6,18)), + Ident value2, (6,11--6,25)), (6,4--6,25), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,25), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,21--4,22) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs new file mode 100644 index 00000000000..730c2d82016 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (Union value): int option = asyncOption() + and! (Union value2): int option = asyncOption() + return value + value2 +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs.bsl new file mode 100644 index 00000000000..7ca03b4f9e3 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 08.fs.bsl @@ -0,0 +1,75 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 08.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,50), false, true, + Typed + (Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (4,16--4,21))], None, (4,10--4,21)), + (4,9--4,22)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (4,24--4,34)), (4,9--4,34)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (4,48--4,50)), (4,37--4,50)), + [SynExprAndBang + (Yes (5,4--5,51), false, true, + Typed + (Paren + (LongIdent + (SynLongIdent ([Union], [], [None]), None, + None, + Pats + [Named + (SynIdent (value2, None), false, None, + (5,16--5,22))], None, (5,10--5,22)), + (5,9--5,23)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], + [], None, true, (5,25--5,35)), (5,9--5,35)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (5,49--5,51)), (5,38--5,51)), + (5,4--5,51), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,36--5,37) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,17--6,18)), Ident value, (6,11--6,18)), + Ident value2, (6,11--6,25)), (6,4--6,25), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,25), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,35--4,36) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs new file mode 100644 index 00000000000..f5221c58c89 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! Union value: int option = asyncOption() + and! Union value2: int option = asyncOption() + return value + value2 +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs.bsl new file mode 100644 index 00000000000..0233ea37538 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 09.fs.bsl @@ -0,0 +1,70 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 09.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,48), false, true, + Typed + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value, None), false, None, + (4,15--4,20))], None, (4,9--4,20)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (4,22--4,32)), (4,9--4,32)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (4,46--4,48)), (4,35--4,48)), + [SynExprAndBang + (Yes (5,4--5,49), false, true, + Typed + (LongIdent + (SynLongIdent ([Union], [], [None]), None, None, + Pats + [Named + (SynIdent (value2, None), false, None, + (5,15--5,21))], None, (5,9--5,21)), + App + (LongIdent (SynLongIdent ([option], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], + [], None, true, (5,23--5,33)), (5,9--5,33)), + App + (Atomic, false, Ident asyncOption, + Const (Unit, (5,47--5,49)), (5,36--5,49)), + (5,4--5,49), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,34--5,35) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,17--6,18)), Ident value, (6,11--6,18)), + Ident value2, (6,11--6,25)), (6,4--6,25), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,25), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,33--4,34) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 10.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 10.fs new file mode 100644 index 00000000000..820ef060e8f --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 10.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (x as y): int = asyncInt() + and! (a as b): string = asyncString() + return x + b +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 10.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 10.fs.bsl new file mode 100644 index 00000000000..4c616752ce3 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 10.fs.bsl @@ -0,0 +1,67 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 10.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,35), false, true, + Typed + (Paren + (As + (Named + (SynIdent (x, None), false, None, (4,10--4,11)), + Named + (SynIdent (y, None), false, None, (4,15--4,16)), + (4,10--4,16)), (4,9--4,17)), + LongIdent (SynLongIdent ([int], [], [None])), + (4,9--4,22)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,33--4,35)), (4,25--4,35)), + [SynExprAndBang + (Yes (5,4--5,41), false, true, + Typed + (Paren + (As + (Named + (SynIdent (a, None), false, None, + (5,10--5,11)), + Named + (SynIdent (b, None), false, None, + (5,15--5,16)), (5,10--5,16)), (5,9--5,17)), + LongIdent (SynLongIdent ([string], [], [None])), + (5,9--5,25)), + App + (Atomic, false, Ident asyncString, + Const (Unit, (5,39--5,41)), (5,28--5,41)), + (5,4--5,41), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,26--5,27) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,13--6,14)), Ident x, (6,11--6,14)), + Ident b, (6,11--6,16)), (6,4--6,16), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,23--4,24) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 11.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 11.fs new file mode 100644 index 00000000000..08da39cd1d8 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 11.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! x as y: int = asyncInt() + and! a as b: string = asyncString() + return x + b +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 11.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 11.fs.bsl new file mode 100644 index 00000000000..4c4991234a3 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 11.fs.bsl @@ -0,0 +1,64 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 11.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,33), false, true, + Typed + (As + (Named + (SynIdent (x, None), false, None, (4,9--4,10)), + Named + (SynIdent (y, None), false, None, (4,14--4,15)), + (4,9--4,15)), + LongIdent (SynLongIdent ([int], [], [None])), + (4,9--4,20)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,31--4,33)), (4,23--4,33)), + [SynExprAndBang + (Yes (5,4--5,39), false, true, + Typed + (As + (Named + (SynIdent (a, None), false, None, (5,9--5,10)), + Named + (SynIdent (b, None), false, None, + (5,14--5,15)), (5,9--5,15)), + LongIdent (SynLongIdent ([string], [], [None])), + (5,9--5,23)), + App + (Atomic, false, Ident asyncString, + Const (Unit, (5,37--5,39)), (5,26--5,39)), + (5,4--5,39), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,24--5,25) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,13--6,14)), Ident x, (6,11--6,14)), + Ident b, (6,11--6,16)), (6,4--6,16), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,21--4,22) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs new file mode 100644 index 00000000000..f8d1d7fad52 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! x as y = asyncInt() + and! a as b = asyncString() + return x + b +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs.bsl new file mode 100644 index 00000000000..bb908917f12 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs.bsl @@ -0,0 +1,56 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 12.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,28), false, true, + As + (Named (SynIdent (x, None), false, None, (4,9--4,10)), + Named (SynIdent (y, None), false, None, (4,14--4,15)), + (4,9--4,15)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,26--4,28)), (4,18--4,28)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + As + (Named + (SynIdent (a, None), false, None, (5,9--5,10)), + Named + (SynIdent (b, None), false, None, (5,14--5,15)), + (5,9--5,15)), + App + (Atomic, false, Ident asyncString, + Const (Unit, (5,29--5,31)), (5,18--5,31)), + (5,4--5,31), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,16--5,17) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,13--6,14)), Ident x, (6,11--6,14)), + Ident b, (6,11--6,16)), (6,4--6,16), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,16--4,17) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs new file mode 100644 index 00000000000..2ec04876505 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! ([| first; second |]: int array) = asyncArray() + and! (head :: tail: string list) = asyncList() + return first +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs.bsl new file mode 100644 index 00000000000..c9f68d900fd --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs.bsl @@ -0,0 +1,70 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 13.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,56), false, true, + Paren + (Typed + (ArrayOrList + (true, + [Named + (SynIdent (first, None), false, None, + (4,13--4,18)); + Named + (SynIdent (second, None), false, None, + (4,20--4,26))], (4,10--4,29)), + App + (LongIdent (SynLongIdent ([array], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], + [], None, true, (4,31--4,40)), (4,10--4,40)), + (4,9--4,41)), + App + (Atomic, false, Ident asyncArray, + Const (Unit, (4,54--4,56)), (4,44--4,56)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + Paren + (ListCons + (Named + (SynIdent (head, None), false, None, + (5,10--5,14)), + Typed + (Named + (SynIdent (tail, None), false, None, + (5,18--5,22)), + App + (LongIdent + (SynLongIdent ([list], [], [None])), + None, + [LongIdent + (SynLongIdent ([string], [], [None]))], + [], None, true, (5,24--5,35)), + (5,18--5,35)), (5,10--5,35), + { ColonColonRange = (5,15--5,17) }), + (5,9--5,36)), + App + (Atomic, false, Ident asyncList, + Const (Unit, (5,48--5,50)), (5,39--5,50)), + (5,4--5,50), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,37--5,38) + InKeyword = None })], + YieldOrReturn + ((false, true), Ident first, (6,4--6,16), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,42--4,43) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 14.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 14.fs new file mode 100644 index 00000000000..95522afafc7 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 14.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! [| first; second |]: int array = asyncArray() + and! head :: tail: string list = asyncList() + return first +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 14.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 14.fs.bsl new file mode 100644 index 00000000000..eaefd1aa4ef --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 14.fs.bsl @@ -0,0 +1,64 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 14.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,54), false, true, + Typed + (ArrayOrList + (true, + [Named + (SynIdent (first, None), false, None, + (4,12--4,17)); + Named + (SynIdent (second, None), false, None, + (4,19--4,25))], (4,9--4,28)), + App + (LongIdent (SynLongIdent ([array], [], [None])), + None, + [LongIdent (SynLongIdent ([int], [], [None]))], [], + None, true, (4,30--4,39)), (4,9--4,39)), + App + (Atomic, false, Ident asyncArray, + Const (Unit, (4,52--4,54)), (4,42--4,54)), + [SynExprAndBang + (Yes (5,4--5,48), false, true, + Typed + (ListCons + (Named + (SynIdent (head, None), false, None, + (5,9--5,13)), + Named + (SynIdent (tail, None), false, None, + (5,17--5,21)), (5,9--5,21), + { ColonColonRange = (5,14--5,16) }), + App + (LongIdent (SynLongIdent ([list], [], [None])), + None, + [LongIdent + (SynLongIdent ([string], [], [None]))], [], + None, true, (5,23--5,34)), (5,9--5,34)), + App + (Atomic, false, Ident asyncList, + Const (Unit, (5,46--5,48)), (5,37--5,48)), + (5,4--5,48), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,35--5,36) + InKeyword = None })], + YieldOrReturn + ((false, true), Ident first, (6,4--6,16), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,40--4,41) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs new file mode 100644 index 00000000000..92646da071f --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (x, y): int * int = asyncInt() + and! x: int, y: int = asyncInt() + return () +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs.bsl new file mode 100644 index 00000000000..b66ac37e92f --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs.bsl @@ -0,0 +1,64 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 15.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Equality], [], [Some (OriginalNotation "=")]), + None, (5,24--5,25)), + LetOrUseBang + (Yes (4,4--4,39), false, true, + Typed + (Paren + (Tuple + (false, + [Named + (SynIdent (x, None), false, None, + (4,10--4,11)); + Named + (SynIdent (y, None), false, None, + (4,13--4,14))], [(4,11--4,12)], + (4,10--4,14)), (4,9--4,15)), + Tuple + (false, + [Type + (LongIdent + (SynLongIdent ([int], [], [None]))); + Star (4,21--4,22); + Type + (LongIdent + (SynLongIdent ([int], [], [None])))], + (4,17--4,26)), (4,9--4,26)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,37--4,39)), (4,29--4,39)), [], + Typed + (Ident y, + LongIdent (SynLongIdent ([int], [], [None])), + (5,17--5,23)), (4,4--5,23), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,27--4,28) }), (4,4--5,25)), + ArbitraryAfterError ("declExprInfixEquals", (5,25--5,25)), + (4,4--5,25)), (3,6--7,1)), (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(5,15)-(5,16) parse error Unexpected symbol ',' in expression. Expected '=' or other token. +(4,4)-(4,8) parse error Incomplete value definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let!' keyword. +(5,26)-(5,34) parse error Unexpected start of structured construct in expression +(5,24)-(5,25) parse error Unexpected token '=' or incomplete expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs new file mode 100644 index 00000000000..b01631488a2 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (x, y): int * int = asyncInt() + and! (x: int, y: int) = asyncInt() + return () +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs.bsl new file mode 100644 index 00000000000..c6344f68319 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs.bsl @@ -0,0 +1,72 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 16.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,39), false, true, + Typed + (Paren + (Tuple + (false, + [Named + (SynIdent (x, None), false, None, + (4,10--4,11)); + Named + (SynIdent (y, None), false, None, + (4,13--4,14))], [(4,11--4,12)], (4,10--4,14)), + (4,9--4,15)), + Tuple + (false, + [Type + (LongIdent (SynLongIdent ([int], [], [None]))); + Star (4,21--4,22); + Type + (LongIdent (SynLongIdent ([int], [], [None])))], + (4,17--4,26)), (4,9--4,26)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,37--4,39)), (4,29--4,39)), + [SynExprAndBang + (Yes (5,4--6,10), false, true, + Paren + (Tuple + (false, + [Typed + (Named + (SynIdent (x, None), false, None, + (5,10--5,11)), + LongIdent + (SynLongIdent ([int], [], [None])), + (5,10--5,16)); + Typed + (Named + (SynIdent (y, None), false, None, + (5,18--5,19)), + LongIdent + (SynLongIdent ([int], [], [None])), + (5,18--5,24))], [(5,16--5,17)], + (5,10--5,24)), (5,9--5,25)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (5,36--5,38)), (5,28--5,38)), + (5,4--5,38), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,26--5,27) + InKeyword = None })], + YieldOrReturn + ((false, true), Const (Unit, (6,11--6,13)), (6,4--6,13), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,13), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,27--4,28) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 17.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 17.fs new file mode 100644 index 00000000000..3918e729716 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 17.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (x, y): int * int = asyncInt() + and! (x, y): int * int = asyncInt() + return () +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 17.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 17.fs.bsl new file mode 100644 index 00000000000..f801b2d1319 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 17.fs.bsl @@ -0,0 +1,75 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 17.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,39), false, true, + Typed + (Paren + (Tuple + (false, + [Named + (SynIdent (x, None), false, None, + (4,10--4,11)); + Named + (SynIdent (y, None), false, None, + (4,13--4,14))], [(4,11--4,12)], (4,10--4,14)), + (4,9--4,15)), + Tuple + (false, + [Type + (LongIdent (SynLongIdent ([int], [], [None]))); + Star (4,21--4,22); + Type + (LongIdent (SynLongIdent ([int], [], [None])))], + (4,17--4,26)), (4,9--4,26)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,37--4,39)), (4,29--4,39)), + [SynExprAndBang + (Yes (5,4--5,39), false, true, + Typed + (Paren + (Tuple + (false, + [Named + (SynIdent (x, None), false, None, + (5,10--5,11)); + Named + (SynIdent (y, None), false, None, + (5,13--5,14))], [(5,11--5,12)], + (5,10--5,14)), (5,9--5,15)), + Tuple + (false, + [Type + (LongIdent + (SynLongIdent ([int], [], [None]))); + Star (5,21--5,22); + Type + (LongIdent + (SynLongIdent ([int], [], [None])))], + (5,17--5,26)), (5,9--5,26)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (5,37--5,39)), (5,29--5,39)), + (5,4--5,39), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,27--5,28) + InKeyword = None })], + YieldOrReturn + ((false, true), Const (Unit, (6,11--6,13)), (6,4--6,13), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,13), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,27--4,28) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) From 86fedfd72032f0136941fe540f972834911c7b87 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Wed, 11 Jun 2025 18:13:39 +0100 Subject: [PATCH 12/22] Update LanguageFeature and release notes --- .../.FSharp.Compiler.Service/10.0.100.md | 2 +- docs/release-notes/.Language/preview.md | 2 +- .../Expressions/CheckComputationExpressions.fs | 2 +- src/Compiler/Facilities/LanguageFeatures.fs | 6 +++--- src/Compiler/Facilities/LanguageFeatures.fsi | 2 +- src/Compiler/pars.fsy | 16 ++++++++-------- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md index b4df947561a..d46e19ed005 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md @@ -7,7 +7,7 @@ * Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543)) * Fix parsing errors using anonymous records and code quotations ([PR #18603](https://github.com/dotnet/fsharp/pull/18603)) * Fixed: Allow `return`, `return!`, `yield`, `yield!` type annotations without parentheses ([PR #18533](https://github.com/dotnet/fsharp/pull/18533)) -* Allow `let!` and `use!` type annotations without requiring parentheses ([PR #18508](https://github.com/dotnet/fsharp/pull/18508)) +* Allow `let!`, `use!`, `and!` type annotations without requiring parentheses (([PR #18508](https://github.com/dotnet/fsharp/pull/18508) and [PR #18682](https://github.com/dotnet/fsharp/pull/18682))) * Fix find all references for F# exceptions ([PR #18565](https://github.com/dotnet/fsharp/pull/18565)) * Shorthand lambda: fix completion for chained calls and analysis for unfinished expression ([PR #18560](https://github.com/dotnet/fsharp/pull/18560)) * Completion: fix previous namespace considered opened [PR #18609](https://github.com/dotnet/fsharp/pull/18609) diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index 687402597c5..0ba66727cd1 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -8,7 +8,7 @@ * Warn when `unit` is passed to an `obj`-typed argument ([PR #18330](https://github.com/dotnet/fsharp/pull/18330)) * Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543)) * Scoped Nowarn: added the #warnon compiler directive ([Language suggestion #278](https://github.com/fsharp/fslang-suggestions/issues/278), [RFC FS-1146 PR](https://github.com/fsharp/fslang-design/pull/782), [PR #18049](https://github.com/dotnet/fsharp/pull/18049)) -* Allow `let!` and `use!` type annotations without requiring parentheses. ([PR #18508](https://github.com/dotnet/fsharp/pull/18508)) +* Allow `let!`, `use!`, `and!` type annotations without requiring parentheses (([PR #18508](https://github.com/dotnet/fsharp/pull/18508) and [PR #18682](https://github.com/dotnet/fsharp/pull/18682))) ### Fixed diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs index 0d2404c5b1a..00b992a6f92 100644 --- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs @@ -1794,7 +1794,7 @@ let rec TryTranslateComputationExpression ceenv.cenv.g.langVersion.SupportsFeature LanguageFeature.UseBangBindingValueDiscard let supportsTypedLetOrUseBang = - ceenv.cenv.g.langVersion.SupportsFeature LanguageFeature.AllowTypedLetOrUseBang + ceenv.cenv.g.langVersion.SupportsFeature LanguageFeature.AllowTypedLetUseAndBang // use! x = ... // use! (x) = ... diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 246ec741d67..33b01d48ce6 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -102,7 +102,7 @@ type LanguageFeature = | UseBangBindingValueDiscard | BetterAnonymousRecordParsing | ScopedNowarn - | AllowTypedLetOrUseBang + | AllowTypedLetUseAndBang /// LanguageVersion management type LanguageVersion(versionText) = @@ -236,7 +236,7 @@ type LanguageVersion(versionText) = LanguageFeature.UseBangBindingValueDiscard, previewVersion LanguageFeature.BetterAnonymousRecordParsing, previewVersion LanguageFeature.ScopedNowarn, previewVersion - LanguageFeature.AllowTypedLetOrUseBang, previewVersion + LanguageFeature.AllowTypedLetUseAndBang, previewVersion ] static let defaultLanguageVersion = LanguageVersion("default") @@ -402,7 +402,7 @@ type LanguageVersion(versionText) = | LanguageFeature.UseBangBindingValueDiscard -> FSComp.SR.featureUseBangBindingValueDiscard () | LanguageFeature.BetterAnonymousRecordParsing -> FSComp.SR.featureBetterAnonymousRecordParsing () | LanguageFeature.ScopedNowarn -> FSComp.SR.featureScopedNowarn () - | LanguageFeature.AllowTypedLetOrUseBang -> FSComp.SR.featureAllowLetOrUseBangTypeAnnotationWithoutParens () + | LanguageFeature.AllowTypedLetUseAndBang -> FSComp.SR.featureAllowLetOrUseBangTypeAnnotationWithoutParens () /// Get a version string associated with the given feature. static member GetFeatureVersionString feature = diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index c9e70ce1567..f034979a6d3 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -93,7 +93,7 @@ type LanguageFeature = | UseBangBindingValueDiscard | BetterAnonymousRecordParsing | ScopedNowarn - | AllowTypedLetOrUseBang + | AllowTypedLetUseAndBang /// LanguageVersion management type LanguageVersion = diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 33691a95c86..ba9d638d887 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4115,7 +4115,7 @@ moreBinders: match $3 with | None -> $2 | Some (_, SynReturnInfo((ty, _), _)) -> - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang ty.Range + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang ty.Range SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) let mEquals = rhs parseState 4 let m = unionRanges (rhs parseState 1) $5.Range @@ -4141,7 +4141,7 @@ moreBinders: match $3 with | None -> $2 | Some (_, SynReturnInfo((ty, _), _)) -> - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang ty.Range + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang ty.Range SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) let mEquals = rhs parseState 4 let m = unionRanges (rhs parseState 1) $5.Range @@ -4461,7 +4461,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 + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang typedExpr.Range SynExpr.YieldOrReturn(($1, not $1), typedExpr, (unionRanges (rhs parseState 1) $4.Range), trivia) } | YIELD declExpr opt_topReturnTypeWithTypeConstraints @@ -4471,7 +4471,7 @@ declExpr: | None -> $2 | Some(_, SynReturnInfo((ty, _), m)) -> let m = unionRanges $2.Range m - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang m + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang m SynExpr.Typed($2, ty, m) SynExpr.YieldOrReturn(($1, not $1), expr, (unionRanges (rhs parseState 1) expr.Range), trivia) } @@ -4488,7 +4488,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 + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang typedExpr.Range SynExpr.YieldOrReturnFrom(($1, not $1), typedExpr, (unionRanges (rhs parseState 1) $2.Range), trivia) } | YIELD_BANG declExpr opt_topReturnTypeWithTypeConstraints @@ -4498,7 +4498,7 @@ declExpr: | None -> $2 | Some(_, SynReturnInfo((ty, _), m)) -> let m = unionRanges $2.Range m - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang m + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang m SynExpr.Typed($2, ty, m) SynExpr.YieldOrReturnFrom(($1, not $1), expr, (unionRanges (rhs parseState 1) $2.Range), trivia) } @@ -4534,7 +4534,7 @@ declExpr: | None -> $2 | Some (_, SynReturnInfo((ty, _), _)) -> SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang pat.Range + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang pat.Range let mEquals = rhs parseState 4 let m = unionRanges (rhs parseState 1) $9.Range let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } @@ -4551,7 +4551,7 @@ declExpr: | None -> $2 | Some (_, SynReturnInfo((ty, _), _)) -> SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetOrUseBang pat.Range + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang pat.Range let mEquals = rhs parseState 4 let m = unionRanges (rhs parseState 1) $9.Range let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } From aee26ec241af7df4efe398322ad6815275aaadbe Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Wed, 11 Jun 2025 19:16:49 +0100 Subject: [PATCH 13/22] update baselines --- .../SynType/Typed LetBang 13.fs.bsl | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 13.fs.bsl diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 13.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 13.fs.bsl new file mode 100644 index 00000000000..54d1f846530 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 13.fs.bsl @@ -0,0 +1,21 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 13.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (Tuple + (false, + [App + (NonAtomic, false, Ident async, + Record (None, None, [], (2,6--2,7)), (2,0--2,7)); Ident y], + [(3,15--3,16)], (2,0--3,18)), (2,0--3,18))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--3,18), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(3,15)-(3,16) parse error Unexpected symbol ',' in expression. Expected '=' or other token. +(2,6)-(2,7) parse error Unmatched '{' +(4,4)-(4,10) parse error Incomplete structured construct at or before this point in implementation file From 47125695a2c87a5b62f85eb8326291770fe259e1 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Wed, 18 Jun 2025 15:20:55 +0200 Subject: [PATCH 14/22] more tests --- .../Language/ComputationExpressionTests.fs | 386 ++++++++++++++++++ 1 file changed, 386 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index 04ef2492fc3..da58048ee3a 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -1639,4 +1639,390 @@ if result3 <> 3 then failwithf $"Expected 3, but got {result3}" |> withLangVersionPreview |> asExe |> compileAndRun + |> shouldSucceed + + [] + let ``Version 9.0: and! with record patterns and type annotations requires parentheses`` () = + FSharp """ +module Test + +type Person = { Name: string; Age: int } +type User = { Id: int; Username: string } + +type ParallelBuilder() = + member _.Return(x) = async { return x } + member _.ReturnFrom(computation: Async<'T>) = computation + member _.Bind(computation: Async<'T>, binder: 'T -> Async<'U>) = + async { + let! x = computation + return! binder x + } + member _.Bind2(comp1: Async<'T1>, comp2: Async<'T2>, binder: 'T1 * 'T2 -> Async<'U>) = + async { + let! task1 = Async.StartChild comp1 + let! task2 = Async.StartChild comp2 + let! result1 = task1 + let! result2 = task2 + return! binder (result1, result2) + } + + member _.Zero() = async.Zero() + member _.Combine(comp1, comp2) = async.Combine(comp1, comp2) + member _.Delay(f) = async.Delay(f) + +let parallelCE = ParallelBuilder() + +let asyncPerson() = async { return { Name = "John"; Age = 30 } } +let asyncUser() = async { return { Id = 1; Username = "john_doe" } } + +let testParallel1() = + parallelCE { + let! ({ Name = name; Age = age }: Person) = asyncPerson() + and! ({ Id = id; Username = username }: User) = asyncUser() + return (name, age, id, username) + } + +let testParallel2() = + parallelCE { + let! { Name = name; Age = age }: Person = asyncPerson() + and! { Id = id; Username = username }: User = asyncUser() + return (name, age, id, username) + } + """ + |> withLangVersion90 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 43, Col 14, Line 43, Col 48, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 42, Col 14, Line 42, Col 46, "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: and! with record patterns and type annotations works without parentheses`` () = + FSharp """ +module Test + +type Person = { Name: string; Age: int } +type User = { Id: int; Username: string } + +type ParallelBuilder() = + member _.Return(x) = async { return x } + member _.ReturnFrom(computation: Async<'T>) = computation + member _.Bind(computation: Async<'T>, binder: 'T -> Async<'U>) = + async { + let! x = computation + return! binder x + } + member _.Bind2(comp1: Async<'T1>, comp2: Async<'T2>, binder: 'T1 * 'T2 -> Async<'U>) = + async { + let! task1 = Async.StartChild comp1 + let! task2 = Async.StartChild comp2 + let! result1 = task1 + let! result2 = task2 + return! binder (result1, result2) + } + + member _.Zero() = async.Zero() + member _.Combine(comp1, comp2) = async.Combine(comp1, comp2) + member _.Delay(f) = async.Delay(f) + +let parallelCE = ParallelBuilder() + +let asyncPerson() = async { return { Name = "John"; Age = 30 } } +let asyncUser() = async { return { Id = 1; Username = "john_doe" } } + +let testParallel1() = + parallelCE { + let! ({ Name = name; Age = age }: Person) = asyncPerson() + and! ({ Id = id; Username = username }: User) = asyncUser() + return (name, age, id, username) + } + +let testParallel2() = + parallelCE { + let! { Name = name; Age = age }: Person = asyncPerson() + and! { Id = id; Username = username }: User = asyncUser() + return (name, age, id, username) + } + +let result1 = testParallel1() |> Async.RunSynchronously +let result2 = testParallel2() |> Async.RunSynchronously + +if result1 <> ("John", 30, 1, "john_doe") then + failwithf $"Expected ('John', 30, 1, 'john_doe'), but got %A{result1}" +if result2 <> ("John", 30, 1, "john_doe") then + failwithf $"Expected ('John', 30, 1, 'john_doe'), but got %A{result2}" + """ + |> withLangVersionPreview + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Version 9.0: and! with union patterns and type annotations requires parentheses`` () = + FSharp """ +module Test + +type MyOption<'T> = Some of 'T | None + +type ParallelBuilder() = + member _.Return(x) = async { return x } + member _.ReturnFrom(computation: Async<'T>) = computation + member _.Bind(computation: Async<'T>, binder: 'T -> Async<'U>) = + async { + let! x = computation + return! binder x + } + member _.Bind2(comp1: Async<'T1>, comp2: Async<'T2>, binder: 'T1 * 'T2 -> Async<'U>) = + async { + let! task1 = Async.StartChild comp1 + let! task2 = Async.StartChild comp2 + let! result1 = task1 + let! result2 = task2 + return! binder (result1, result2) + } + + member _.Zero() = async.Zero() + member _.Combine(comp1, comp2) = async.Combine(comp1, comp2) + member _.Delay(f) = async.Delay(f) + +let parallelCE = ParallelBuilder() + +let asyncOption1() = async { return MyOption.Some 42 } +let asyncOption2() = async { return MyOption.Some "hello" } + +let testParallel() = + parallelCE { + let! (Some value1): MyOption = asyncOption1() + and! (Some value2): MyOption = asyncOption2() + return (value1, value2) + } + +let testParallel2() = + parallelCE { + let! Some value1: MyOption = asyncOption1() + and! Some value2: MyOption = asyncOption2() + return (value1, value2) + } + """ + |> withLangVersion90 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 41, Col 14, Line 41, Col 46, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 40, Col 14, Line 40, Col 41, "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: and! with union patterns and type annotations works without parentheses`` () = + FSharp """ +module Test + +type MyOption<'T> = Some of 'T | None + +type ParallelBuilder() = + member _.Return(x) = async { return x } + member _.ReturnFrom(computation: Async<'T>) = computation + member _.Bind(computation: Async<'T>, binder: 'T -> Async<'U>) = + async { + let! x = computation + return! binder x + } + member _.Bind2(comp1: Async<'T1>, comp2: Async<'T2>, binder: 'T1 * 'T2 -> Async<'U>) = + async { + let! task1 = Async.StartChild comp1 + let! task2 = Async.StartChild comp2 + let! result1 = task1 + let! result2 = task2 + return! binder (result1, result2) + } + + member _.Zero() = async.Zero() + member _.Combine(comp1, comp2) = async.Combine(comp1, comp2) + member _.Delay(f) = async.Delay(f) + +let parallelCE = ParallelBuilder() + +let asyncOption1() = async { return MyOption.Some 42 } +let asyncOption2() = async { return MyOption.Some "hello" } + +let testParallel1() = + parallelCE { + let! (Some value1): MyOption = asyncOption1() + and! (Some value2): MyOption = asyncOption2() + return (value1, value2) + } + +let testParallel2() = + parallelCE { + let! Some value1: MyOption = asyncOption1() + and! Some value2: MyOption = asyncOption2() + return (value1, value2) + } + +let result1 = testParallel1() |> Async.RunSynchronously +let result2 = testParallel2() |> Async.RunSynchronously + +if result1 <> (42, "hello") then + failwithf $"Expected (42, 'hello'), but got %A{result1}" +if result2 <> (42, "hello") then + failwithf $"Expected (42, 'hello'), but got %A{result2}" + """ + |> withLangVersionPreview + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Preview: and! with mixed patterns and type annotations works`` () = + FSharp """ +module Test + +type Person = { Name: string; Age: int } + +type ParallelBuilder() = + member _.Return(x) = async { return x } + member _.ReturnFrom(computation: Async<'T>) = computation + member _.Bind(computation: Async<'T>, binder: 'T -> Async<'U>) = + async { + let! x = computation + return! binder x + } + member _.Bind2(comp1: Async<'T1>, comp2: Async<'T2>, binder: 'T1 * 'T2 -> Async<'U>) = + async { + let! task1 = Async.StartChild comp1 + let! task2 = Async.StartChild comp2 + let! result1 = task1 + let! result2 = task2 + return! binder (result1, result2) + } + + member _.Zero() = async.Zero() + member _.Combine(comp1, comp2) = async.Combine(comp1, comp2) + member _.Delay(f) = async.Delay(f) + +let parallelCE = ParallelBuilder() + +let asyncInt() = async { return 42 } +let asyncPerson() = async { return { Name = "Alice"; Age = 25 } } + +// Test mixing different pattern types with type annotations +let testMixed() = + parallelCE { + let! x: int = asyncInt() + and! { Name = name; Age = age }: Person = asyncPerson() + return (x, name, age) + } + +// Test with parentheses on one and not the other +let testMixed2() = + parallelCE { + let! (y: int) = asyncInt() + and! { Name = name2; Age = age2 }: Person = asyncPerson() + return (y, name2, age2) + } + +let result1 = testMixed() |> Async.RunSynchronously +let result2 = testMixed2() |> Async.RunSynchronously + +if result1 <> (42, "Alice", 25) then + failwithf $"Expected (42, 'Alice', 25), but got %A{result1}" +if result2 <> (42, "Alice", 25) then + failwithf $"Expected (42, 'Alice', 25), but got %A{result2}" + """ + |> withLangVersionPreview + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Preview: multiple and! with type annotations works`` () = + FSharp """ +module Test + +type Builder() = + member _.Return(x) = async { return x } + member _.Bind(computation: Async<'T>, binder: 'T -> Async<'U>) = + async { + let! x = computation + return! binder x + } + member _.Bind3(comp1: Async<'T1>, comp2: Async<'T2>, comp3: Async<'T3>, binder: 'T1 * 'T2 * 'T3 -> Async<'U>) = + async { + let! task1 = Async.StartChild comp1 + let! task2 = Async.StartChild comp2 + let! task3 = Async.StartChild comp3 + let! result1 = task1 + let! result2 = task2 + let! result3 = task3 + return! binder (result1, result2, result3) + } + + member _.Zero() = async.Zero() + member _.Combine(comp1, comp2) = async.Combine(comp1, comp2) + member _.Delay(f) = async.Delay(f) + +let builder = Builder() + +let asyncInt() = async { return 42 } +let asyncString() = async { return "test" } +let asyncFloat() = async { return 3.14 } + +// Test multiple and! with type annotations +let testMultiple() = + builder { + let! x: int = asyncInt() + and! y: string = asyncString() + and! z: float = asyncFloat() + return (x, y, z) + } + +let result = testMultiple() |> Async.RunSynchronously + +if result <> (42, "test", 3.14) then + failwithf $"Expected (42, 'test', 3.14), but got %A{result}" + """ + |> withLangVersionPreview + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Preview: and! with generic type annotations works`` () = + FSharp """ +module Test + +type Result<'T, 'E> = Ok of 'T | Error of 'E + +type ResultBuilder() = + member _.Return(x) = Ok x + member _.Bind(m: Result<'T, 'E>, f: 'T -> Result<'U, 'E>) = + match m with + | Ok x -> f x + | Error e -> Error e + member _.Bind2(m1: Result<'T1, 'E>, m2: Result<'T2, 'E>, f: 'T1 * 'T2 -> Result<'U, 'E>) = + match m1, m2 with + | Ok x1, Ok x2 -> f (x1, x2) + | Error e, _ -> Error e + | _, Error e -> Error e + +let result = ResultBuilder() + +let getValue1() = Ok 42 +let getValue2() = Ok "success" + +let test() = + result { + let! x: int = getValue1() + and! y: string = getValue2() + return (x, y) + } + +match test() with +| Ok (42, "success") -> printfn "Test passed" +| _ -> failwith "Test failed" + """ + |> withLangVersionPreview + |> asExe + |> compileAndRun |> shouldSucceed \ No newline at end of file From 3a346deadad8d2c3de8eac55ae96c1e2175e197a Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 18 Jun 2025 20:51:56 +0200 Subject: [PATCH 15/22] update tests --- .../Language/ComputationExpressionTests.fs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index da58048ee3a..b409b3653d0 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -1693,8 +1693,8 @@ let testParallel2() = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 43, Col 14, Line 43, Col 48, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); - (Error 3350, Line 42, Col 14, Line 42, Col 46, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 43, Col 48, Line 43, Col 52, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 42, Col 14, Line 42, Col 48, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") ] [] @@ -1809,8 +1809,10 @@ let testParallel2() = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 41, Col 14, Line 41, Col 46, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); - (Error 3350, Line 40, Col 14, Line 40, Col 41, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 35, Col 29, Line 35, Col 45, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 34, Col 14, Line 34, 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.") + (Error 3350, Line 42, Col 27, Line 42, 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.") + (Error 3350, Line 41, Col 14, Line 41, Col 40, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") ] [] @@ -1870,6 +1872,7 @@ if result2 <> (42, "hello") then """ |> withLangVersionPreview |> asExe + |> ignoreWarnings |> compileAndRun |> shouldSucceed From c03a338e4cfe410c98062105b1e2dd2fed5d5359 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Thu, 19 Jun 2025 15:52:19 +0200 Subject: [PATCH 16/22] Unifying let, let! and! parser rules --- src/Compiler/pars.fsy | 220 ++++++++++-------- .../UseBindings/UseBangBindings.fs | 6 +- .../Language/ComputationExpressionTests.fs | 14 +- ...atStartsAtAndAndEndsAfterExpression.fs.bsl | 4 +- ...geStartsAtAndAndEndsAfterExpression.fs.bsl | 2 +- ...BangContainsTheRangeOfTheEqualsSign.fs.bsl | 2 +- .../SynType/Typed LetBang AndBang 02.fs.bsl | 2 +- .../SynType/Typed LetBang AndBang 03.fs.bsl | 2 +- .../SynType/Typed LetBang AndBang 06.fs.bsl | 2 +- .../SynType/Typed LetBang AndBang 07.fs.bsl | 2 +- .../SynType/Typed LetBang AndBang 12.fs.bsl | 2 +- .../SynType/Typed LetBang AndBang 13.fs.bsl | 2 +- .../SynType/Typed LetBang AndBang 15.fs.bsl | 79 +++---- .../SynType/Typed LetBang AndBang 16.fs.bsl | 2 +- 14 files changed, 183 insertions(+), 158 deletions(-) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index ba9d638d887..6c373bf45da 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3520,6 +3520,57 @@ bindingPattern: | headBindingPattern { $1, $1.Range } +/* Common pattern for bindings that may include type annotations + This rule unifies the pattern parsing for both regular 'let' bindings and + computation expression bindings (let!, use!, and!). + + Returns: (pattern, pattern_range, optional_type) + - pattern: The parsed pattern (may be typed if annotation present) + - pattern_range: The full range including any type annotation + - optional_type: The type if annotation was present, None otherwise */ +bindingPatternWithOptType: + | headBindingPattern + { // Simple pattern without type annotation + $1, $1.Range, None } + + | headBindingPattern COLON topTypeWithTypeConstraints + { // Pattern with type annotation (e.g., x: int) + let ty, arity = $3 + let mWhole = unionRanges $1.Range ty.Range + // Create a typed pattern node + let typedPat = SynPat.Typed($1, ty, mWhole) + typedPat, mWhole, Some ty } + + | headBindingPattern COLON error + { // Error recovery: incomplete type annotation (e.g., "let x:" with no type) + let mColon = rhs parseState 2 + let mWhole = unionRanges $1.Range mColon + // Create a typed pattern with an error type for recovery + let errorType = SynType.FromParseError(mColon.EndRange) + let typedPat = SynPat.Typed($1, errorType, mWhole) + typedPat, mWhole, Some errorType } + +/* Common rule for computation expression binding patterns + Handles the pattern part of let!, use!, and! bindings with consistent + type annotation support and language feature checking. + + Returns: (pattern, pattern_range, isInline, isMutable, optional_type) */ +ceBindingCore: + | opt_inline opt_mutable bindingPatternWithOptType + { let pat, mPat, tyOpt = $3 + let isInline = Option.isSome $1 + let isMutable = Option.isSome $2 + + // For CE bindings, check language feature if type annotation is present + // This ensures that typed let!/use!/and! bindings are only allowed when + // the AllowTypedLetUseAndBang feature is enabled + match tyOpt with + | Some ty -> + parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang ty.Range + | None -> () + + pat, mPat, isInline, isMutable, tyOpt } + opt_simplePatterns: | simplePatterns { Some $1 } @@ -4099,54 +4150,45 @@ recover: { debugPrint("recovering via EOF"); false } moreBinders: - | AND_BANG headBindingPattern EQUALS typedSequentialExprBlock IN moreBinders %prec expr_let - { let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) + /* Refactored and! bindings to use unified ceBindingCore + This ensures consistent handling of patterns and type annotations + across all computation expression bindings */ + | AND_BANG ceBindingCore EQUALS typedSequentialExprBlock IN moreBinders %prec expr_let + { // Handle and! bindings with unified pattern parsing + let pat, mPat, isInline, isMutable, tyOpt = $2 + + // and! bindings don't support inline or mutable modifiers + if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + if isMutable then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + let mEquals = rhs parseState 3 let m = unionRanges (rhs parseState 1) $4.Range + // Debug point should span the entire binding: from AND_BANG through the expression + let spBind = DebugPointAtBinding.Yes(m) let mIn = rhs parseState 5 let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = Some mIn } - SynExprAndBang(spBind, $1, true, $2, $4, m, trivia) :: $6 } - - | AND_BANG headBindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock IN moreBinders %prec expr_let - { // Handle type annotations on patterns in and! bindings - // Example: and! y: string = asyncString() - let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 6) - let pat = - match $3 with - | None -> $2 - | Some (_, SynReturnInfo((ty, _), _)) -> - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang ty.Range - SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) - let mEquals = rhs parseState 4 - let m = unionRanges (rhs parseState 1) $5.Range - let mIn = rhs parseState 6 - let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = Some mIn } - SynExprAndBang(spBind, false, true, pat, $5, m, trivia) :: $7 } - - | OAND_BANG headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let - { let report, mIn, _ = $5 + + // Note: For and!, we always use isRecursive=false and isUse=true + SynExprAndBang(spBind, false, true, pat, $4, m, trivia) :: $6 } + + | OAND_BANG ceBindingCore EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let + { // Offside-sensitive version of and! binding + let pat, mPat, isInline, isMutable, tyOpt = $2 + + // and! bindings don't support inline or mutable modifiers + if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + if isMutable then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + + let report, mIn, _ = $5 report "and!" (rhs parseState 1) // report unterminated error - let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) let mEquals = rhs parseState 3 let m = unionRanges (rhs parseState 1) $4.Range + // Debug point should span the entire binding: from OAND_BANG through the expression + let spBind = DebugPointAtBinding.Yes(m) let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = mIn } - SynExprAndBang(spBind, $1, true, $2, $4, m, trivia) :: $7 } - - | OAND_BANG headBindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let - { // Handle type annotations on patterns in and! bindings (offside-sensitive version) - let report, mIn, _ = $6 - report "and!" (rhs parseState 1) // report unterminated error - let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $5.Range) - let pat = - match $3 with - | None -> $2 - | Some (_, SynReturnInfo((ty, _), _)) -> - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang ty.Range - SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) - let mEquals = rhs parseState 4 - let m = unionRanges (rhs parseState 1) $5.Range - let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = mIn } - SynExprAndBang(spBind, false, true, pat, $5, m, trivia) :: $8 } + + // Note: For and!, we always use isRecursive=false and isUse=true + SynExprAndBang(spBind, false, true, pat, $4, m, trivia) :: $7 } | %prec prec_no_more_attr_bindings { [] } @@ -4502,69 +4544,65 @@ declExpr: 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 - { (* This rule handles the 'use!' and 'let!' binding expressions in computation expressions *) - (* The BINDER token represents keywords like 'use!' or 'let!' *) - (* headBindingPattern represents patterns in the binding: - - Underscore ('_') patterns are preserved as SynPat.Wild - - Named patterns ('__') are represented as SynPat.Named - - Identifiers (like 'value') are represented as SynPat.LongIdent *) - let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) + /* Refactored let! and use! bindings to use unified ceBindingCore + This ensures consistent handling across all computation expression bindings + while maintaining backward compatibility */ + | BINDER ceBindingCore EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let + { // Handle let! and use! bindings with unified pattern parsing + let pat, mPat, isInline, isMutable, tyOpt = $2 + + // let! and use! bindings don't support inline or mutable modifiers + if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + if isMutable then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + let mEquals = rhs parseState 3 let m = unionRanges (rhs parseState 1) $8.Range + // Debug point should span from BINDER through the expression (but not the continuation) + let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } - SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m, trivia) } - - | OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let - { let report, mIn, _ = $5 + + // $1 contains the actual keyword ("let!" or "use!") + let isUse = ($1 = "use") + SynExpr.LetOrUseBang(spBind, isUse, true, pat, $4, $7, $8, m, trivia) } + + | OBINDER ceBindingCore EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let + { // Offside-sensitive version of let!/use! binding + let pat, mPat, isInline, isMutable, tyOpt = $2 + + // let! and use! bindings don't support inline or mutable modifiers + if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + if isMutable then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + + let report, mIn, _ = $5 report (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error - let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let mEquals = rhs parseState 3 let m = unionRanges (rhs parseState 1) $8.Range + // Debug point should span from OBINDER through the expression (but not the continuation) + let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } - SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m, trivia) } - - | BINDER headBindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let - { // Handle type annotations on patterns in let!/use! bindings - // Examples: let! x: int = async { return 1 } - // use! _: IDisposable = async { return new MemoryStream() } - let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 7) - let pat = - match $3 with - | None -> $2 - | Some (_, SynReturnInfo((ty, _), _)) -> - SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang pat.Range - let mEquals = rhs parseState 4 - let m = unionRanges (rhs parseState 1) $9.Range - let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } - SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, pat, $5, $8, $9, m, trivia) } - - | OBINDER headBindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let - { // Handle type annotations on patterns in let!/use! bindings (offside-sensitive version) - // This rule maintains consistent handling of binding constructs across different syntactic contexts - let report, mIn, _ = $6 - report (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error - let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $5.Range) - let pat = - match $3 with - | None -> $2 - | Some (_, SynReturnInfo((ty, _), _)) -> - SynPat.Typed($2, ty, unionRanges $2.Range ty.Range) - parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang pat.Range - let mEquals = rhs parseState 4 - let m = unionRanges (rhs parseState 1) $9.Range - let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } - SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, pat, $5, $8, $9, m, trivia) } - - | OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let - { // error recovery that allows intellisense when writing incomplete computation expressions + + let isUse = ($1 = "use") + SynExpr.LetOrUseBang(spBind, isUse, true, pat, $4, $7, $8, m, trivia) } + + | OBINDER ceBindingCore EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let + { // Error recovery for incomplete let!/use! bindings + // Allows intellisense to work when writing incomplete computation expressions + let pat, mPat, isInline, isMutable, tyOpt = $2 + + // Error checking for invalid modifiers + if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + if isMutable then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + + // Debug point should span from OBINDER through the expression let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let mEquals = rhs parseState 3 let mAll = unionRanges (rhs parseState 1) (rhs parseState 7) let m = $4.Range.EndRange // zero-width range let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } - SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, [], SynExpr.ImplicitZero m, mAll, trivia) } + + let isUse = ($1 = "use") + // Use ImplicitZero as the continuation expression for error recovery + SynExpr.LetOrUseBang(spBind, isUse, true, pat, $4, [], SynExpr.ImplicitZero m, mAll, trivia) } | DO_BANG typedSequentialExpr IN opt_OBLOCKSEP typedSequentialExprBlock %prec expr_let { let spBind = DebugPointAtBinding.NoneAtDo diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs index 37c1447e89e..53cb84ccf21 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs @@ -59,9 +59,9 @@ module UseBangBindingsVersion9 = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 43, Col 14, Line 43, Col 28, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") - (Error 3350, Line 41, Col 14, Line 41, Col 28, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") - (Error 3350, Line 40, Col 14, Line 40, Col 29, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 40, Col 18, Line 40, Col 29, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 41, Col 17, Line 41, Col 28, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 43, Col 17, Line 43, Col 28, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") ] module UseBangBindingsPreview = diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index b409b3653d0..c23d2bd6d71 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -1576,8 +1576,8 @@ let testParallel3() = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 44, Col 17, Line 44, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); - (Error 3350, Line 43, Col 14, Line 43, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 43, Col 17, Line 43, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 44, Col 17, Line 44, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") ] [] @@ -1693,8 +1693,8 @@ let testParallel2() = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 43, Col 48, Line 43, Col 52, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); - (Error 3350, Line 42, Col 14, Line 42, Col 48, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 42, Col 42, Line 42, Col 48, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 43, Col 48, Line 43, Col 52, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") ] [] @@ -1809,10 +1809,10 @@ let testParallel2() = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 35, Col 29, Line 35, Col 45, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") - (Error 3350, Line 34, Col 14, Line 34, 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.") + (Error 3350, Line 34, Col 29, Line 34, 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."); + (Error 3350, Line 35, Col 29, Line 35, Col 45, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 41, Col 27, Line 41, Col 40, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); (Error 3350, Line 42, Col 27, Line 42, 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.") - (Error 3350, Line 41, Col 14, Line 41, Col 40, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") ] [] diff --git a/tests/service/data/SyntaxTree/ComputationExpression/MultipleSynExprAndBangHaveRangeThatStartsAtAndAndEndsAfterExpression.fs.bsl b/tests/service/data/SyntaxTree/ComputationExpression/MultipleSynExprAndBangHaveRangeThatStartsAtAndAndEndsAfterExpression.fs.bsl index 77bbe3164c6..a9f281321fa 100644 --- a/tests/service/data/SyntaxTree/ComputationExpression/MultipleSynExprAndBangHaveRangeThatStartsAtAndAndEndsAfterExpression.fs.bsl +++ b/tests/service/data/SyntaxTree/ComputationExpression/MultipleSynExprAndBangHaveRangeThatStartsAtAndAndEndsAfterExpression.fs.bsl @@ -19,7 +19,7 @@ ImplFile (NonAtomic, false, Ident getBar, Const (Unit, (3,22--3,24)), (3,15--3,24)), [SynExprAndBang - (Yes (4,4--4,27), false, true, + (Yes (4,4--4,24), false, true, Named (SynIdent (foo, None), false, None, (4,9--4,12)), App @@ -29,7 +29,7 @@ ImplFile EqualsRange = (4,13--4,14) InKeyword = Some (4,25--4,27) }); SynExprAndBang - (Yes (5,4--6,10), false, true, + (Yes (5,4--5,24), false, true, Named (SynIdent (meh, None), false, None, (5,9--5,12)), App diff --git a/tests/service/data/SyntaxTree/ComputationExpression/SynExprAndBangRangeStartsAtAndAndEndsAfterExpression.fs.bsl b/tests/service/data/SyntaxTree/ComputationExpression/SynExprAndBangRangeStartsAtAndAndEndsAfterExpression.fs.bsl index 610ab87132f..031ace760eb 100644 --- a/tests/service/data/SyntaxTree/ComputationExpression/SynExprAndBangRangeStartsAtAndAndEndsAfterExpression.fs.bsl +++ b/tests/service/data/SyntaxTree/ComputationExpression/SynExprAndBangRangeStartsAtAndAndEndsAfterExpression.fs.bsl @@ -19,7 +19,7 @@ ImplFile (NonAtomic, false, Ident getBar, Const (Unit, (3,22--3,24)), (3,15--3,24)), [SynExprAndBang - (Yes (5,4--7,10), false, true, + (Yes (5,4--5,24), false, true, Named (SynIdent (foo, None), false, None, (5,9--5,12)), App diff --git a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseBangContainsTheRangeOfTheEqualsSign.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseBangContainsTheRangeOfTheEqualsSign.fs.bsl index c5a6b577bc1..19bef59c8a3 100644 --- a/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseBangContainsTheRangeOfTheEqualsSign.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/SynExprLetOrUseBangContainsTheRangeOfTheEqualsSign.fs.bsl @@ -16,7 +16,7 @@ ImplFile Named (SynIdent (x, None), false, None, (3,9--3,10)), Ident y, [SynExprAndBang - (Yes (4,4--5,10), false, true, + (Yes (4,4--4,28), false, true, Named (SynIdent (z, None), false, None, (4,9--4,10)), App (NonAtomic, false, Ident someFunction, diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs.bsl index c6ad9a45417..0f5f06df777 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 02.fs.bsl @@ -27,7 +27,7 @@ ImplFile { YieldOrReturnKeyword = (4,30--4,36) }), (4,28--4,40)), (4,22--4,40)), [SynExprAndBang - (Yes (5,4--6,10), false, true, + (Yes (5,4--5,41), false, true, Paren (Typed (Named diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs.bsl index 77d69da0a0b..9d127609634 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 03.fs.bsl @@ -28,7 +28,7 @@ ImplFile (Atomic, false, Ident asyncPerson, Const (Unit, (4,59--4,61)), (4,48--4,61)), [SynExprAndBang - (Yes (5,4--6,10), false, true, + (Yes (5,4--5,42), false, true, Paren (Typed (Record diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl index 564967a7a33..e46cfc2ef7c 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 06.fs.bsl @@ -23,7 +23,7 @@ ImplFile (Atomic, false, Ident asyncOption, Const (Unit, (4,36--4,38)), (4,25--4,38)), [SynExprAndBang - (Yes (5,4--6,10), false, true, + (Yes (5,4--5,39), false, true, Paren (LongIdent (SynLongIdent ([Union], [], [None]), None, None, diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl index 8fab57b3ca4..6bc6a07abec 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 07.fs.bsl @@ -21,7 +21,7 @@ ImplFile (Atomic, false, Ident asyncOption, Const (Unit, (4,34--4,36)), (4,23--4,36)), [SynExprAndBang - (Yes (5,4--6,10), false, true, + (Yes (5,4--5,37), false, true, LongIdent (SynLongIdent ([Union], [], [None]), None, None, Pats diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs.bsl index bb908917f12..ffb04e5db54 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 12.fs.bsl @@ -19,7 +19,7 @@ ImplFile (Atomic, false, Ident asyncInt, Const (Unit, (4,26--4,28)), (4,18--4,28)), [SynExprAndBang - (Yes (5,4--6,10), false, true, + (Yes (5,4--5,31), false, true, As (Named (SynIdent (a, None), false, None, (5,9--5,10)), diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs.bsl index c9f68d900fd..b79f90358d2 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 13.fs.bsl @@ -31,7 +31,7 @@ ImplFile (Atomic, false, Ident asyncArray, Const (Unit, (4,54--4,56)), (4,44--4,56)), [SynExprAndBang - (Yes (5,4--6,10), false, true, + (Yes (5,4--5,50), false, true, Paren (ListCons (Named diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs.bsl index b66ac37e92f..e60943e9933 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 15.fs.bsl @@ -9,49 +9,39 @@ ImplFile (NonAtomic, false, Ident async, ComputationExpr (false, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], [Some (OriginalNotation "=")]), - None, (5,24--5,25)), - LetOrUseBang - (Yes (4,4--4,39), false, true, - Typed - (Paren - (Tuple - (false, - [Named - (SynIdent (x, None), false, None, - (4,10--4,11)); - Named - (SynIdent (y, None), false, None, - (4,13--4,14))], [(4,11--4,12)], - (4,10--4,14)), (4,9--4,15)), - Tuple - (false, - [Type - (LongIdent - (SynLongIdent ([int], [], [None]))); - Star (4,21--4,22); - Type - (LongIdent - (SynLongIdent ([int], [], [None])))], - (4,17--4,26)), (4,9--4,26)), - App - (Atomic, false, Ident asyncInt, - Const (Unit, (4,37--4,39)), (4,29--4,39)), [], - Typed - (Ident y, - LongIdent (SynLongIdent ([int], [], [None])), - (5,17--5,23)), (4,4--5,23), - { LetOrUseBangKeyword = (4,4--4,8) - EqualsRange = Some (4,27--4,28) }), (4,4--5,25)), - ArbitraryAfterError ("declExprInfixEquals", (5,25--5,25)), - (4,4--5,25)), (3,6--7,1)), (3,0--7,1)), (3,0--7,1))], + Tuple + (false, + [LetOrUseBang + (Yes (4,4--4,39), false, true, + Typed + (Paren + (Tuple + (false, + [Named + (SynIdent (x, None), false, None, + (4,10--4,11)); + Named + (SynIdent (y, None), false, None, + (4,13--4,14))], [(4,11--4,12)], + (4,10--4,14)), (4,9--4,15)), + Tuple + (false, + [Type + (LongIdent + (SynLongIdent ([int], [], [None]))); + Star (4,21--4,22); + Type + (LongIdent + (SynLongIdent ([int], [], [None])))], + (4,17--4,26)), (4,9--4,26)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,37--4,39)), (4,29--4,39)), [], + ImplicitZero (4,39--4,39), (4,4--5,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,27--4,28) }); Ident y], + [(5,15--5,16)], (4,4--5,18)), (3,6--7,1)), (3,0--7,1)), + (3,0--7,1))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] @@ -59,6 +49,3 @@ ImplFile CodeComments = [] }, set [])) (5,15)-(5,16) parse error Unexpected symbol ',' in expression. Expected '=' or other token. -(4,4)-(4,8) parse error Incomplete value definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let!' keyword. -(5,26)-(5,34) parse error Unexpected start of structured construct in expression -(5,24)-(5,25) parse error Unexpected token '=' or incomplete expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs.bsl index c6344f68319..d9f64778935 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 16.fs.bsl @@ -34,7 +34,7 @@ ImplFile (Atomic, false, Ident asyncInt, Const (Unit, (4,37--4,39)), (4,29--4,39)), [SynExprAndBang - (Yes (5,4--6,10), false, true, + (Yes (5,4--5,38), false, true, Paren (Tuple (false, From b5a9e9f01e9b92b06db8ef9e60d3657d106a89f6 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Sat, 5 Jul 2025 12:02:16 -0500 Subject: [PATCH 17/22] Unify mkLetExpression --- src/Compiler/SyntaxTree/ParseHelpers.fs | 113 ++++++++++++++++------ src/Compiler/SyntaxTree/ParseHelpers.fsi | 14 ++- src/Compiler/pars.fsy | 116 ++++++++++++++--------- 3 files changed, 164 insertions(+), 79 deletions(-) diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index 17d2c998012..9dfa2aa9458 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -867,41 +867,21 @@ let mkClassMemberLocalBindings SynMemberDefn.LetBindings(decls, isStatic, isRec, mWhole) -let mkLocalBindings (mWhole, BindingSetPreAttrs(_, isRec, isUse, declsPreAttrs, _), mIn, body: SynExpr) = - let ignoredFreeAttrs, decls = declsPreAttrs [] None +/// Creates a SynExprAndBang node for and! bindings in computation expressions +let mkAndBang (mKeyword: range, pat: SynPat, rhs: SynExpr, mWhole: range, mEquals: range, mIn: range option) = + // Calculate debug point range: from keyword through the rhs expression + let spBind = DebugPointAtBinding.Yes(unionRanges mKeyword rhs.Range) - let mWhole = - match decls with - | SynBinding(xmlDoc = xmlDoc) :: _ -> unionRangeWithXmlDoc xmlDoc mWhole - | _ -> mWhole - - if not (isNil ignoredFreeAttrs) then - warning (Error(FSComp.SR.parsAttributesIgnored (), mWhole)) - - let mIn = - mIn - |> Option.bind (fun (mIn: range) -> - if Position.posEq mIn.Start body.Range.Start then - None - else - Some mIn) - - let mLetOrUse = - match decls with - | SynBinding(trivia = trivia) :: _ -> trivia.LeadingKeyword.Range - | _ -> range0 - - SynExpr.LetOrUse( - isRec, - isUse, - decls, - body, - mWhole, + // Create trivia + let trivia: SynExprAndBangTrivia = { - LetOrUseKeyword = mLetOrUse + AndBangKeyword = mKeyword + EqualsRange = mEquals InKeyword = mIn } - ) + + // For and!, isUse is always true, isFromSource is always true + SynExprAndBang(spBind, false, true, pat, rhs, mWhole, trivia) let mkDefnBindings (mWhole, BindingSetPreAttrs(_, isRec, isUse, declsPreAttrs, _bindingSetRange), attrs, vis, attrsm) = if isUse then @@ -1073,3 +1053,74 @@ let leadingKeywordIsAbstract = | SynLeadingKeyword.StaticAbstract _ | SynLeadingKeyword.StaticAbstractMember _ -> true | _ -> false + + +/// Unified helper for creating let/let!/use/use! expressions +/// Creates either SynExpr.LetOrUse or SynExpr.LetOrUseBang based on isBang parameter +/// Handles all four cases: 'let', 'let!', 'use', and 'use!' +let mkLetExpression + ( + isBang: bool, + mKeyword: range, + mIn: Option, + mWhole: range, + body: SynExpr, + // For regular let/use: binding information + bindingInfo: (bool * BindingSet) option, + // For let!/use!: pattern, rhs, andBangs, equals range, and isUse flag + bangInfo: (SynPat * SynExpr * SynExprAndBang list * range option * bool) option + ) = + if isBang then + match bangInfo with + | Some (pat, rhs, andBangs, mEquals, isUse) -> + // Create let! or use! expression + let spBind = DebugPointAtBinding.Yes(unionRanges mKeyword rhs.Range) + let trivia: SynExprLetOrUseBangTrivia = + { + LetOrUseBangKeyword = mKeyword + EqualsRange = mEquals + } + // isFromSource is true for user-written code + SynExpr.LetOrUseBang(spBind, isUse, true, pat, rhs, andBangs, body, mWhole, trivia) + | None -> + failwith "mkLetExpression: bangInfo required for let!/use! expressions" + else + match bindingInfo with + | Some (isRec, BindingSetPreAttrs(_, _, isUse, declsPreAttrs, _)) -> + // Create regular let or use expression + let ignoredFreeAttrs, decls = declsPreAttrs [] None + + let mWhole' = + match decls with + | SynBinding(xmlDoc = xmlDoc) :: _ -> unionRangeWithXmlDoc xmlDoc mWhole + | _ -> mWhole + + if not (isNil ignoredFreeAttrs) then + warning (Error(FSComp.SR.parsAttributesIgnored (), mWhole')) + + let mIn' = + mIn + |> Option.bind (fun (mIn: range) -> + if Position.posEq mIn.Start body.Range.Start then + None + else + Some mIn) + + let mLetOrUse = + match decls with + | SynBinding(trivia = trivia) :: _ -> trivia.LeadingKeyword.Range + | _ -> range0 + + SynExpr.LetOrUse( + isRec, + isUse, // Pass through the isUse flag from binding info + decls, + body, + mWhole', + { + LetOrUseKeyword = mLetOrUse + InKeyword = mIn' + } + ) + | None -> + failwith "mkLetExpression: bindingInfo required for regular let/use expressions" diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fsi b/src/Compiler/SyntaxTree/ParseHelpers.fsi index 84be5f0e4f7..0f67a2bc1f3 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fsi +++ b/src/Compiler/SyntaxTree/ParseHelpers.fsi @@ -196,7 +196,19 @@ val mkClassMemberLocalBindings: isStatic: bool * initialRangeOpt: range option * attrs: SynAttributes * vis: SynAccess option * BindingSet -> SynMemberDefn -val mkLocalBindings: mWhole: range * BindingSet * mIn: range option * body: SynExpr -> SynExpr +/// Creates either SynExpr.LetOrUse or SynExpr.LetOrUseBang based on isBang parameter +/// Handles all four cases: 'let', 'let!', 'use', and 'use!' +val mkLetExpression: + isBang: bool * + mKeyword: range * + mIn: range option * + mWhole: range * + body: SynExpr * + bindingInfo: (bool * BindingSet) option * + bangInfo: (SynPat * SynExpr * SynExprAndBang list * range option * bool) option -> SynExpr + +val mkAndBang: + mKeyword: range * pat: SynPat * rhs: SynExpr * mWhole: range * mEquals: range * mIn: range option -> SynExprAndBang val mkDefnBindings: mWhole: range * BindingSet * attrs: SynAttributes * vis: SynAccess option * attrsm: range -> SynModuleDecl list diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 6c373bf45da..4aaca811f3d 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4131,12 +4131,15 @@ sequentialExpr: SynExpr.Sequential(DebugPointAtSequential.SuppressNeither, false, $1, $4, unionRanges $1.Range $4.Range, trivia) } | hardwhiteLetBindings %prec prec_args_error - { let hwlb, m, mIn = $1 - let mLetKwd, isUse = match hwlb with (BindingSetPreAttrs(m, _, isUse, _, _)) -> m, isUse + { let bindingSet, m, mIn = $1 + let mLetKwd, isUse = match bindingSet with (BindingSetPreAttrs(m, _, isUse, _, _)) -> m, isUse let usedKeyword = if isUse then "use" else "let" reportParseErrorAt mLetKwd (FSComp.SR.parsExpectedExpressionAfterLet(usedKeyword, usedKeyword)) let fauxRange = m.EndRange // zero width range at end of m - mkLocalBindings (m, hwlb, mIn, arbExpr ("seqExpr", fauxRange)) } + // Extract isRec from BindingSetPreAttrs + let isRec = match bindingSet with BindingSetPreAttrs(_, isRec, _, _, _) -> isRec + // Use mkLetExpression for both let and use expressions + mkLetExpression(false, mLetKwd, mIn, m, arbExpr ("seqExpr", fauxRange), Some(isRec, bindingSet), None) } /* Use this as the last terminal when performing error recovery */ /* The contract for using this is that (a) if EOF occurs then the */ @@ -4161,15 +4164,12 @@ moreBinders: if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) if isMutable then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) + let mKeyword = rhs parseState 1 let mEquals = rhs parseState 3 - let m = unionRanges (rhs parseState 1) $4.Range - // Debug point should span the entire binding: from AND_BANG through the expression - let spBind = DebugPointAtBinding.Yes(m) - let mIn = rhs parseState 5 - let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = Some mIn } + let m = unionRanges mKeyword $4.Range + let mIn = Some(rhs parseState 5) - // Note: For and!, we always use isRecursive=false and isUse=true - SynExprAndBang(spBind, false, true, pat, $4, m, trivia) :: $6 } + mkAndBang(mKeyword, pat, $4, m, mEquals, mIn) :: $6 } | OAND_BANG ceBindingCore EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let { // Offside-sensitive version of and! binding @@ -4181,14 +4181,11 @@ moreBinders: let report, mIn, _ = $5 report "and!" (rhs parseState 1) // report unterminated error + let mKeyword = rhs parseState 1 let mEquals = rhs parseState 3 - let m = unionRanges (rhs parseState 1) $4.Range - // Debug point should span the entire binding: from OAND_BANG through the expression - let spBind = DebugPointAtBinding.Yes(m) - let trivia = { AndBangKeyword = rhs parseState 1; EqualsRange = mEquals; InKeyword = mIn } + let m = unionRanges mKeyword $4.Range - // Note: For and!, we always use isRecursive=false and isUse=true - SynExprAndBang(spBind, false, true, pat, $4, m, trivia) :: $7 } + mkAndBang(mKeyword, pat, $4, m, mEquals, mIn) :: $7 } | %prec prec_no_more_attr_bindings { [] } @@ -4196,32 +4193,57 @@ moreBinders: declExpr: | defnBindings IN typedSequentialExpr %prec expr_let { let mIn = rhs parseState 2 |> Some - mkLocalBindings (unionRanges (rhs2 parseState 1 2) $3.Range, $1, mIn, $3) } + let mWhole = unionRanges (rhs2 parseState 1 2) $3.Range + let bindingSet = $1 + // Extract isRec and mKeyword from BindingSetPreAttrs + let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec + // Use mkLetExpression for both let and use expressions + mkLetExpression(false, mKeyword, mIn, mWhole, $3, Some(isRec, bindingSet), None) } | defnBindings IN error %prec expr_let { let mIn = rhs parseState 2 |> Some - mkLocalBindings (rhs2 parseState 1 2, $1, mIn, arbExpr ("declExpr1", (rhs parseState 3))) } + let mWhole = rhs2 parseState 1 2 + let bindingSet = $1 + // Extract isRec and mKeyword from BindingSetPreAttrs + let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec + // Use mkLetExpression for both let and use expressions + mkLetExpression(false, mKeyword, mIn, mWhole, arbExpr ("declExpr1", (rhs parseState 3)), Some(isRec, bindingSet), None) } /* FSComp.SR.parsNoMatchingInForLet() -- leave this in for now - it's an unused error string */ | hardwhiteLetBindings typedSequentialExprBlock %prec expr_let - { let hwlb, m, mIn = $1 - mkLocalBindings (unionRanges m $2.Range, hwlb, mIn, $2) } + { let bindingSet, m, mIn = $1 + let mWhole = unionRanges m $2.Range + // Extract isRec and mKeyword from BindingSetPreAttrs + let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec + // Use mkLetExpression for both let and use expressions + mkLetExpression(false, mKeyword, mIn, mWhole, $2, Some(isRec, bindingSet), None) } | hardwhiteLetBindings error %prec expr_let - { let hwlb, m, mIn = $1 - reportParseErrorAt (match hwlb with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) - mkLocalBindings (m, hwlb, mIn, arbExpr ("declExpr2", (rhs parseState 2))) } + { let bindingSet, m, mIn = $1 + reportParseErrorAt (match bindingSet with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) + // Extract isRec and mKeyword from BindingSetPreAttrs + let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec + // Use mkLetExpression for both let and use expressions + mkLetExpression(false, mKeyword, mIn, m, arbExpr ("declExpr2", (rhs parseState 2)), Some(isRec, bindingSet), None) } | hardwhiteLetBindings OBLOCKSEP typedSequentialExprBlock %prec expr_let - { let hwlb, m, mIn = $1 - mkLocalBindings (unionRanges m $3.Range, hwlb, mIn, $3) } + { let bindingSet, m, mIn = $1 + let mWhole = unionRanges m $3.Range + // Extract isRec and mKeyword from BindingSetPreAttrs + let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec + // Use mkLetExpression for both let and use expressions + mkLetExpression(false, mKeyword, mIn, mWhole, $3, Some(isRec, bindingSet), None) } | hardwhiteLetBindings OBLOCKSEP error %prec expr_let - { let hwlb, m, mIn = $1 - //reportParseErrorAt (match hwlb with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) - mkLocalBindings (unionRanges m (rhs parseState 3), hwlb, mIn, arbExpr ("declExpr3", (rhs parseState 3))) } + { let bindingSet, m, mIn = $1 + //reportParseErrorAt (match bindingSet with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) + let mWhole = unionRanges m (rhs parseState 3) + // Extract isRec and mKeyword from BindingSetPreAttrs + let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec + // Use mkLetExpression for both let and use expressions + mkLetExpression(false, mKeyword, mIn, mWhole, arbExpr ("declExpr3", (rhs parseState 3)), Some(isRec, bindingSet), None) } | hardwhiteDoBinding %prec expr_let { let (BindingSetPreAttrs(_, _, _, _, m)), e = $1 @@ -4555,15 +4577,15 @@ declExpr: if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) if isMutable then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) - let mEquals = rhs parseState 3 - let m = unionRanges (rhs parseState 1) $8.Range - // Debug point should span from BINDER through the expression (but not the continuation) - let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) - let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } + let mKeyword = rhs parseState 1 + let mEquals = Some(rhs parseState 3) + let m = unionRanges mKeyword $8.Range - // $1 contains the actual keyword ("let!" or "use!") + // $1 contains the actual keyword ("let" or "use") let isUse = ($1 = "use") - SynExpr.LetOrUseBang(spBind, isUse, true, pat, $4, $7, $8, m, trivia) } + + // Use mkLetExpression for both let! and use! bindings + mkLetExpression(true, mKeyword, None, m, $8, None, Some(pat, $4, $7, mEquals, isUse)) } | OBINDER ceBindingCore EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let { // Offside-sensitive version of let!/use! binding @@ -4575,14 +4597,14 @@ declExpr: let report, mIn, _ = $5 report (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error - let mEquals = rhs parseState 3 - let m = unionRanges (rhs parseState 1) $8.Range - // Debug point should span from OBINDER through the expression (but not the continuation) - let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) - let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } + let mKeyword = rhs parseState 1 + let mEquals = Some(rhs parseState 3) + let m = unionRanges mKeyword $8.Range let isUse = ($1 = "use") - SynExpr.LetOrUseBang(spBind, isUse, true, pat, $4, $7, $8, m, trivia) } + + // Use mkLetExpression for both let! and use! bindings + mkLetExpression(true, mKeyword, None, m, $8, None, Some(pat, $4, $7, mEquals, isUse)) } | OBINDER ceBindingCore EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let { // Error recovery for incomplete let!/use! bindings @@ -4593,16 +4615,16 @@ declExpr: if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) if isMutable then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) - // Debug point should span from OBINDER through the expression - let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) - let mEquals = rhs parseState 3 - let mAll = unionRanges (rhs parseState 1) (rhs parseState 7) + let mKeyword = rhs parseState 1 + let mEquals = Some(rhs parseState 3) + let mAll = unionRanges mKeyword (rhs parseState 7) let m = $4.Range.EndRange // zero-width range - let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals } let isUse = ($1 = "use") + // Use ImplicitZero as the continuation expression for error recovery - SynExpr.LetOrUseBang(spBind, isUse, true, pat, $4, [], SynExpr.ImplicitZero m, mAll, trivia) } + // Use mkLetExpression for both let! and use! bindings + mkLetExpression(true, mKeyword, None, mAll, SynExpr.ImplicitZero m, None, Some(pat, $4, [], mEquals, isUse)) } | DO_BANG typedSequentialExpr IN opt_OBLOCKSEP typedSequentialExprBlock %prec expr_let { let spBind = DebugPointAtBinding.NoneAtDo From 7aeb9b7ef9e26155943efa187819f9845a723cd6 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Sat, 5 Jul 2025 17:33:21 -0500 Subject: [PATCH 18/22] format code --- src/Compiler/Facilities/LanguageFeatures.fs | 2 +- src/Compiler/SyntaxTree/ParseHelpers.fs | 12 +++++------- src/Compiler/SyntaxTree/ParseHelpers.fsi | 3 ++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index d260d55292b..817f63672bb 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -235,7 +235,7 @@ type LanguageVersion(versionText) = LanguageFeature.UseBangBindingValueDiscard, languageVersion100 LanguageFeature.BetterAnonymousRecordParsing, languageVersion100 LanguageFeature.ScopedNowarn, languageVersion100 - LanguageFeature.AllowTypedLetOrUseBang, languageVersion100 + LanguageFeature.AllowTypedLetUseAndBang, languageVersion100 // F# preview (still preview in 10.0) LanguageFeature.UnmanagedConstraintCsharpInterop, previewVersion // not enabled because: https://github.com/dotnet/fsharp/issues/17509 diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index 9dfa2aa9458..d9a187e4775 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -1054,7 +1054,6 @@ let leadingKeywordIsAbstract = | SynLeadingKeyword.StaticAbstractMember _ -> true | _ -> false - /// Unified helper for creating let/let!/use/use! expressions /// Creates either SynExpr.LetOrUse or SynExpr.LetOrUseBang based on isBang parameter /// Handles all four cases: 'let', 'let!', 'use', and 'use!' @@ -1072,9 +1071,10 @@ let mkLetExpression ) = if isBang then match bangInfo with - | Some (pat, rhs, andBangs, mEquals, isUse) -> + | Some(pat, rhs, andBangs, mEquals, isUse) -> // Create let! or use! expression let spBind = DebugPointAtBinding.Yes(unionRanges mKeyword rhs.Range) + let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = mKeyword @@ -1082,11 +1082,10 @@ let mkLetExpression } // isFromSource is true for user-written code SynExpr.LetOrUseBang(spBind, isUse, true, pat, rhs, andBangs, body, mWhole, trivia) - | None -> - failwith "mkLetExpression: bangInfo required for let!/use! expressions" + | None -> failwith "mkLetExpression: bangInfo required for let!/use! expressions" else match bindingInfo with - | Some (isRec, BindingSetPreAttrs(_, _, isUse, declsPreAttrs, _)) -> + | Some(isRec, BindingSetPreAttrs(_, _, isUse, declsPreAttrs, _)) -> // Create regular let or use expression let ignoredFreeAttrs, decls = declsPreAttrs [] None @@ -1122,5 +1121,4 @@ let mkLetExpression InKeyword = mIn' } ) - | None -> - failwith "mkLetExpression: bindingInfo required for regular let/use expressions" + | None -> failwith "mkLetExpression: bindingInfo required for regular let/use expressions" diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fsi b/src/Compiler/SyntaxTree/ParseHelpers.fsi index 0f67a2bc1f3..190545286a4 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fsi +++ b/src/Compiler/SyntaxTree/ParseHelpers.fsi @@ -205,7 +205,8 @@ val mkLetExpression: mWhole: range * body: SynExpr * bindingInfo: (bool * BindingSet) option * - bangInfo: (SynPat * SynExpr * SynExprAndBang list * range option * bool) option -> SynExpr + bangInfo: (SynPat * SynExpr * SynExprAndBang list * range option * bool) option -> + SynExpr val mkAndBang: mKeyword: range * pat: SynPat * rhs: SynExpr * mWhole: range * mEquals: range * mIn: range option -> SynExprAndBang From 9e50380fc113440e928f7828912ad06e8c7e9239 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Sun, 6 Jul 2025 00:11:27 -0500 Subject: [PATCH 19/22] update tests --- .../UseBindings/UseBangBindings.fs | 6 +++--- .../Language/ComputationExpressionTests.fs | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs index 77ac4e5706f..79fd3535db9 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs @@ -59,9 +59,9 @@ module UseBangBindingsVersion9 = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 43, Col 14, Line 43, Col 28, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") - (Error 3350, Line 41, Col 14, Line 41, Col 28, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") - (Error 3350, Line 40, Col 14, Line 40, Col 29, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") + (Error 3350, Line 40, Col 18, Line 40, Col 29, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") + (Error 3350, Line 41, Col 17, Line 41, Col 28, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") + (Error 3350, Line 43, Col 17, Line 43, Col 28, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") ] module UseBangBindingsPreview = diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index 40c6be388fd..d7a6d342996 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -1576,8 +1576,8 @@ let testParallel3() = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 43, Col 17, Line 43, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); - (Error 3350, Line 44, Col 17, Line 44, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 43, Col 17, Line 43, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater."); + (Error 3350, Line 44, Col 17, Line 44, Col 20, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") ] [] @@ -1693,8 +1693,8 @@ let testParallel2() = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 42, Col 42, Line 42, Col 48, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); - (Error 3350, Line 43, Col 48, Line 43, Col 52, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 42, Col 42, Line 42, Col 48, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater."); + (Error 3350, Line 43, Col 48, Line 43, Col 52, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") ] [] @@ -1809,10 +1809,10 @@ let testParallel2() = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3350, Line 34, Col 29, Line 34, 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."); - (Error 3350, Line 35, Col 29, Line 35, Col 45, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); - (Error 3350, Line 41, Col 27, Line 41, Col 40, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); - (Error 3350, Line 42, Col 27, Line 42, 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.") + (Error 3350, Line 34, Col 29, Line 34, Col 42, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater."); + (Error 3350, Line 35, Col 29, Line 35, Col 45, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater."); + (Error 3350, Line 41, Col 27, Line 41, Col 40, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater."); + (Error 3350, Line 42, Col 27, Line 42, Col 43, "Feature 'Allow let! and use! type annotations without requiring parentheses' is not available in F# 9.0. Please use language version 10.0 or greater.") ] [] From 02fecdffb2947623474af0dfb1906f919bf0b4a7 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Fri, 11 Jul 2025 22:14:24 -0500 Subject: [PATCH 20/22] cover error cases in the grammar --- src/Compiler/SyntaxTree/ParseHelpers.fs | 4 +- src/Compiler/pars.fsy | 28 ++++---- .../SyntaxTree/SynType/Typed LetBang 14.fs | 7 ++ .../SynType/Typed LetBang 14.fs.bsl | 67 ++++++++++++++++++ .../SyntaxTree/SynType/Typed LetBang 15.fs | 7 ++ .../SynType/Typed LetBang 15.fs.bsl | 48 +++++++++++++ .../SyntaxTree/SynType/Typed LetBang 16.fs | 7 ++ .../SynType/Typed LetBang 16.fs.bsl | 12 ++++ .../SynType/Typed LetBang AndBang 18.fs | 7 ++ .../SynType/Typed LetBang AndBang 18.fs.bsl | 68 +++++++++++++++++++ .../SyntaxTree/SynType/Typed UseBang 05.fs | 6 ++ .../SynType/Typed UseBang 05.fs.bsl | 37 ++++++++++ .../SyntaxTree/SynType/Typed UseBang 06.fs | 6 ++ .../SynType/Typed UseBang 06.fs.bsl | 12 ++++ 14 files changed, 298 insertions(+), 18 deletions(-) create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs.bsl diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index d9a187e4775..b797e2bc59c 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -1082,7 +1082,7 @@ let mkLetExpression } // isFromSource is true for user-written code SynExpr.LetOrUseBang(spBind, isUse, true, pat, rhs, andBangs, body, mWhole, trivia) - | None -> failwith "mkLetExpression: bangInfo required for let!/use! expressions" + | None -> SynExpr.FromParseError(body, mWhole) else match bindingInfo with | Some(isRec, BindingSetPreAttrs(_, _, isUse, declsPreAttrs, _)) -> @@ -1121,4 +1121,4 @@ let mkLetExpression InKeyword = mIn' } ) - | None -> failwith "mkLetExpression: bindingInfo required for regular let/use expressions" + | None -> SynExpr.FromParseError(body, mWhole) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 4aaca811f3d..2f6e2953d35 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3533,22 +3533,18 @@ bindingPatternWithOptType: { // Simple pattern without type annotation $1, $1.Range, None } - | headBindingPattern COLON topTypeWithTypeConstraints - { // Pattern with type annotation (e.g., x: int) - let ty, arity = $3 - let mWhole = unionRanges $1.Range ty.Range - // Create a typed pattern node - let typedPat = SynPat.Typed($1, ty, mWhole) - typedPat, mWhole, Some ty } - - | headBindingPattern COLON error - { // Error recovery: incomplete type annotation (e.g., "let x:" with no type) - let mColon = rhs parseState 2 - let mWhole = unionRanges $1.Range mColon - // Create a typed pattern with an error type for recovery - let errorType = SynType.FromParseError(mColon.EndRange) - let typedPat = SynPat.Typed($1, errorType, mWhole) - typedPat, mWhole, Some errorType } + | headBindingPattern opt_topReturnTypeWithTypeConstraints + { // Pattern with optional type annotation + match $2 with + | None -> + // No type annotation + $1, $1.Range, None + | Some(colonRangeOpt, SynReturnInfo((ty, _), _)) -> + // Pattern with type annotation (e.g., x: int) + let mWhole = unionRanges $1.Range ty.Range + // Create a typed pattern node + let typedPat = SynPat.Typed($1, ty, mWhole) + typedPat, mWhole, Some ty } /* Common rule for computation expression binding patterns Handles the pattern part of let!, use!, and! bindings with consistent diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs new file mode 100644 index 00000000000..098e12cd639 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (x as y): = asyncInt() + and! (a as b): string = asyncString() + return x + b +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs.bsl new file mode 100644 index 00000000000..a5ca5ea403f --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs.bsl @@ -0,0 +1,67 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 14.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,31), false, true, + Typed + (Paren + (As + (Named + (SynIdent (x, None), false, None, (4,10--4,11)), + Named + (SynIdent (y, None), false, None, (4,15--4,16)), + (4,10--4,16)), (4,9--4,17)), + FromParseError (4,18--4,18), (4,9--4,18)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,29--4,31)), (4,21--4,31)), + [SynExprAndBang + (Yes (5,4--5,41), false, true, + Typed + (Paren + (As + (Named + (SynIdent (a, None), false, None, + (5,10--5,11)), + Named + (SynIdent (b, None), false, None, + (5,15--5,16)), (5,10--5,16)), (5,9--5,17)), + LongIdent (SynLongIdent ([string], [], [None])), + (5,9--5,25)), + App + (Atomic, false, Ident asyncString, + Const (Unit, (5,39--5,41)), (5,28--5,41)), + (5,4--5,41), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,26--5,27) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,13--6,14)), Ident x, (6,11--6,14)), + Ident b, (6,11--6,16)), (6,4--6,16), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,19--4,20) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(4,19)-(4,20) parse error Unexpected symbol '=' in expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs new file mode 100644 index 00000000000..141c53d6724 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (x as y): + and! (a as b): string = asyncString() + return x + b +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs.bsl new file mode 100644 index 00000000000..e4db6014bf8 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs.bsl @@ -0,0 +1,48 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 15.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--5,41), false, true, + Typed + (Paren + (As + (Named + (SynIdent (x, None), false, None, (4,10--4,11)), + Named + (SynIdent (y, None), false, None, (4,15--4,16)), + (4,10--4,16)), (4,9--4,17)), + FromParseError (4,18--4,18), (4,9--4,18)), + App + (Atomic, false, Ident asyncString, + Const (Unit, (5,39--5,41)), (5,28--5,41)), [], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,13--6,14)), Ident x, (6,11--6,14)), + Ident b, (6,11--6,16)), (6,4--6,16), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (5,26--5,27) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(5,4)-(5,8) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs new file mode 100644 index 00000000000..39041e9b461 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (x as y): int = asyncInt() + and! (a as b): + return x + b +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs.bsl new file mode 100644 index 00000000000..8faddfde7f5 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs.bsl @@ -0,0 +1,12 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 16.fs", false, + QualifiedNameOfFile Typed LetBang 16, [], + [SynModuleOrNamespace + ([Typed LetBang 16], false, AnonModule, [], PreXmlDocEmpty, [], None, + (7,1--7,1), { LeadingKeyword = None })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(6,4)-(6,10) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs new file mode 100644 index 00000000000..d4e86eafa48 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs @@ -0,0 +1,7 @@ +module Module + +async { + let! (x as y): int = asyncInt() + and! (a as b): = asyncString() + return x + b +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs.bsl new file mode 100644 index 00000000000..1e38d52d4e5 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs.bsl @@ -0,0 +1,68 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang AndBang 18.fs", false, + QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,35), false, true, + Typed + (Paren + (As + (Named + (SynIdent (x, None), false, None, (4,10--4,11)), + Named + (SynIdent (y, None), false, None, (4,15--4,16)), + (4,10--4,16)), (4,9--4,17)), + LongIdent (SynLongIdent ([int], [], [None])), + (4,9--4,22)), + App + (Atomic, false, Ident asyncInt, + Const (Unit, (4,33--4,35)), (4,25--4,35)), + [SynExprAndBang + (Yes (5,4--5,34), false, true, + Typed + (Paren + (As + (Named + (SynIdent (a, None), false, None, + (5,10--5,11)), + Named + (SynIdent (b, None), false, None, + (5,15--5,16)), (5,10--5,16)), (5,9--5,17)), + FromParseError (5,18--5,18), (5,9--5,18)), + App + (Atomic, false, Ident asyncString, + Const (Unit, (5,32--5,34)), (5,21--5,34)), + (5,4--5,34), { AndBangKeyword = (5,4--5,8) + EqualsRange = (5,19--5,20) + InKeyword = None })], + YieldOrReturn + ((false, true), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (6,13--6,14)), Ident x, (6,11--6,14)), + Ident b, (6,11--6,16)), (6,4--6,16), + { YieldOrReturnKeyword = (6,4--6,10) }), (4,4--6,16), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,23--4,24) }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(5,19)-(5,20) parse error Unexpected symbol '=' in expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs b/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs new file mode 100644 index 00000000000..4fd5d1f25ef --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs @@ -0,0 +1,6 @@ +module Module + +async { + use! res: = async { return 1 } + return res +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs.bsl new file mode 100644 index 00000000000..4b1410b5274 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs.bsl @@ -0,0 +1,37 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed UseBang 05.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUseBang + (Yes (4,4--4,34), true, true, + Typed + (Named (SynIdent (res, None), false, None, (4,9--4,12)), + FromParseError (4,13--4,13), (4,9--4,13)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 1, (4,31--4,32)), + (4,24--4,32), + { YieldOrReturnKeyword = (4,24--4,30) }), + (4,22--4,34)), (4,16--4,34)), [], + YieldOrReturn + ((false, true), Ident res, (5,4--5,14), + { YieldOrReturnKeyword = (5,4--5,10) }), (4,4--5,14), + { LetOrUseBangKeyword = (4,4--4,8) + EqualsRange = Some (4,14--4,15) }), (3,6--6,1)), + (3,0--6,1)), (3,0--6,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--6,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(4,14)-(4,15) parse error Unexpected symbol '=' in expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs b/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs new file mode 100644 index 00000000000..66bc6a8e4b7 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs @@ -0,0 +1,6 @@ +module Module + +async { + use! res: + return res +} diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs.bsl new file mode 100644 index 00000000000..34b209cbdc7 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs.bsl @@ -0,0 +1,12 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed UseBang 06.fs", false, + QualifiedNameOfFile Typed UseBang 06, [], + [SynModuleOrNamespace + ([Typed UseBang 06], false, AnonModule, [], PreXmlDocEmpty, [], None, + (7,0--7,0), { LeadingKeyword = None })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(5,4)-(5,10) parse error Incomplete structured construct at or before this point in expression From fd7e890d2cbe616097cda205c0b3a95cce75deb7 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Sat, 12 Jul 2025 16:05:46 -0500 Subject: [PATCH 21/22] Use parsExpectingType --- src/Compiler/SyntaxTree/ParseHelpers.fs | 4 -- src/Compiler/pars.fsy | 47 ++----------------- .../SyntaxTree/Expression/Return 07.fs.bsl | 1 + .../Expression/ReturnBang 03.fs.bsl | 1 + .../SyntaxTree/Expression/Yield 05.fs.bsl | 1 + .../SyntaxTree/Expression/Yield 06.fs.bsl | 1 + .../SyntaxTree/Expression/YieldBang 05.fs.bsl | 1 + .../SyntaxTree/Expression/YieldBang 06.fs.bsl | 1 + .../data/SyntaxTree/Member/Member 13.fs.bsl | 1 + .../Pattern/Typed - Missing type 01.fs.bsl | 1 + .../Pattern/Typed - Missing type 02.fs.bsl | 1 + .../Pattern/Typed - Missing type 05.fs.bsl | 1 + .../Pattern/Typed - Missing type 06.fs.bsl | 1 + .../SynType/Typed LetBang 14.fs.bsl | 1 + .../SynType/Typed LetBang 15.fs.bsl | 1 + .../SynType/Typed LetBang 16.fs.bsl | 1 + .../SynType/Typed LetBang AndBang 18.fs.bsl | 1 + .../SynType/Typed UseBang 05.fs.bsl | 1 + .../SynType/Typed UseBang 06.fs.bsl | 1 + 19 files changed, 21 insertions(+), 47 deletions(-) diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index b797e2bc59c..4aeffc3a056 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -869,10 +869,8 @@ let mkClassMemberLocalBindings /// Creates a SynExprAndBang node for and! bindings in computation expressions let mkAndBang (mKeyword: range, pat: SynPat, rhs: SynExpr, mWhole: range, mEquals: range, mIn: range option) = - // Calculate debug point range: from keyword through the rhs expression let spBind = DebugPointAtBinding.Yes(unionRanges mKeyword rhs.Range) - // Create trivia let trivia: SynExprAndBangTrivia = { AndBangKeyword = mKeyword @@ -1064,9 +1062,7 @@ let mkLetExpression mIn: Option, mWhole: range, body: SynExpr, - // For regular let/use: binding information bindingInfo: (bool * BindingSet) option, - // For let!/use!: pattern, rhs, andBangs, equals range, and isUse flag bangInfo: (SynPat * SynExpr * SynExprAndBang list * range option * bool) option ) = if isBang then diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 2f6e2953d35..ee2e4de3fde 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3520,14 +3520,7 @@ bindingPattern: | headBindingPattern { $1, $1.Range } -/* Common pattern for bindings that may include type annotations - This rule unifies the pattern parsing for both regular 'let' bindings and - computation expression bindings (let!, use!, and!). - - Returns: (pattern, pattern_range, optional_type) - - pattern: The parsed pattern (may be typed if annotation present) - - pattern_range: The full range including any type annotation - - optional_type: The type if annotation was present, None otherwise */ +// This rule unifies the pattern parsing for both regular 'let' bindings and (let!, use!, and!) bindingPatternWithOptType: | headBindingPattern { // Simple pattern without type annotation @@ -3542,24 +3535,15 @@ bindingPatternWithOptType: | Some(colonRangeOpt, SynReturnInfo((ty, _), _)) -> // Pattern with type annotation (e.g., x: int) let mWhole = unionRanges $1.Range ty.Range - // Create a typed pattern node let typedPat = SynPat.Typed($1, ty, mWhole) typedPat, mWhole, Some ty } -/* Common rule for computation expression binding patterns - Handles the pattern part of let!, use!, and! bindings with consistent - type annotation support and language feature checking. - - Returns: (pattern, pattern_range, isInline, isMutable, optional_type) */ +// Handles the pattern part of let!, use!, and! bindings ceBindingCore: | opt_inline opt_mutable bindingPatternWithOptType { let pat, mPat, tyOpt = $3 let isInline = Option.isSome $1 let isMutable = Option.isSome $2 - - // For CE bindings, check language feature if type annotation is present - // This ensures that typed let!/use!/and! bindings are only allowed when - // the AllowTypedLetUseAndBang feature is enabled match tyOpt with | Some ty -> parseState.LexBuffer.CheckLanguageFeatureAndRecover LanguageFeature.AllowTypedLetUseAndBang ty.Range @@ -4132,9 +4116,7 @@ sequentialExpr: let usedKeyword = if isUse then "use" else "let" reportParseErrorAt mLetKwd (FSComp.SR.parsExpectedExpressionAfterLet(usedKeyword, usedKeyword)) let fauxRange = m.EndRange // zero width range at end of m - // Extract isRec from BindingSetPreAttrs let isRec = match bindingSet with BindingSetPreAttrs(_, isRec, _, _, _) -> isRec - // Use mkLetExpression for both let and use expressions mkLetExpression(false, mLetKwd, mIn, m, arbExpr ("seqExpr", fauxRange), Some(isRec, bindingSet), None) } /* Use this as the last terminal when performing error recovery */ @@ -4149,12 +4131,8 @@ recover: { debugPrint("recovering via EOF"); false } moreBinders: - /* Refactored and! bindings to use unified ceBindingCore - This ensures consistent handling of patterns and type annotations - across all computation expression bindings */ | AND_BANG ceBindingCore EQUALS typedSequentialExprBlock IN moreBinders %prec expr_let - { // Handle and! bindings with unified pattern parsing - let pat, mPat, isInline, isMutable, tyOpt = $2 + { let pat, mPat, isInline, isMutable, tyOpt = $2 // and! bindings don't support inline or mutable modifiers if isInline then errorR(Error(FSComp.SR.parsInvalidDeclarationSyntax(), rhs parseState 2)) @@ -4191,18 +4169,14 @@ declExpr: { let mIn = rhs parseState 2 |> Some let mWhole = unionRanges (rhs2 parseState 1 2) $3.Range let bindingSet = $1 - // Extract isRec and mKeyword from BindingSetPreAttrs let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec - // Use mkLetExpression for both let and use expressions mkLetExpression(false, mKeyword, mIn, mWhole, $3, Some(isRec, bindingSet), None) } | defnBindings IN error %prec expr_let { let mIn = rhs parseState 2 |> Some let mWhole = rhs2 parseState 1 2 let bindingSet = $1 - // Extract isRec and mKeyword from BindingSetPreAttrs let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec - // Use mkLetExpression for both let and use expressions mkLetExpression(false, mKeyword, mIn, mWhole, arbExpr ("declExpr1", (rhs parseState 3)), Some(isRec, bindingSet), None) } /* FSComp.SR.parsNoMatchingInForLet() -- leave this in for now - it's an unused error string @@ -4211,34 +4185,26 @@ declExpr: | hardwhiteLetBindings typedSequentialExprBlock %prec expr_let { let bindingSet, m, mIn = $1 let mWhole = unionRanges m $2.Range - // Extract isRec and mKeyword from BindingSetPreAttrs let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec - // Use mkLetExpression for both let and use expressions mkLetExpression(false, mKeyword, mIn, mWhole, $2, Some(isRec, bindingSet), None) } | hardwhiteLetBindings error %prec expr_let { let bindingSet, m, mIn = $1 reportParseErrorAt (match bindingSet with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) - // Extract isRec and mKeyword from BindingSetPreAttrs let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec - // Use mkLetExpression for both let and use expressions mkLetExpression(false, mKeyword, mIn, m, arbExpr ("declExpr2", (rhs parseState 2)), Some(isRec, bindingSet), None) } | hardwhiteLetBindings OBLOCKSEP typedSequentialExprBlock %prec expr_let { let bindingSet, m, mIn = $1 let mWhole = unionRanges m $3.Range - // Extract isRec and mKeyword from BindingSetPreAttrs let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec - // Use mkLetExpression for both let and use expressions mkLetExpression(false, mKeyword, mIn, mWhole, $3, Some(isRec, bindingSet), None) } | hardwhiteLetBindings OBLOCKSEP error %prec expr_let { let bindingSet, m, mIn = $1 //reportParseErrorAt (match bindingSet with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) let mWhole = unionRanges m (rhs parseState 3) - // Extract isRec and mKeyword from BindingSetPreAttrs let mKeyword, isRec = match bindingSet with BindingSetPreAttrs(m, isRec, _, _, _) -> m, isRec - // Use mkLetExpression for both let and use expressions mkLetExpression(false, mKeyword, mIn, mWhole, arbExpr ("declExpr3", (rhs parseState 3)), Some(isRec, bindingSet), None) } | hardwhiteDoBinding %prec expr_let @@ -4562,9 +4528,6 @@ declExpr: SynExpr.Typed($2, ty, m) SynExpr.YieldOrReturnFrom(($1, not $1), expr, (unionRanges (rhs parseState 1) $2.Range), trivia) } - /* Refactored let! and use! bindings to use unified ceBindingCore - This ensures consistent handling across all computation expression bindings - while maintaining backward compatibility */ | BINDER ceBindingCore EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let { // Handle let! and use! bindings with unified pattern parsing let pat, mPat, isInline, isMutable, tyOpt = $2 @@ -4580,7 +4543,6 @@ declExpr: // $1 contains the actual keyword ("let" or "use") let isUse = ($1 = "use") - // Use mkLetExpression for both let! and use! bindings mkLetExpression(true, mKeyword, None, m, $8, None, Some(pat, $4, $7, mEquals, isUse)) } | OBINDER ceBindingCore EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let @@ -4599,7 +4561,6 @@ declExpr: let isUse = ($1 = "use") - // Use mkLetExpression for both let! and use! bindings mkLetExpression(true, mKeyword, None, m, $8, None, Some(pat, $4, $7, mEquals, isUse)) } | OBINDER ceBindingCore EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let @@ -4619,7 +4580,6 @@ declExpr: let isUse = ($1 = "use") // Use ImplicitZero as the continuation expression for error recovery - // Use mkLetExpression for both let! and use! bindings mkLetExpression(true, mKeyword, None, mAll, SynExpr.ImplicitZero m, None, Some(pat, $4, [], mEquals, isUse)) } | DO_BANG typedSequentialExpr IN opt_OBLOCKSEP typedSequentialExprBlock %prec expr_let @@ -6079,6 +6039,7 @@ opt_topReturnTypeWithTypeConstraints: | COLON recover { let mColon = rhs parseState 1 let ty, arity = SynType.FromParseError(mColon.EndRange), SynInfo.unnamedRetVal + reportParseErrorAt mColon.EndRange (FSComp.SR.parsExpectingType ()) Some(Some mColon, SynReturnInfo((ty, arity), mColon.EndRange)) } topType: diff --git a/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl b/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl index 0bf151be5bb..d45aa5689ce 100644 --- a/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Return 07.fs.bsl @@ -35,3 +35,4 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,5) parse error Unexpected symbol '}' in expression +(5,29)-(5,29) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl index e23e8ccde38..1747359d47d 100644 --- a/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/ReturnBang 03.fs.bsl @@ -36,3 +36,4 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,5) parse error Unexpected symbol '}' in expression +(5,30)-(5,30) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl index 1deada75f94..b3b6e05aabf 100644 --- a/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Yield 05.fs.bsl @@ -29,3 +29,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected symbol '}' in expression +(4,23)-(4,23) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl index ced49e682d6..43a6887f39e 100644 --- a/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Yield 06.fs.bsl @@ -29,3 +29,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected symbol '}' in expression +(4,23)-(4,23) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl index 595f455632d..317ca5dc112 100644 --- a/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 05.fs.bsl @@ -29,3 +29,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected symbol '}' in expression +(4,24)-(4,24) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl index de83602e2d5..dbbbe74f59a 100644 --- a/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/YieldBang 06.fs.bsl @@ -22,3 +22,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Incomplete structured construct at or before this point in expression +(3,20)-(3,20) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/Member/Member 13.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 13.fs.bsl index 929250cabbe..bb146d2a2ba 100644 --- a/tests/service/data/SyntaxTree/Member/Member 13.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Member 13.fs.bsl @@ -75,4 +75,5 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,4) parse error Incomplete structured construct at or before this point in member definition +(4,20)-(4,20) parse error Expecting type (6,0)-(6,4) parse error Expecting member body diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 01.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 01.fs.bsl index c3b01295134..47a126930af 100644 --- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 01.fs.bsl @@ -29,5 +29,6 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Incomplete structured construct at or before this point in binding +(3,6)-(3,6) parse error Expecting type (6,0)-(6,0) parse error Unexpected end of input in value, function or member definition (3,0)-(3,3) parse error Incomplete value or function definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let' keyword. diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 02.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 02.fs.bsl index d90f5c5d863..ead5a85c1af 100644 --- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 02.fs.bsl @@ -30,3 +30,4 @@ ImplFile CodeComments = [] }, set [])) (3,7)-(3,8) parse error Unexpected symbol '=' in binding +(3,6)-(3,6) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl index 86cac0dc468..12785905c05 100644 --- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 05.fs.bsl @@ -40,6 +40,7 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,5) parse error Incomplete structured construct at or before this point in binding +(4,10)-(4,10) parse error Expecting type (7,0)-(7,0) parse error Unexpected end of input in value, function or member definition (4,4)-(4,7) parse error Incomplete value or function definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let' keyword. (4,4)-(4,7) parse error The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result. diff --git a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 06.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 06.fs.bsl index 618cbcfcee8..a6e663f076a 100644 --- a/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Typed - Missing type 06.fs.bsl @@ -36,3 +36,4 @@ ImplFile CodeComments = [] }, set [])) (4,11)-(4,12) parse error Unexpected symbol '=' in binding +(4,10)-(4,10) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs.bsl index a5ca5ea403f..c4ed5ee643f 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 14.fs.bsl @@ -65,3 +65,4 @@ ImplFile CodeComments = [] }, set [])) (4,19)-(4,20) parse error Unexpected symbol '=' in expression +(4,18)-(4,18) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs.bsl index e4db6014bf8..1a461ef4b3e 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 15.fs.bsl @@ -46,3 +46,4 @@ ImplFile CodeComments = [] }, set [])) (5,4)-(5,8) parse error Incomplete structured construct at or before this point in expression +(4,18)-(4,18) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs.bsl index 8faddfde7f5..5178a6c2714 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 16.fs.bsl @@ -10,3 +10,4 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,10) parse error Incomplete structured construct at or before this point in expression +(5,18)-(5,18) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs.bsl index 1e38d52d4e5..037d6651228 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang AndBang 18.fs.bsl @@ -66,3 +66,4 @@ ImplFile CodeComments = [] }, set [])) (5,19)-(5,20) parse error Unexpected symbol '=' in expression +(5,18)-(5,18) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs.bsl index 4b1410b5274..9042c097425 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 05.fs.bsl @@ -35,3 +35,4 @@ ImplFile CodeComments = [] }, set [])) (4,14)-(4,15) parse error Unexpected symbol '=' in expression +(4,13)-(4,13) parse error Expecting type diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs.bsl index 34b209cbdc7..dd99b50a61a 100644 --- a/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs.bsl +++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 06.fs.bsl @@ -10,3 +10,4 @@ ImplFile CodeComments = [] }, set [])) (5,4)-(5,10) parse error Incomplete structured construct at or before this point in expression +(4,13)-(4,13) parse error Expecting type From 58667ff1cedcaa9378878d4e8bc4c08a77f888a8 Mon Sep 17 00:00:00 2001 From: edgargonzalez Date: Mon, 14 Jul 2025 20:50:12 -0600 Subject: [PATCH 22/22] more tests --- .../SyntaxTree/SynType/Typed LetBang 17.fs | 5 ++ .../SynType/Typed LetBang 17.fs.bsl | 57 +++++++++++++++ .../SyntaxTree/SynType/Typed LetBang 18.fs | 5 ++ .../SynType/Typed LetBang 18.fs.bsl | 58 +++++++++++++++ .../SyntaxTree/SynType/Typed LetBang 19.fs | 7 ++ .../SynType/Typed LetBang 19.fs.bsl | 69 ++++++++++++++++++ .../SyntaxTree/SynType/Typed LetBang 20.fs | 7 ++ .../SynType/Typed LetBang 20.fs.bsl | 72 +++++++++++++++++++ 8 files changed, 280 insertions(+) create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 17.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 17.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 18.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 18.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 19.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 19.fs.bsl create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 20.fs create mode 100644 tests/service/data/SyntaxTree/SynType/Typed LetBang 20.fs.bsl diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 17.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 17.fs new file mode 100644 index 00000000000..3365fee1357 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 17.fs @@ -0,0 +1,5 @@ +module Module + +let (Even as x: int) = 1 + +let! (Even as x: int) = async { return 2 } \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 17.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 17.fs.bsl new file mode 100644 index 00000000000..6f78c27dca1 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 17.fs.bsl @@ -0,0 +1,57 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 17.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), + Paren + (Typed + (As + (LongIdent + (SynLongIdent ([Even], [], [None]), None, None, + Pats [], None, (3,5--3,9)), + Named (SynIdent (x, None), false, None, (3,13--3,14)), + (3,5--3,14)), + LongIdent (SynLongIdent ([int], [], [None])), + (3,5--3,19)), (3,4--3,20)), None, + Const (Int32 1, (3,23--3,24)), (3,4--3,20), Yes (3,0--3,24), + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,21--3,22) })], (3,0--3,24)); + Expr + (LetOrUseBang + (Yes (5,0--5,42), false, true, + Paren + (Typed + (As + (LongIdent + (SynLongIdent ([Even], [], [None]), None, None, + Pats [], None, (5,6--5,10)), + Named (SynIdent (x, None), false, None, (5,14--5,15)), + (5,6--5,15)), + LongIdent (SynLongIdent ([int], [], [None])), (5,6--5,20)), + (5,5--5,21)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 2, (5,39--5,40)), + (5,32--5,40), { YieldOrReturnKeyword = (5,32--5,38) }), + (5,30--5,42)), (5,24--5,42)), [], + ImplicitZero (5,42--5,42), (5,0--5,42), + { LetOrUseBangKeyword = (5,0--5,4) + EqualsRange = Some (5,22--5,23) }), (5,0--5,42))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,42), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,42) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 18.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 18.fs new file mode 100644 index 00000000000..05a94e21d04 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 18.fs @@ -0,0 +1,5 @@ +module Module + +let Even as x: int = 1 + +let! Even as x: int = async { return 2 } \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 18.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 18.fs.bsl new file mode 100644 index 00000000000..8579d42db13 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 18.fs.bsl @@ -0,0 +1,58 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 18.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), + As + (LongIdent + (SynLongIdent ([Even], [], [None]), None, None, Pats [], + None, (3,4--3,8)), + Named (SynIdent (x, None), false, None, (3,12--3,13)), + (3,4--3,13)), + Some + (SynBindingReturnInfo + (LongIdent (SynLongIdent ([int], [], [None])), + (3,15--3,18), [], { ColonRange = Some (3,13--3,14) })), + Typed + (Const (Int32 1, (3,21--3,22)), + LongIdent (SynLongIdent ([int], [], [None])), (3,21--3,22)), + (3,4--3,13), Yes (3,0--3,22), + { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,19--3,20) })], (3,0--3,22)); + Expr + (LetOrUseBang + (Yes (5,0--5,40), false, true, + Typed + (As + (LongIdent + (SynLongIdent ([Even], [], [None]), None, None, Pats [], + None, (5,5--5,9)), + Named (SynIdent (x, None), false, None, (5,13--5,14)), + (5,5--5,14)), + LongIdent (SynLongIdent ([int], [], [None])), (5,5--5,19)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 2, (5,37--5,38)), + (5,30--5,38), { YieldOrReturnKeyword = (5,30--5,36) }), + (5,28--5,40)), (5,22--5,40)), [], + ImplicitZero (5,40--5,40), (5,0--5,40), + { LetOrUseBangKeyword = (5,0--5,4) + EqualsRange = Some (5,20--5,21) }), (5,0--5,40))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--5,40), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) + +(5,0)-(5,40) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 19.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 19.fs new file mode 100644 index 00000000000..57c7276c7a4 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 19.fs @@ -0,0 +1,7 @@ +module Module + +async { + let (Even as x: int) = 1 + let! (Even as x: int) = async { return 2 } + return x +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 19.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 19.fs.bsl new file mode 100644 index 00000000000..4ccac506d64 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 19.fs.bsl @@ -0,0 +1,69 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 19.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUse + (false, false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, + SynValInfo ([], SynArgInfo ([], false, None)), + None), + Paren + (Typed + (As + (LongIdent + (SynLongIdent ([Even], [], [None]), None, + None, Pats [], None, (4,9--4,13)), + Named + (SynIdent (x, None), false, None, + (4,17--4,18)), (4,9--4,18)), + LongIdent (SynLongIdent ([int], [], [None])), + (4,9--4,23)), (4,8--4,24)), None, + Const (Int32 1, (4,27--4,28)), (4,8--4,24), + Yes (4,4--4,28), { LeadingKeyword = Let (4,4--4,7) + InlineKeyword = None + EqualsRange = Some (4,25--4,26) })], + LetOrUseBang + (Yes (5,4--5,46), false, true, + Paren + (Typed + (As + (LongIdent + (SynLongIdent ([Even], [], [None]), None, + None, Pats [], None, (5,10--5,14)), + Named + (SynIdent (x, None), false, None, + (5,18--5,19)), (5,10--5,19)), + LongIdent (SynLongIdent ([int], [], [None])), + (5,10--5,24)), (5,9--5,25)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 2, (5,43--5,44)), + (5,36--5,44), + { YieldOrReturnKeyword = (5,36--5,42) }), + (5,34--5,46)), (5,28--5,46)), [], + YieldOrReturn + ((false, true), Ident x, (6,4--6,12), + { YieldOrReturnKeyword = (6,4--6,10) }), + (5,4--6,12), { LetOrUseBangKeyword = (5,4--5,8) + EqualsRange = Some (5,26--5,27) }), + (4,4--6,12), { LetOrUseKeyword = (4,4--4,7) + InKeyword = None }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 20.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 20.fs new file mode 100644 index 00000000000..8f1eaac2989 --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 20.fs @@ -0,0 +1,7 @@ +module Module + +async { + let Even as x: int = 1 + let! Even as x: int = async { return 2 } + return x +} \ No newline at end of file diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 20.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 20.fs.bsl new file mode 100644 index 00000000000..e14813fde0c --- /dev/null +++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 20.fs.bsl @@ -0,0 +1,72 @@ +ImplFile + (ParsedImplFileInput + ("/root/SynType/Typed LetBang 20.fs", false, QualifiedNameOfFile Module, [], + [SynModuleOrNamespace + ([Module], false, NamedModule, + [Expr + (App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + LetOrUse + (false, false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, + SynValInfo ([], SynArgInfo ([], false, None)), + None), + As + (LongIdent + (SynLongIdent ([Even], [], [None]), None, None, + Pats [], None, (4,8--4,12)), + Named + (SynIdent (x, None), false, None, (4,16--4,17)), + (4,8--4,17)), + Some + (SynBindingReturnInfo + (LongIdent (SynLongIdent ([int], [], [None])), + (4,19--4,22), [], + { ColonRange = Some (4,17--4,18) })), + Typed + (Const (Int32 1, (4,25--4,26)), + LongIdent (SynLongIdent ([int], [], [None])), + (4,25--4,26)), (4,8--4,17), Yes (4,4--4,26), + { LeadingKeyword = Let (4,4--4,7) + InlineKeyword = None + EqualsRange = Some (4,23--4,24) })], + LetOrUseBang + (Yes (5,4--5,44), false, true, + Typed + (As + (LongIdent + (SynLongIdent ([Even], [], [None]), None, None, + Pats [], None, (5,9--5,13)), + Named + (SynIdent (x, None), false, None, (5,17--5,18)), + (5,9--5,18)), + LongIdent (SynLongIdent ([int], [], [None])), + (5,9--5,23)), + App + (NonAtomic, false, Ident async, + ComputationExpr + (false, + YieldOrReturn + ((false, true), Const (Int32 2, (5,41--5,42)), + (5,34--5,42), + { YieldOrReturnKeyword = (5,34--5,40) }), + (5,32--5,44)), (5,26--5,44)), [], + YieldOrReturn + ((false, true), Ident x, (6,4--6,12), + { YieldOrReturnKeyword = (6,4--6,10) }), + (5,4--6,12), { LetOrUseBangKeyword = (5,4--5,8) + EqualsRange = Some (5,24--5,25) }), + (4,4--6,12), { LetOrUseKeyword = (4,4--4,7) + InKeyword = None }), (3,6--7,1)), + (3,0--7,1)), (3,0--7,1))], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, + (1,0--7,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), + { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set []))