diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs index d328f6a310a6..6a8004431681 100644 --- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs @@ -1801,11 +1801,8 @@ let rec TryTranslateComputationExpression | SynExpr.LetOrUse( isUse = true bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr; debugPoint = spBind) ] - body = innerComp) -> - let mBind = - match spBind with - | DebugPointAtBinding.Yes m -> m - | _ -> rhsExpr.Range + body = innerComp + trivia = { LetOrUseKeyword = mBind }) -> if ceenv.isQuery then error (Error(FSComp.SR.tcUseMayNotBeUsedInQueries (), mBind)) diff --git a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs index b627eef29222..5f57d7da60f8 100644 --- a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs @@ -232,9 +232,10 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT // 'use x = expr in expr' | SynExpr.LetOrUse( isUse = true - bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr; debugPoint = spBind) ] + bindings = [ SynBinding(kind = SynBindingKind.Normal; headPat = pat; expr = rhsExpr) ] body = innerComp - range = wholeExprMark) -> + range = wholeExprMark + trivia = { LetOrUseKeyword = mBind }) -> let bindPatTy = NewInferenceType g let inputExprTy = NewInferenceType g @@ -252,11 +253,6 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT let envinner = { envinner with eIsControlFlow = true } tcSequenceExprBody envinner genOuterTy tpenv innerComp - let mBind = - match spBind with - | DebugPointAtBinding.Yes m -> m.NoteSourceConstruct(NotedSourceConstruct.Binding) - | _ -> inputExpr.Range - let inputExprMark = inputExpr.Range let matchv, matchExpr = diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index 22c27eeb9b0e..97ec34bdead7 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -1048,8 +1048,13 @@ let mkLocalBindings (mWhole, BindingSetPreAttrs(_, isRec, isUse, declsPreAttrs, None else Some mIn) + + let mLetOrUse = + match decls with + | SynBinding(trivia = trivia) :: _ -> trivia.LeadingKeyword.Range + | _ -> Range.Zero - SynExpr.LetOrUse(isRec, isUse, decls, body, mWhole, { InKeyword = mIn }) + SynExpr.LetOrUse(isRec, isUse, decls, body, mWhole, { LetOrUseKeyword = mLetOrUse ; InKeyword = mIn }) let mkDefnBindings (mWhole, BindingSetPreAttrs(_, isRec, isUse, declsPreAttrs, _bindingSetRange), attrs, vis, attrsm) = if isUse then diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs index 7e03572719e5..9bf1465c0104 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs @@ -85,10 +85,11 @@ type SynExprDotLambdaTrivia = [] type SynExprLetOrUseTrivia = { + LetOrUseKeyword: range InKeyword: range option } - static member Zero: SynExprLetOrUseTrivia = { InKeyword = None } + static member Zero: SynExprLetOrUseTrivia = { InKeyword = None; LetOrUseKeyword = Range.Zero } [] type SynExprLetOrUseBangTrivia = diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi index 3c678a726799..f12afad99fee 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi @@ -129,6 +129,8 @@ type SynExprDotLambdaTrivia = [] type SynExprLetOrUseTrivia = { + /// The syntax range of the `let` or `use` keyword. + LetOrUseKeyword: range /// The syntax range of the `in` keyword. InKeyword: range option } diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index 027ad51ee4c2..f2b5f576b138 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -442,4 +442,52 @@ query { |> shouldFail |> withDiagnostics [ (Error 3143, Line 4, Col 5, Line 4, Col 9, "'let!', 'use!' and 'do!' expressions may not be used in queries") - ] \ No newline at end of file + ] + + [] + let ``use expressions may not be used in queries(SynExpr.Sequential)`` () = + Fsx """ +let x11 = + query { for c in [1..10] do + use x = { new System.IDisposable with __.Dispose() = () } + yield 1 } + """ + |> ignoreWarnings + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3142, Line 4, Col 13, Line 4, Col 16, "'use' expressions may not be used in queries") + ] + + [] + let ``use, This control construct may only be used if the computation expression builder defines a 'Using' method`` () = + Fsx """ +module Result = + let zip x1 x2 = + match x1,x2 with + | Ok x1res, Ok x2res -> Ok (x1res, x2res) + | Error e, _ -> Error e + | _, Error e -> Error e + +type ResultBuilder() = + member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2 + member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x + + member _.YieldReturn(x: Result<'T,'U>) = x + member _.Return(x: 'T) = Ok x + +let result = ResultBuilder() + +let run r2 r3 = + result { + use b = r2 + return Ok 0 + } + """ + |> ignoreWarnings + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 708, Line 20, Col 9, Line 20, Col 12, "This control construct may only be used if the computation expression builder defines a 'Using' method") + ] + \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg61.bsl b/tests/fsharp/typecheck/sigs/neg61.bsl index 91291a6cb94b..014af35d598c 100644 --- a/tests/fsharp/typecheck/sigs/neg61.bsl +++ b/tests/fsharp/typecheck/sigs/neg61.bsl @@ -57,7 +57,7 @@ neg61.fs(79,13,79,16): typecheck error FS3146: 'try/with' expressions may not be neg61.fs(86,13,86,16): typecheck error FS3141: 'try/finally' expressions may not be used in queries -neg61.fs(92,13,92,70): typecheck error FS3142: 'use' expressions may not be used in queries +neg61.fs(92,13,92,15): typecheck error FS3142: 'use' expressions may not be used in queries neg61.fs(97,13,97,17): typecheck error FS3143: 'let!', 'use!' and 'do!' expressions may not be used in queries