Better error reporting for `CE` `do!` (#17779)

* Better error reporting for `CE` do bang

* Use SynExpr.DoBang

* update surface area

* format code

* release notes

* update tests

* Remove no intended case
This commit is contained in:
Edgar Gonzalez 2024-09-25 12:24:12 +01:00 коммит произвёл GitHub
Родитель cd736c4959
Коммит 6cdcc3c33c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
19 изменённых файлов: 53 добавлений и 24 удалений

Просмотреть файл

@ -8,5 +8,6 @@
* Make ILTypeDef interface impls calculation lazy. ([PR #17392](https://github.com/dotnet/fsharp/pull/17392))
* Better ranges for CE `let!` and `use!` error reporting. ([PR #17712](https://github.com/dotnet/fsharp/pull/17712))
* Better ranges for CE `do!` error reporting. ([PR #17779](https://github.com/dotnet/fsharp/pull/17779))
### Breaking Changes

Просмотреть файл

@ -1592,7 +1592,7 @@ let rec TryTranslateComputationExpression
if ceenv.isQuery && not (innerComp1.IsArbExprAndThusAlreadyReportedError) then
match innerComp1 with
| SynExpr.JoinIn _ -> ()
| SynExpr.DoBang(range = m) -> errorR (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), m))
| SynExpr.DoBang(trivia = { DoBangKeyword = m }) -> errorR (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), m))
| _ -> errorR (Error(FSComp.SR.tcUnrecognizedQueryOperator (), innerComp1.RangeOfFirstPortion))
match
@ -1657,7 +1657,7 @@ let rec TryTranslateComputationExpression
| None ->
// "do! expr; cexpr" is treated as { let! () = expr in cexpr }
match innerComp1 with
| SynExpr.DoBang(rhsExpr, m) ->
| SynExpr.DoBang(expr = rhsExpr; range = m) ->
let sp =
match sp with
| DebugPointAtSequential.SuppressExpr -> DebugPointAtBinding.NoneAtDo
@ -2867,7 +2867,7 @@ and TranslateComputationExpression (ceenv: ComputationExpressionContext<'a>) fir
// This only occurs in final position in a sequence
match comp with
// "do! expr;" in final position is treated as { let! () = expr in return () } when Return is provided (and no Zero with Default attribute is available) or as { let! () = expr in zero } otherwise
| SynExpr.DoBang(rhsExpr, m) ->
| SynExpr.DoBang(expr = rhsExpr; trivia = { DoBangKeyword = m }) ->
let mUnit = rhsExpr.Range
let rhsExpr = mkSourceExpr rhsExpr ceenv.sourceMethInfo ceenv.builderValName

Просмотреть файл

@ -6003,10 +6003,10 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
| SynExpr.ImplicitZero m ->
error(Error(FSComp.SR.tcConstructRequiresSequenceOrComputations(), m))
| SynExpr.DoBang (_, m)
| SynExpr.DoBang (trivia = { DoBangKeyword = m })
| SynExpr.MatchBang (range = m)
| SynExpr.WhileBang (range = m)
| SynExpr.LetOrUseBang (range = m) ->
| SynExpr.LetOrUseBang (trivia = { LetOrUseBangKeyword = m }) ->
error(Error(FSComp.SR.tcConstructRequiresComputationExpression(), m))
| SynExpr.IndexFromEnd (rightExpr, m) ->

Просмотреть файл

@ -168,7 +168,7 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT
| SynExpr.ImplicitZero m -> Some(mkSeqEmpty cenv env m genOuterTy, tpenv)
| SynExpr.DoBang(_rhsExpr, m) -> error (Error(FSComp.SR.tcDoBangIllegalInSequenceExpression (), m))
| SynExpr.DoBang(trivia = { DoBangKeyword = m }) -> error (Error(FSComp.SR.tcDoBangIllegalInSequenceExpression (), m))
| SynExpr.Sequential(sp, true, innerComp1, innerComp2, m, _) ->
let env1 =

Просмотреть файл

@ -523,7 +523,7 @@ let visitSynExpr (e: SynExpr) : FileContentEntry list =
visit expr (fun exprNodes ->
[ yield! exprNodes; yield! List.collect visitSynMatchClause clauses ]
|> continuation)
| SynExpr.DoBang(expr, _) -> visit expr continuation
| SynExpr.DoBang(expr = expr) -> visit expr continuation
| SynExpr.WhileBang(whileExpr = whileExpr; doExpr = doExpr) ->
visit whileExpr (fun whileNodes -> visit doExpr (fun doNodes -> whileNodes @ doNodes |> continuation))
| SynExpr.LibraryOnlyILAssembly(typeArgs = typeArgs; args = args; retTy = retTy) ->

Просмотреть файл

@ -578,7 +578,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
yield! walkExpr false e
| SynExpr.YieldOrReturnFrom(_, e, _)
| SynExpr.DoBang(e, _) ->
| SynExpr.DoBang(expr = e) ->
yield! checkRange e.Range
yield! walkExpr false e

Просмотреть файл

@ -952,9 +952,9 @@ module InterfaceStubGenerator =
| SynExpr.Null _range
| SynExpr.ImplicitZero _range -> None
| SynExpr.YieldOrReturn(_, synExpr, _range)
| SynExpr.YieldOrReturnFrom(_, synExpr, _range)
| SynExpr.DoBang(synExpr, _range) -> walkExpr synExpr
| SynExpr.YieldOrReturn(expr = synExpr)
| SynExpr.YieldOrReturnFrom(expr = synExpr)
| SynExpr.DoBang(expr = synExpr) -> walkExpr synExpr
| SynExpr.LetOrUseBang(rhs = synExpr1; andBangs = synExprAndBangs; body = synExpr2) ->
[

Просмотреть файл

@ -254,7 +254,7 @@ module Structure =
rcheck Scope.YieldOrReturnBang Collapse.Below r r
parseExpr e
| SynExpr.DoBang(e, r) ->
| SynExpr.DoBang(expr = e; range = r) ->
rcheck Scope.Do Collapse.Below r <| Range.modStart 3 r
parseExpr e

Просмотреть файл

@ -726,7 +726,7 @@ type SynExpr =
range: range *
trivia: SynExprMatchBangTrivia
| DoBang of expr: SynExpr * range: range
| DoBang of expr: SynExpr * range: range * trivia: SynExprDoBangTrivia
| WhileBang of whileDebugPoint: DebugPointAtWhile * whileExpr: SynExpr * doExpr: SynExpr * range: range

Просмотреть файл

@ -909,7 +909,7 @@ type SynExpr =
/// F# syntax: do! expr
/// Computation expressions only
| DoBang of expr: SynExpr * range: range
| DoBang of expr: SynExpr * range: range * trivia: SynExprDoBangTrivia
/// F# syntax: 'while! ... do ...'
| WhileBang of whileDebugPoint: DebugPointAtWhile * whileExpr: SynExpr * doExpr: SynExpr * range: range

Просмотреть файл

@ -885,7 +885,7 @@ let rec synExprContainsError inpExpr =
| SynExpr.TraitCall(_, _, e, _)
| SynExpr.YieldOrReturn(_, e, _)
| SynExpr.YieldOrReturnFrom(_, e, _)
| SynExpr.DoBang(e, _)
| SynExpr.DoBang(e, _, _)
| SynExpr.Fixed(e, _)
| SynExpr.DebugPoint(_, _, e)
| SynExpr.Paren(e, _, _, _) -> walkExpr e

Просмотреть файл

@ -117,6 +117,9 @@ type SynExprMatchBangTrivia =
WithKeyword: range
}
[<NoEquality; NoComparison>]
type SynExprDoBangTrivia = { DoBangKeyword: range }
[<NoEquality; NoComparison>]
type SynExprAnonRecdTrivia = { OpeningBraceRange: range }

Просмотреть файл

@ -169,6 +169,14 @@ type SynExprMatchBangTrivia =
WithKeyword: range
}
/// Represents additional information for SynExpr.DoBang
[<NoEquality; NoComparison>]
type SynExprDoBangTrivia =
{
/// The syntax range of the `do!` keyword
DoBangKeyword: range
}
/// Represents additional information for SynExpr.AnonRecd
[<NoEquality; NoComparison>]
type SynExprAnonRecdTrivia =

Просмотреть файл

@ -4442,11 +4442,14 @@ declExpr:
| DO_BANG typedSequentialExpr IN opt_OBLOCKSEP typedSequentialExprBlock %prec expr_let
{ let spBind = DebugPointAtBinding.NoneAtDo
let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = Range.Zero; EqualsRange = None }
SynExpr.LetOrUseBang(spBind, false, true, SynPat.Const(SynConst.Unit, $2.Range), $2, [], $5, unionRanges (rhs parseState 1) $5.Range, trivia) }
let trivia: SynExprDoBangTrivia = { DoBangKeyword = rhs parseState 1 }
let m = unionRanges (rhs parseState 1) $5.Range
SynExpr.DoBang($2, m, trivia) }
| ODO_BANG typedSequentialExprBlock hardwhiteDefnBindingsTerminator %prec expr_let
{ SynExpr.DoBang($2, unionRanges (rhs parseState 1) $2.Range) }
{ let trivia: SynExprDoBangTrivia = { DoBangKeyword = rhs parseState 1 }
let m = unionRanges (rhs parseState 1) $2.Range
SynExpr.DoBang($2, m, trivia) }
| FIXED declExpr
{ SynExpr.Fixed($2, (unionRanges (rhs parseState 1) $2.Range)) }

Просмотреть файл

@ -330,7 +330,7 @@ query {
|> typecheck
|> shouldFail
|> withDiagnostics [
(Error 3143, Line 3, Col 5, Line 3, Col 20, "'let!', 'use!' and 'do!' expressions may not be used in queries")
(Error 3143, Line 3, Col 5, Line 3, Col 8, "'let!', 'use!' and 'do!' expressions may not be used in queries")
]
[<Fact>]
@ -392,7 +392,7 @@ query {
|> typecheck
|> shouldFail
|> withDiagnostics [
(Error 3143, Line 4, Col 5, Line 4, Col 20, "'let!', 'use!' and 'do!' expressions may not be used in queries")
(Error 3143, Line 4, Col 5, Line 4, Col 8, "'let!', 'use!' and 'do!' expressions may not be used in queries")
]
[<Fact>]

Просмотреть файл

@ -7606,7 +7606,13 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewConst(FSharp.C
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDebugPoint(FSharp.Compiler.Syntax.DebugPointAtLeafExpr, Boolean, FSharp.Compiler.Syntax.SynExpr)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDiscardAfterMissingQualificationAfterDot(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDo(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDoBang(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr+DoBang: FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia get_trivia()
FSharp.Compiler.Syntax.SynExpr+DoBang: FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia trivia
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDoBang(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia)
FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia: FSharp.Compiler.Text.Range DoBangKeyword
FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia: FSharp.Compiler.Text.Range get_DoBangKeyword()
FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia: System.String ToString()
FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia: Void .ctor(FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDotGet(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynLongIdent, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDotIndexedGet(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDotIndexedSet(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range)

Просмотреть файл

@ -7606,7 +7606,13 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewConst(FSharp.C
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDebugPoint(FSharp.Compiler.Syntax.DebugPointAtLeafExpr, Boolean, FSharp.Compiler.Syntax.SynExpr)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDiscardAfterMissingQualificationAfterDot(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDo(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDoBang(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr+DoBang: FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia get_trivia()
FSharp.Compiler.Syntax.SynExpr+DoBang: FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia trivia
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDoBang(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia)
FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia: FSharp.Compiler.Text.Range DoBangKeyword
FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia: FSharp.Compiler.Text.Range get_DoBangKeyword()
FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia: System.String ToString()
FSharp.Compiler.SyntaxTrivia.SynExprDoBangTrivia: Void .ctor(FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDotGet(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynLongIdent, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDotIndexedGet(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewDotIndexedSet(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range)

2
tests/fsharp/typecheck/sigs/neg61.bsl поставляемый
Просмотреть файл

@ -61,7 +61,7 @@ neg61.fs(92,13,92,70): typecheck error FS3142: 'use' expressions may not be used
neg61.fs(97,13,97,17): typecheck error FS3143: 'let!', 'use!' and 'do!' expressions may not be used in queries
neg61.fs(102,13,102,28): typecheck error FS3143: 'let!', 'use!' and 'do!' expressions may not be used in queries
neg61.fs(102,13,102,16): typecheck error FS3143: 'let!', 'use!' and 'do!' expressions may not be used in queries
neg61.fs(107,13,107,21): typecheck error FS3144: 'return' and 'return!' may not be used in queries

Просмотреть файл

@ -14,7 +14,9 @@ ImplFile
Named (SynIdent (a, None), false, None, (2,4--2,5)), None,
Sequential
(SuppressNeither, true, Do (Ident foobar, (3,4--4,14)),
DoBang (Ident foobarBang, (5,4--6,18)), (3,4--6,18),
DoBang
(Ident foobarBang, (5,4--6,18),
{ DoBangKeyword = (5,4--5,7) }), (3,4--6,18),
{ SeparatorRange = None }), (2,4--2,5), NoneAtLet,
{ LeadingKeyword = Let (2,0--2,3)
InlineKeyword = None