Skip to content

Commit 3c3ccaf

Browse files
authored
Merge pull request #9421 from dotnet/merges/master-to-release/dev16.7
Merge master to release/dev16.7
2 parents f8fbef6 + cce16a4 commit 3c3ccaf

File tree

5 files changed

+172
-0
lines changed

5 files changed

+172
-0
lines changed

fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<Project Sdk="Microsoft.NET.Sdk">
33
<Import Project="..\netfx.props" />
44
<Import Project="..\..\src\buildtools\buildtools.targets" />
5+
<Import Project="..\..\eng\Versions.props" />
56
<PropertyGroup>
67
<TargetFrameworks>$(FcsTargetNetFxFramework);netstandard2.0</TargetFrameworks>
78
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>

src/fsharp/TypeChecker.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8884,6 +8884,7 @@ and TcComputationExpression cenv env overallTy mWhole (interpExpr: Expr) builder
88848884
clauses |> List.forall (fun (Clause(_, _, clauseComp, _, _)) -> isSimpleExpr clauseComp)
88858885
| SynExpr.YieldOrReturnFrom _ -> false
88868886
| SynExpr.YieldOrReturn _ -> false
8887+
| SynExpr.DoBang _ -> false
88878888
| _ -> true
88888889

88898890
let basicSynExpr =

