提交 24ea91bf 编写于 作者: S Steffen Forkmann 提交者: Kevin Ransom (msft)

Give better error message when IF Statement has context requirements (#3150)

* Give better error message when IF Statement has context requirements

* simplify code

* Update TypeChecker.fs

* something has a type

* Adding a test

* Transitive IF context

* Another test - fixes #3146

* fix wording
上级 4f222ace
......@@ -628,6 +628,7 @@ let OutputPhasedErrorR (os:StringBuilder) (err:PhasedDiagnostic) =
let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv t1 t2
match contextInfo with
| ContextInfo.IfExpression range when range = m -> os.Append(FSComp.SR.ifExpression(t1,t2)) |> ignore
| ContextInfo.OmittedElseBranch range when range = m -> os.Append(FSComp.SR.missingElseBranch(t2)) |> ignore
| ContextInfo.ElseBranchResult range when range = m -> os.Append(FSComp.SR.elseBranchHasWrongType(t1,t2)) |> ignore
| _ -> os.Append(ConstraintSolverTypesNotInEqualityRelation1E().Format t1 t2 ) |> ignore
......@@ -639,6 +640,7 @@ let OutputPhasedErrorR (os:StringBuilder) (err:PhasedDiagnostic) =
let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv t1 t2
match contextInfo with
| ContextInfo.IfExpression range when range = m -> os.Append(FSComp.SR.ifExpression(t1,t2)) |> ignore
| ContextInfo.OmittedElseBranch range when range = m -> os.Append(FSComp.SR.missingElseBranch(t2)) |> ignore
| ContextInfo.ElseBranchResult range when range = m -> os.Append(FSComp.SR.elseBranchHasWrongType(t1,t2)) |> ignore
| _ -> os.Append(ConstraintSolverTypesNotInEqualityRelation2E().Format t1 t2) |> ignore
......@@ -664,6 +666,7 @@ let OutputPhasedErrorR (os:StringBuilder) (err:PhasedDiagnostic) =
&& typeEquiv g t2 t2' ->
let t1,t2,tpcs = NicePrint.minimalStringsOfTwoTypes denv t1 t2
match contextInfo with
| ContextInfo.IfExpression range when range = m -> os.Append(FSComp.SR.ifExpression(t1,t2)) |> ignore
| ContextInfo.OmittedElseBranch range when range = m -> os.Append(FSComp.SR.missingElseBranch(t2)) |> ignore
| ContextInfo.ElseBranchResult range when range = m -> os.Append(FSComp.SR.elseBranchHasWrongType(t1,t2)) |> ignore
| ContextInfo.TupleInRecordFields ->
......
......@@ -117,6 +117,8 @@ let FreshenMethInfo m (minfo:MethInfo) =
type ContextInfo =
/// No context was given.
| NoContext
/// The type equation comes from an IF expression.
| IfExpression of range
/// The type equation comes from an omitted else branch.
| OmittedElseBranch of range
/// The type equation comes from a type check of the result of an else branch.
......
......@@ -52,6 +52,8 @@ val FreshenMethInfo : range -> MethInfo -> TType list
type ContextInfo =
/// No context was given.
| NoContext
/// The type equation comes from an IF expression.
| IfExpression of range
/// The type equation comes from an omitted else branch.
| OmittedElseBranch of range
/// The type equation comes from a type check of the result of an else branch.
......
......@@ -17,6 +17,7 @@ undefinedNameTypeParameter,"The type parameter %s is not defined."
undefinedNamePatternDiscriminator,"The pattern discriminator '%s' is not defined."
replaceWithSuggestion,"Replace with '%s'"
missingElseBranch,"The 'if' expression is missing an 'else' branch. The 'then' branch has type '%s'. Because 'if' is an expression, and not a statement, add an 'else' branch which returns a value of the same type."
ifExpression,"The 'if' expression needs to have type '%s' to satisfy context type requirements. It currently has type '%s'."
elseBranchHasWrongType,"All branches of an 'if' expression must return the same type. This expression was expected to have type '%s' but here has type '%s'."
commaInsteadOfSemicolonInRecord,"A ';' is used to separate field values in records. Consider replacing ',' with ';'."
derefInsteadOfNot,"The '!' operator is used to dereference a ref cell. Consider using 'not expr' here."
......
......@@ -5872,12 +5872,19 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) =
| SynExpr.IfThenElse (e1,e2,e3opt,spIfToThen,isRecovery,mIfToThen,m) ->
let e1',tpenv = TcExprThatCantBeCtorBody cenv cenv.g.bool_ty env tpenv e1
let e2',tpenv =
let env =
match env.eContextInfo with
| ContextInfo.ElseBranchResult _ -> { env with eContextInfo = ContextInfo.ElseBranchResult e2.Range }
| _ ->
match e3opt with
| None -> { env with eContextInfo = ContextInfo.OmittedElseBranch e2.Range }
| _ -> { env with eContextInfo = ContextInfo.IfExpression e2.Range }
if not isRecovery && Option.isNone e3opt then
let env = { env with eContextInfo = ContextInfo.OmittedElseBranch e2.Range}
UnifyTypes cenv env m cenv.g.unit_ty overallTy
TcExprThatCanBeCtorBody cenv overallTy env tpenv e2
else
TcExprThatCanBeCtorBody cenv overallTy env tpenv e2
TcExprThatCanBeCtorBody cenv overallTy env tpenv e2
let e3',sp2,tpenv =
match e3opt with
| None ->
......@@ -5886,6 +5893,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) =
let env = { env with eContextInfo = ContextInfo.ElseBranchResult e3.Range }
let e3',tpenv = TcExprThatCanBeCtorBody cenv overallTy env tpenv e3
e3',SequencePointAtTarget,tpenv
primMkCond spIfToThen SequencePointAtTarget sp2 m overallTy e1' e2' e3', tpenv
// This is for internal use in the libraries only
......
// #Warnings
//<Expects status="Error" id="FS0001">The 'if' expression needs to have type 'bool'</Expects>
let x = 1
let y : bool =
if x = 2 then "A"
else "B"
exit 0
\ No newline at end of file
// #Warnings
//<Expects status="Error" id="FS0001">All branches of an 'if' expression must return the same type.</Expects>
let x = 1
if x = 1 then true
else
if x = 2 then "A"
else "B"
exit 0
\ No newline at end of file
......@@ -45,6 +45,8 @@
SOURCE=SuggestDoubleBacktickUnions.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickUnions.fs
SOURCE=ElseBranchHasWrongType.fs # ElseBranchHasWrongType.fs
SOURCE=ElseBranchHasWrongType2.fs # ElseBranchHasWrongType2.fs
SOURCE=NestedElseBranchHasWrongType.fs # NestedElseBranchHasWrongType.fs
SOURCE=ElseBranchHasWrongContextType.fs # ElseBranchHasWrongContextType.fs
SOURCE=ElseBranchContextDoesntPropagateInAppl.fs # ElseBranchContextDoesntPropagateInAppl.fs
SOURCE=ElseBranchContextDoesntPropagateInAppl2.fs # ElseBranchContextDoesntPropagateInAppl2.fs
SOURCE=ElseBranchContextDoesntPropagateInForLoop.fs # ElseBranchContextDoesntPropagateInForLoop.fs
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册