diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md
new file mode 100644
index 00000000000..52228f33b09
--- /dev/null
+++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md
@@ -0,0 +1,3 @@
+### Fixed
+
+* Allow `let!` and `use!` type annotations without requiring parentheses ([PR #18508](https://github.com/dotnet/fsharp/pull/18508))
diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md
index 4a420016a14..40775e8dfa6 100644
--- a/docs/release-notes/.Language/preview.md
+++ b/docs/release-notes/.Language/preview.md
@@ -7,6 +7,7 @@
* Allow `_` in `use!` bindings values (lift FS1228 restriction) ([PR #18487](https://github.com/dotnet/fsharp/pull/18487))
* Warn when `unit` is passed to an `obj`-typed argument ([PR #18330](https://github.com/dotnet/fsharp/pull/18330))
* 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))
### Fixed
diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
index f861665a5fc..0d2404c5b1a 100644
--- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
@@ -1793,6 +1793,9 @@ let rec TryTranslateComputationExpression
let supportsUseBangBindingValueDiscard =
ceenv.cenv.g.langVersion.SupportsFeature LanguageFeature.UseBangBindingValueDiscard
+ let supportsTypedLetOrUseBang =
+ ceenv.cenv.g.langVersion.SupportsFeature LanguageFeature.AllowTypedLetOrUseBang
+
// use! x = ...
// use! (x) = ...
// use! (__) = ...
@@ -1802,6 +1805,7 @@ let rec TryTranslateComputationExpression
match pat with
| SynPat.Named(ident = SynIdent(id, _); isThisVal = false) -> id, pat
| SynPat.LongIdent(longDotId = SynLongIdent(id = [ id ])) -> id, pat
+ | SynPat.Typed(pat = pat) when supportsTypedLetOrUseBang -> extractIdentifierFromPattern pat
| SynPat.Wild(m) when supportsUseBangBindingValueDiscard ->
// To properly call the Using(disposable) CE member, we need to convert the wildcard to a SynPat.Named
let tmpIdent = mkSynId m "_"
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index 010088e958e..1d7e9d6499a 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -1800,6 +1800,7 @@ featureSupportValueOptionsAsOptionalParameters,"Support ValueOption as valid typ
featureSupportWarnWhenUnitPassedToObjArg,"Warn when unit is passed to a member accepting `obj` argument, e.g. `Method(o:obj)` will warn if called via `Method()`."
featureUseBangBindingValueDiscard,"Allows use! _ = ... in computation expressions"
featureScopedNowarn,"Support for scoped enabling / disabling of warnings by #warn and #nowarn directives, also inside modules"
+featureAllowLetOrUseBangTypeAnnotationWithoutParens,"Allow let! and use! type annotations without requiring parentheses"
3874,lexWarnDirectiveMustBeFirst,"#nowarn/#warnon directives must appear as the first non-whitespace characters on a line"
3875,lexWarnDirectiveMustHaveArgs,"Warn directives must have warning number(s) as argument(s)"
3876,lexWarnDirectivesMustMatch,"There is another %s for this warning already in line %d."
diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs
index 763452592a4..fd0f646531b 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fs
+++ b/src/Compiler/Facilities/LanguageFeatures.fs
@@ -101,6 +101,7 @@ type LanguageFeature =
| WarnWhenUnitPassedToObjArg
| UseBangBindingValueDiscard
| ScopedNowarn
+ | AllowTypedLetOrUseBang
/// LanguageVersion management
type LanguageVersion(versionText) =
@@ -233,6 +234,7 @@ type LanguageVersion(versionText) =
LanguageFeature.WarnWhenUnitPassedToObjArg, previewVersion
LanguageFeature.UseBangBindingValueDiscard, previewVersion
LanguageFeature.ScopedNowarn, previewVersion
+ LanguageFeature.AllowTypedLetOrUseBang, previewVersion
]
static let defaultLanguageVersion = LanguageVersion("default")
@@ -397,6 +399,7 @@ type LanguageVersion(versionText) =
| LanguageFeature.WarnWhenUnitPassedToObjArg -> FSComp.SR.featureSupportWarnWhenUnitPassedToObjArg ()
| LanguageFeature.UseBangBindingValueDiscard -> FSComp.SR.featureUseBangBindingValueDiscard ()
| LanguageFeature.ScopedNowarn -> FSComp.SR.featureScopedNowarn ()
+ | LanguageFeature.AllowTypedLetOrUseBang -> 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 a452205765e..95bd956e0b7 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fsi
+++ b/src/Compiler/Facilities/LanguageFeatures.fsi
@@ -92,6 +92,7 @@ type LanguageFeature =
| WarnWhenUnitPassedToObjArg
| UseBangBindingValueDiscard
| ScopedNowarn
+ | AllowTypedLetOrUseBang
/// LanguageVersion management
type LanguageVersion =
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index 7326c4a6a12..61f8e2fef86 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -4466,6 +4466,39 @@ declExpr:
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.AllowTypedLetOrUseBang 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.AllowTypedLetOrUseBang 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 spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range)
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index de5b2815fdc..caa825a8245 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index 53bf24ff3e9..2d193f09a0e 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index 483e820ed5c..1e0f79d0124 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index f003166db2d..71a14ff33f0 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index e4c08f83cb2..12f56c30e93 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index 7d56499a955..d84ecad7170 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index 887f0f199f1..39c3a728b37 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index 589e0f8535e..e5f2bda5529 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 5af5b7fcd34..c69f534b10e 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index e8747be3f5c..ca41d4affcc 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index a2d6e89305c..17a75ffa27c 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index fce23f29c9a..155480c6314 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index d2563922fc3..3c96310c8a7 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -287,6 +287,11 @@
Allow access modifiers to auto properties getters and setters
+
+ Allow let! and use! type annotations without requiring parentheses
+ Allow let! and use! type annotations without requiring parentheses
+
+
Allow object expressions without overrides
Allow object expressions without overrides
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBang05.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBang05.fs
new file mode 100644
index 00000000000..7bd2b4cd827
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBang05.fs
@@ -0,0 +1,58 @@
+open System
+
+open System
+
+type Disposable(id: int) =
+ static let mutable disposedIds = Set.empty
+ static let mutable constructedIds = Set.empty
+
+ do constructedIds <- constructedIds.Add(id)
+
+ member _.Id = id
+
+ static member GetDisposed() = disposedIds
+ static member GetConstructed() = constructedIds
+ static member Reset() =
+ disposedIds <- Set.empty
+ constructedIds <- Set.empty
+
+ interface IDisposable with
+ member this.Dispose() = disposedIds <- disposedIds.Add(this.Id)
+
+type DisposableBuilder() =
+ member _.Using(resource: #IDisposable, f) =
+ async {
+ use res = resource
+ return! f res
+ }
+
+ member _.Bind(disposable: Disposable, f) = async.Bind(async.Return(disposable), f)
+ member _.Return(x) = async.Return x
+ member _.ReturnFrom(x) = x
+ member _.Bind(task, f) = async.Bind(task, f)
+
+let counterDisposable = DisposableBuilder()
+
+let testBindingPatterns() =
+ Disposable.Reset()
+
+ counterDisposable {
+ use! res:IDisposable = new Disposable(1)
+ use! __:IDisposable = new Disposable(2)
+ use! (res1: IDisposable) = new Disposable(3)
+ use! _: IDisposable = new Disposable(4)
+ use! (_: IDisposable) = new Disposable(5)
+ return ()
+ } |> Async.RunSynchronously
+
+ let constructed = Disposable.GetConstructed()
+ let disposed = Disposable.GetDisposed()
+ let undisposed = constructed - disposed
+
+ if not undisposed.IsEmpty then
+ printfn $"Undisposed instances: %A{undisposed}"
+ failwithf "Not all disposables were properly disposed"
+ else
+ printfn $"Success! All %d{constructed.Count} disposables were properly disposed"
+
+testBindingPatterns()
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs
index ba0f31bd885..37c1447e89e 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBangBindings.fs
@@ -50,6 +50,19 @@ module UseBangBindingsVersion9 =
|> withDiagnostics [
(Error 1228, Line 47, Col 14, Line 47, Col 15, "'use!' bindings must be of the form 'use! = '")
]
+
+ []
+ let ``UseBangBindings - UseBang05_fs - Current LangVersion`` compilation =
+ compilation
+ |> asFsx
+ |> withLangVersion90
+ |> 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.")
+ ]
module UseBangBindingsPreview =
[]
@@ -83,4 +96,13 @@ module UseBangBindingsPreview =
|> withLangVersionPreview
|> compileAndRun
|> shouldSucceed
+
+ []
+ let ``UseBangBindings - UseBang05_fs - Preview LangVersion`` compilation =
+ compilation
+ |> asExe
+ |> withLangVersionPreview
+ |> compileAndRun
+ |> shouldSucceed
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBinding01.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBinding01.fs
new file mode 100644
index 00000000000..4fbe7575b3a
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBinding01.fs
@@ -0,0 +1,7 @@
+// #DeclarationElements #LetBindings
+//
+open System
+
+let answer =
+ use x:IDisposable = new System.IO.MemoryStream()
+ 42
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBinding02.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBinding02.fs
new file mode 100644
index 00000000000..be6cf7b8399
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBinding02.fs
@@ -0,0 +1,26 @@
+open System
+
+type private Disposable() =
+ [] static val mutable private disposedTimes: int
+ [] static val mutable private constructedTimes: int
+
+ do Disposable.constructedTimes <- Disposable.constructedTimes + 1
+
+ static member DisposeCallCount() = Disposable.disposedTimes
+ static member ConstructorCallCount() = Disposable.constructedTimes
+
+ interface System.IDisposable with
+ member _.Dispose() =
+ Disposable.disposedTimes <- Disposable.disposedTimes + 1
+
+let _scope =
+ use x: IDisposable = new Disposable()
+ ()
+
+let disposeCalls = Disposable.DisposeCallCount()
+if disposeCalls <> 1 then
+ failwith "was not disposed or disposed too many times"
+
+let ctorCalls = Disposable.ConstructorCallCount()
+if ctorCalls <> 1 then
+ failwithf "unexpected constructor call count: %i" ctorCalls
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBindingDiscard03.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBindingDiscard03.fs
new file mode 100644
index 00000000000..840870377fe
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBindingDiscard03.fs
@@ -0,0 +1,26 @@
+open System
+
+type private Disposable() =
+ [] static val mutable private disposedTimes: int
+ [] static val mutable private constructedTimes: int
+
+ do Disposable.constructedTimes <- Disposable.constructedTimes + 1
+
+ static member DisposeCallCount() = Disposable.disposedTimes
+ static member ConstructorCallCount() = Disposable.constructedTimes
+
+ interface System.IDisposable with
+ member _.Dispose() =
+ Disposable.disposedTimes <- Disposable.disposedTimes + 1
+
+let _scope =
+ use _:IDisposable = new Disposable()
+ ()
+
+let disposeCalls = Disposable.DisposeCallCount()
+if disposeCalls <> 1 then
+ failwith "was not disposed or disposed too many times"
+
+let ctorCalls = Disposable.ConstructorCallCount()
+if ctorCalls <> 1 then
+ failwithf "unexpected constructor call count: %i" ctorCalls
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBindings.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBindings.fs
index 74137286a8a..b1e08869312 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBindings.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/UseBindings/UseBindings.fs
@@ -33,4 +33,25 @@ module UseBindings =
|> asExe
|> withLangVersion60
|> compileAndRun
- |> shouldSucceed
\ No newline at end of file
+ |> shouldSucceed
+
+ []
+ let ``UseBindings - UseBindingDiscard03_fs - Current LangVersion`` compilation =
+ compilation
+ |> asExe
+ |> compileAndRun
+ |> shouldSucceed
+
+ []
+ let ``UseBindings - UseBinding01_fs - Current LangVersion`` compilation =
+ compilation
+ |> asFsx
+ |> compile
+ |> shouldSucceed
+
+ []
+ let ``UseBindings - UseBinding02_fs - Current LangVersion`` compilation =
+ compilation
+ |> asFsx
+ |> compile
+ |> shouldSucceed
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 01.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 01.fs
new file mode 100644
index 00000000000..f191f7aee2b
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 01.fs
@@ -0,0 +1,6 @@
+module Module
+
+async {
+ let! res: int = async { return 1 }
+ return res
+}
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 01.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 01.fs.bsl
new file mode 100644
index 00000000000..1aa552d5f05
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 01.fs.bsl
@@ -0,0 +1,36 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed LetBang 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)), [],
+ 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,18--4,19) }), (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 []))
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 02.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 02.fs
new file mode 100644
index 00000000000..4d58841b1d6
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 02.fs
@@ -0,0 +1,6 @@
+module Module
+
+async {
+ let! (res: int) = async { return 1 }
+ return res
+}
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 02.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 02.fs.bsl
new file mode 100644
index 00000000000..6046708ca7f
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 02.fs.bsl
@@ -0,0 +1,38 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed LetBang 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)), [],
+ 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,20--4,21) }), (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 []))
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 03.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 03.fs
new file mode 100644
index 00000000000..5c5e72047cc
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 03.fs
@@ -0,0 +1,7 @@
+module Module
+
+async {
+ let (a: int, b: int) = 1, 3
+ let! (c: int, d: int) = async { return 1, 3 }
+ return a + b + c + d
+}
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 03.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 03.fs.bsl
new file mode 100644
index 00000000000..c065ea59e32
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 03.fs.bsl
@@ -0,0 +1,125 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed LetBang 03.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
+ (Tuple
+ (false,
+ [Typed
+ (Named
+ (SynIdent (a, None), false, None,
+ (4,9--4,10)),
+ LongIdent
+ (SynLongIdent ([int], [], [None])),
+ (4,9--4,15));
+ Typed
+ (Named
+ (SynIdent (b, None), false, None,
+ (4,17--4,18)),
+ LongIdent
+ (SynLongIdent ([int], [], [None])),
+ (4,17--4,23))], [(4,15--4,16)], (4,9--4,23)),
+ (4,8--4,24)), None,
+ Tuple
+ (false,
+ [Const (Int32 1, (4,27--4,28));
+ Const (Int32 3, (4,30--4,31))], [(4,28--4,29)],
+ (4,27--4,31)), (4,8--4,24), Yes (4,4--4,31),
+ { LeadingKeyword = Let (4,4--4,7)
+ InlineKeyword = None
+ EqualsRange = Some (4,25--4,26) })],
+ LetOrUseBang
+ (Yes (5,4--5,49), false, true,
+ Paren
+ (Tuple
+ (false,
+ [Typed
+ (Named
+ (SynIdent (c, None), false, None,
+ (5,10--5,11)),
+ LongIdent (SynLongIdent ([int], [], [None])),
+ (5,10--5,16));
+ Typed
+ (Named
+ (SynIdent (d, 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
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true),
+ Tuple
+ (false,
+ [Const (Int32 1, (5,43--5,44));
+ Const (Int32 3, (5,46--5,47))],
+ [(5,44--5,45)], (5,43--5,47)),
+ (5,36--5,47),
+ { YieldOrReturnKeyword = (5,36--5,42) }),
+ (5,34--5,49)), (5,28--5,49)), [],
+ YieldOrReturn
+ ((false, true),
+ App
+ (NonAtomic, false,
+ App
+ (NonAtomic, true,
+ LongIdent
+ (false,
+ SynLongIdent
+ ([op_Addition], [],
+ [Some (OriginalNotation "+")]), None,
+ (6,21--6,22)),
+ App
+ (NonAtomic, false,
+ App
+ (NonAtomic, true,
+ LongIdent
+ (false,
+ SynLongIdent
+ ([op_Addition], [],
+ [Some (OriginalNotation "+")]),
+ None, (6,17--6,18)),
+ App
+ (NonAtomic, false,
+ App
+ (NonAtomic, true,
+ LongIdent
+ (false,
+ SynLongIdent
+ ([op_Addition], [],
+ [Some
+ (OriginalNotation "+")]),
+ None, (6,13--6,14)), Ident a,
+ (6,11--6,14)), Ident b,
+ (6,11--6,16)), (6,11--6,18)),
+ Ident c, (6,11--6,20)), (6,11--6,22)),
+ Ident d, (6,11--6,24)), (6,4--6,24),
+ { YieldOrReturnKeyword = (6,4--6,10) }),
+ (5,4--6,24), { LetOrUseBangKeyword = (5,4--5,8)
+ EqualsRange = Some (5,26--5,27) }),
+ (4,4--6,24), { 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 04.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 04.fs
new file mode 100644
index 00000000000..2a1e0319849
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 04.fs
@@ -0,0 +1,7 @@
+module Module
+
+async {
+ let a: int, b: int = 1, 3
+ let! c: int, d: int = async { return 1, 3 }
+ return a + b + c + d
+}
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 04.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 04.fs.bsl
new file mode 100644
index 00000000000..fc39d00e0a5
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 04.fs.bsl
@@ -0,0 +1,51 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed LetBang 04.fs", false, QualifiedNameOfFile Module, [],
+ [SynModuleOrNamespace
+ ([Module], false, NamedModule,
+ [Expr
+ (App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ Tuple
+ (false,
+ [LetOrUse
+ (false, false,
+ [SynBinding
+ (None, Normal, false, false, [],
+ PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
+ SynValData
+ (None,
+ SynValInfo ([], SynArgInfo ([], false, None)),
+ None),
+ Named
+ (SynIdent (a, None), false, None, (4,8--4,9)),
+ Some
+ (SynBindingReturnInfo
+ (LongIdent
+ (SynLongIdent ([int], [], [None])),
+ (4,11--4,14), [],
+ { ColonRange = Some (4,9--4,10) })),
+ Typed
+ (ArbitraryAfterError
+ ("localBinding2", (4,14--4,14)),
+ LongIdent (SynLongIdent ([int], [], [None])),
+ (4,14--4,14)), (4,8--4,9), Yes (4,4--4,14),
+ { LeadingKeyword = Let (4,4--4,7)
+ InlineKeyword = None
+ EqualsRange = None })],
+ ArbitraryAfterError ("declExpr3", (5,15--5,16)),
+ (4,4--5,16), { LetOrUseKeyword = (4,4--4,7)
+ InKeyword = None }); Ident d],
+ [(5,15--5,16)], (4,4--5,18)), (3,6--5,47)), (3,0--5,47)),
+ (3,0--5,47))],
+ PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+ (1,0--5,47), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+ { ConditionalDirectives = []
+ WarnDirectives = []
+ CodeComments = [] }, set []))
+
+(4,14)-(4,15) parse error Unexpected symbol ',' in binding. Expected '=' or other token.
+(5,15)-(5,16) parse error Unexpected symbol ',' in expression. Expected '=' or other token.
+(6,4)-(6,10) parse error Incomplete structured construct at or before this point in implementation file
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 05.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 05.fs
new file mode 100644
index 00000000000..be48e42bb81
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 05.fs
@@ -0,0 +1,3 @@
+module Module
+let! x:int = async { return 1 }
+let! (y:int) = async { return 2 }
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 05.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 05.fs.bsl
new file mode 100644
index 00000000000..08008766b4d
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 05.fs.bsl
@@ -0,0 +1,47 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed LetBang 05.fs", false, QualifiedNameOfFile Module, [],
+ [SynModuleOrNamespace
+ ([Module], false, NamedModule,
+ [Expr
+ (LetOrUseBang
+ (Yes (2,0--2,31), false, true,
+ Typed
+ (Named (SynIdent (x, None), false, None, (2,5--2,6)),
+ LongIdent (SynLongIdent ([int], [], [None])), (2,5--2,10)),
+ App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true), Const (Int32 1, (2,28--2,29)),
+ (2,21--2,29), { YieldOrReturnKeyword = (2,21--2,27) }),
+ (2,19--2,31)), (2,13--2,31)), [],
+ LetOrUseBang
+ (Yes (3,0--3,33), false, true,
+ Paren
+ (Typed
+ (Named (SynIdent (y, None), false, None, (3,6--3,7)),
+ LongIdent (SynLongIdent ([int], [], [None])),
+ (3,6--3,11)), (3,5--3,12)),
+ App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true), Const (Int32 2, (3,30--3,31)),
+ (3,23--3,31),
+ { YieldOrReturnKeyword = (3,23--3,29) }),
+ (3,21--3,33)), (3,15--3,33)), [],
+ ImplicitZero (3,33--3,33), (3,0--3,33),
+ { LetOrUseBangKeyword = (3,0--3,4)
+ EqualsRange = Some (3,13--3,14) }), (2,0--3,33),
+ { LetOrUseBangKeyword = (2,0--2,4)
+ EqualsRange = Some (2,11--2,12) }), (2,0--3,33))],
+ PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+ (1,0--3,33), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+ { ConditionalDirectives = []
+ WarnDirectives = []
+ CodeComments = [] }, set []))
+
+(3,0)-(3,33) parse error Incomplete structured construct at or before this point in expression
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 06.fs b/tests/service/data/SyntaxTree/SynType/Typed LetBang 06.fs
new file mode 100644
index 00000000000..4dfb5dcf98a
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 06.fs
@@ -0,0 +1,3 @@
+module Module
+let! _:int = async { return 1 }
+let! (_:int) = async { return 2 }
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/SynType/Typed LetBang 06.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed LetBang 06.fs.bsl
new file mode 100644
index 00000000000..591ef048599
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed LetBang 06.fs.bsl
@@ -0,0 +1,47 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed LetBang 06.fs", false, QualifiedNameOfFile Module, [],
+ [SynModuleOrNamespace
+ ([Module], false, NamedModule,
+ [Expr
+ (LetOrUseBang
+ (Yes (2,0--2,31), false, true,
+ Typed
+ (Wild (2,5--2,6),
+ LongIdent (SynLongIdent ([int], [], [None])), (2,5--2,10)),
+ App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true), Const (Int32 1, (2,28--2,29)),
+ (2,21--2,29), { YieldOrReturnKeyword = (2,21--2,27) }),
+ (2,19--2,31)), (2,13--2,31)), [],
+ LetOrUseBang
+ (Yes (3,0--3,33), false, true,
+ Paren
+ (Typed
+ (Wild (3,6--3,7),
+ LongIdent (SynLongIdent ([int], [], [None])),
+ (3,6--3,11)), (3,5--3,12)),
+ App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true), Const (Int32 2, (3,30--3,31)),
+ (3,23--3,31),
+ { YieldOrReturnKeyword = (3,23--3,29) }),
+ (3,21--3,33)), (3,15--3,33)), [],
+ ImplicitZero (3,33--3,33), (3,0--3,33),
+ { LetOrUseBangKeyword = (3,0--3,4)
+ EqualsRange = Some (3,13--3,14) }), (2,0--3,33),
+ { LetOrUseBangKeyword = (2,0--2,4)
+ EqualsRange = Some (2,11--2,12) }), (2,0--3,33))],
+ PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+ (1,0--3,33), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+ { ConditionalDirectives = []
+ WarnDirectives = []
+ CodeComments = [] }, set []))
+
+(3,0)-(3,33) parse error Incomplete structured construct at or before this point in expression
diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 01.fs b/tests/service/data/SyntaxTree/SynType/Typed UseBang 01.fs
new file mode 100644
index 00000000000..840c1678319
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 01.fs
@@ -0,0 +1,6 @@
+module Module
+
+async {
+ use! res: int = async { return 1 }
+ return res
+}
diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 01.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed UseBang 01.fs.bsl
new file mode 100644
index 00000000000..a49e9a4abf3
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 01.fs.bsl
@@ -0,0 +1,36 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed UseBang 01.fs", false, QualifiedNameOfFile Module, [],
+ [SynModuleOrNamespace
+ ([Module], false, NamedModule,
+ [Expr
+ (App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ LetOrUseBang
+ (Yes (4,4--4,38), true, 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)), [],
+ 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,18--4,19) }), (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 []))
diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 02.fs b/tests/service/data/SyntaxTree/SynType/Typed UseBang 02.fs
new file mode 100644
index 00000000000..cf1f75dc46c
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 02.fs
@@ -0,0 +1,6 @@
+module Module
+
+async {
+ use! (res: int) = async { return 1 }
+ return res
+}
diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 02.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed UseBang 02.fs.bsl
new file mode 100644
index 00000000000..d402cdf754d
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 02.fs.bsl
@@ -0,0 +1,38 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed UseBang 02.fs", false, QualifiedNameOfFile Module, [],
+ [SynModuleOrNamespace
+ ([Module], false, NamedModule,
+ [Expr
+ (App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ LetOrUseBang
+ (Yes (4,4--4,40), true, 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)), [],
+ 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,20--4,21) }), (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 []))
diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 03.fs b/tests/service/data/SyntaxTree/SynType/Typed UseBang 03.fs
new file mode 100644
index 00000000000..c0f2a3eb394
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 03.fs
@@ -0,0 +1,4 @@
+module Module
+
+use! x:int = async { return 1 }
+use! (y:int) = async { return 2 }
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 03.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed UseBang 03.fs.bsl
new file mode 100644
index 00000000000..a3eda56c6e0
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 03.fs.bsl
@@ -0,0 +1,47 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed UseBang 03.fs", false, QualifiedNameOfFile Module, [],
+ [SynModuleOrNamespace
+ ([Module], false, NamedModule,
+ [Expr
+ (LetOrUseBang
+ (Yes (3,0--3,31), true, true,
+ Typed
+ (Named (SynIdent (x, None), false, None, (3,5--3,6)),
+ LongIdent (SynLongIdent ([int], [], [None])), (3,5--3,10)),
+ App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true), Const (Int32 1, (3,28--3,29)),
+ (3,21--3,29), { YieldOrReturnKeyword = (3,21--3,27) }),
+ (3,19--3,31)), (3,13--3,31)), [],
+ LetOrUseBang
+ (Yes (4,0--4,33), true, true,
+ Paren
+ (Typed
+ (Named (SynIdent (y, None), false, None, (4,6--4,7)),
+ LongIdent (SynLongIdent ([int], [], [None])),
+ (4,6--4,11)), (4,5--4,12)),
+ App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true), Const (Int32 2, (4,30--4,31)),
+ (4,23--4,31),
+ { YieldOrReturnKeyword = (4,23--4,29) }),
+ (4,21--4,33)), (4,15--4,33)), [],
+ ImplicitZero (4,33--4,33), (4,0--4,33),
+ { LetOrUseBangKeyword = (4,0--4,4)
+ EqualsRange = Some (4,13--4,14) }), (3,0--4,33),
+ { LetOrUseBangKeyword = (3,0--3,4)
+ EqualsRange = Some (3,11--3,12) }), (3,0--4,33))],
+ PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+ (1,0--4,33), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+ { ConditionalDirectives = []
+ WarnDirectives = []
+ CodeComments = [] }, set []))
+
+(4,0)-(4,33) parse error Incomplete structured construct at or before this point in expression
diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 04.fs b/tests/service/data/SyntaxTree/SynType/Typed UseBang 04.fs
new file mode 100644
index 00000000000..9ef3a6a3665
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 04.fs
@@ -0,0 +1,4 @@
+module Module
+
+use! _:int = async { return 1 }
+use! (_:int) = async { return 2 }
\ No newline at end of file
diff --git a/tests/service/data/SyntaxTree/SynType/Typed UseBang 04.fs.bsl b/tests/service/data/SyntaxTree/SynType/Typed UseBang 04.fs.bsl
new file mode 100644
index 00000000000..3bf8a0ce44c
--- /dev/null
+++ b/tests/service/data/SyntaxTree/SynType/Typed UseBang 04.fs.bsl
@@ -0,0 +1,47 @@
+ImplFile
+ (ParsedImplFileInput
+ ("/root/SynType/Typed UseBang 04.fs", false, QualifiedNameOfFile Module, [],
+ [SynModuleOrNamespace
+ ([Module], false, NamedModule,
+ [Expr
+ (LetOrUseBang
+ (Yes (3,0--3,31), true, true,
+ Typed
+ (Wild (3,5--3,6),
+ LongIdent (SynLongIdent ([int], [], [None])), (3,5--3,10)),
+ App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true), Const (Int32 1, (3,28--3,29)),
+ (3,21--3,29), { YieldOrReturnKeyword = (3,21--3,27) }),
+ (3,19--3,31)), (3,13--3,31)), [],
+ LetOrUseBang
+ (Yes (4,0--4,33), true, true,
+ Paren
+ (Typed
+ (Wild (4,6--4,7),
+ LongIdent (SynLongIdent ([int], [], [None])),
+ (4,6--4,11)), (4,5--4,12)),
+ App
+ (NonAtomic, false, Ident async,
+ ComputationExpr
+ (false,
+ YieldOrReturn
+ ((false, true), Const (Int32 2, (4,30--4,31)),
+ (4,23--4,31),
+ { YieldOrReturnKeyword = (4,23--4,29) }),
+ (4,21--4,33)), (4,15--4,33)), [],
+ ImplicitZero (4,33--4,33), (4,0--4,33),
+ { LetOrUseBangKeyword = (4,0--4,4)
+ EqualsRange = Some (4,13--4,14) }), (3,0--4,33),
+ { LetOrUseBangKeyword = (3,0--3,4)
+ EqualsRange = Some (3,11--3,12) }), (3,0--4,33))],
+ PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
+ (1,0--4,33), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
+ { ConditionalDirectives = []
+ WarnDirectives = []
+ CodeComments = [] }, set []))
+
+(4,0)-(4,33) parse error Incomplete structured construct at or before this point in expression