tests/FSharp.TestHelpers/CompilerAssert.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ let main argv = 0"""
420420
static member ExecutionHasOutput(cmpl: Compilation, expectedOutput: string) =
421421
CompilerAssert.Execute(cmpl, newProcess = true, onOutput = (fun output -> Assert.AreEqual(expectedOutput, output)))
422422

423+
/// Assert that the given source code compiles with the `defaultProjectOptions`, with no errors or warnings
423424
static member Pass (source: string) =
424425
lock gate <| fun () ->
425426
let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, defaultProjectOptions) |> Async.RunSynchronously
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
namespace FSharp.Compiler.UnitTests
2+
3+
open NUnit.Framework
4+
open FSharp.TestHelpers
5+
open FSharp.Compiler.SourceCodeServices
6+
7+
[<TestFixture>]
8+
module ComputationExpressionTests =
9+
10+
[<Test>]
11+
let ``do-bang can be used with nested CE expressions``() =
12+
let code = """
13+
module Code
14+
type ResultBuilder() =
15+
member __.Return value = Ok value
16+
member __.ReturnFrom (result: Result<_,_>) = result
17+
member x.Zero() = x.Return ()
18+
member __.Bind(r: Result<'t,_>, binder: 't -> Result<_,_>) = match r with | Ok r' -> binder r' | Error e -> e
19+
member __.Delay(gen: unit -> Result<_,_>) = gen
20+
member __.Run(gen: unit -> Result<_,_>) = gen()
21+
member _.BindReturn(x: Result<'t,_>, f) = Result.map f x
22+
member inline _.Source(result : Result<_,_>) : Result<_,_> = result
23+
24+
let result = ResultBuilder()
25+
26+
module Result =
27+
let zip x1 x2 =
28+
match x1,x2 with
29+
| Ok x1res, Ok x2res -> Ok (x1res, x2res)
30+
| Error e, _ -> Error e
31+
| _, Error e -> Error e
32+
let ofChoice c =
33+
match c with
34+
| Choice1Of2 x -> Ok x
35+
| Choice2Of2 x -> Error x
36+
let fold onOk onError r =
37+
match r with
38+
| Ok x -> onOk x
39+
| Error y -> onError y
40+
41+
module Async =
42+
let inline singleton value = value |> async.Return
43+
let inline bind f x = async.Bind(x, f)
44+
let inline map f x = x |> bind (f >> singleton)
45+
let zip a1 a2 = async {
46+
let! r1 = a1
47+
let! r2 = a2
48+
return r1,r2
49+
}
50+
51+
module AsyncResult =
52+
let zip x1 x2 =
53+
Async.zip x1 x2
54+
|> Async.map(fun (r1, r2) -> Result.zip r1 r2)
55+
let foldResult onSuccess onError ar =
56+
Async.map (Result.fold onSuccess onError) ar
57+
58+
type AsyncResultBuilder() =
59+
60+
member __.Return (value: 'T) : Async<Result<'T, 'TError>> =
61+
async.Return <| result.Return value
62+
63+
member inline __.ReturnFrom
64+
(asyncResult: Async<Result<'T, 'TError>>)
65+
: Async<Result<'T, 'TError>> =
66+
asyncResult
67+
68+
member __.Zero () : Async<Result<unit, 'TError>> =
69+
async.Return <| result.Zero ()
70+
71+
member inline __.Bind
72+
(asyncResult: Async<Result<'T, 'TError>>,
73+
binder: 'T -> Async<Result<'U, 'TError>>)
74+
: Async<Result<'U, 'TError>> =
75+
async {
76+
let! result = asyncResult
77+
match result with
78+
| Ok x -> return! binder x
79+
| Error x -> return Error x
80+
}
81+
82+
member __.Delay
83+
(generator: unit -> Async<Result<'T, 'TError>>)
84+
: Async<Result<'T, 'TError>> =
85+
async.Delay generator
86+
87+
member this.Combine
88+
(computation1: Async<Result<unit, 'TError>>,
89+
computation2: Async<Result<'U, 'TError>>)
90+
: Async<Result<'U, 'TError>> =
91+
this.Bind(computation1, fun () -> computation2)
92+
93+
member __.TryWith
94+
(computation: Async<Result<'T, 'TError>>,
95+
handler: System.Exception -> Async<Result<'T, 'TError>>)
96+
: Async<Result<'T, 'TError>> =
97+
async.TryWith(computation, handler)
98+
99+
member __.TryFinally
100+
(computation: Async<Result<'T, 'TError>>,
101+
compensation: unit -> unit)
102+
: Async<Result<'T, 'TError>> =
103+
async.TryFinally(computation, compensation)
104+
105+
member __.Using
106+
(resource: 'T when 'T :> System.IDisposable,
107+
binder: 'T -> Async<Result<'U, 'TError>>)
108+
: Async<Result<'U, 'TError>> =
109+
async.Using(resource, binder)
110+
111+
member this.While
112+
(guard: unit -> bool, computation: Async<Result<unit, 'TError>>)
113+
: Async<Result<unit, 'TError>> =
114+
if not <| guard () then this.Zero ()
115+
else this.Bind(computation, fun () -> this.While (guard, computation))
116+
117+
member this.For
118+
(sequence: #seq<'T>, binder: 'T -> Async<Result<unit, 'TError>>)
119+
: Async<Result<unit, 'TError>> =
120+
this.Using(sequence.GetEnumerator (), fun enum ->
121+
this.While(enum.MoveNext,
122+
this.Delay(fun () -> binder enum.Current)))
123+
124+
member inline __.BindReturn(x: Async<Result<'T,'U>>, f) = async.Bind(x, fun r -> Result.map f r |> async.Return)
125+
member inline __.MergeSources(t1: Async<Result<'T,'U>>, t2: Async<Result<'T1,'U>>) =
126+
AsyncResult.zip t1 t2
127+
128+
member inline _.Source(result : Async<Result<_,_>>) : Async<Result<_,_>> = result
129+
130+
module ARExts =
131+
type AsyncResultBuilder with
132+
/// <summary>
133+
/// Needed to allow `for..in` and `for..do` functionality
134+
/// </summary>
135+
member inline __.Source(s: #seq<_>) = s
136+
137+
/// <summary>
138+
/// Method lets us transform data types into our internal representation.
139+
/// </summary>
140+
member inline _.Source(result : Result<_,_>) : Async<Result<_,_>> = Async.singleton result
141+
142+
/// <summary>
143+
/// Method lets us transform data types into our internal representation.
144+
/// </summary>
145+
member inline _.Source(choice : Choice<_,_>) : Async<Result<_,_>> =
146+
choice
147+
|> Result.ofChoice
148+
|> Async.singleton
149+
150+
/// <summary>
151+
/// Method lets us transform data types into our internal representation.
152+
/// </summary>
153+
member inline __.Source(asyncComputation : Async<_>) : Async<Result<_,_>> = asyncComputation |> Async.map Ok
154+
155+
let asyncResult = AsyncResultBuilder()
156+
157+
asyncResult {
158+
let! something = asyncResult { return 5 }
159+
do! asyncResult {
160+
return ()
161+
}
162+
return something
163+
}
164+
|> AsyncResult.foldResult id (fun (_err: string) -> 10)
165+
|> Async.RunSynchronously
166+
|> printfn "%d"
167+
"""
168+
CompilerAssert.Pass code

tests/fsharp/FSharpSuite.Tests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
<Compile Include="Compiler\Language\SpanOptimizationTests.fs" />
7373
<Compile Include="Compiler\Language\SpanTests.fs" />
7474
<Compile Include="Compiler\Language\StringConcatOptimizationTests.fs" />
75+
<Compile Include="Compiler\Language\ComputationExpressionTests.fs" />
7576
<Compile Include="Compiler\Stress\LargeExprTests.fs" />
7677
<Compile Include="Compiler\Regressions\IndexerRegressionTests.fs" />
7778
<Compile Include="Compiler\Regressions\ForInDoMutableRegressionTest.fs" />

0 commit comments

Comments
 (0)