Skip to content

Commit 499b2c3

Browse files
dungpalatkin
authored andcommitted
Issue warning for additional unused arguments of 'raise'-family functions
closes dotnet/fsharp#630 fixes dotnet/fsharp#46 commit 45c8e02781b3829f06cab9af2c0b515731812424 Author: Anh-Dung Phan <phananhdung309@yahoo.com> Date: Fri Sep 11 21:34:52 2015 +0000 Add relevant unit tests commit 91b45f2b5130cb05cda227ac2d3986680c999e79 Author: Anh-Dung Phan <phananhdung309@yahoo.com> Date: Fri Sep 11 20:51:46 2015 +0000 Fix compiler warnings exposed by the feature commit 9fd06108987aaddd5e25a40baea1495693e54048 Author: dungpa <phananhdung309@yahoo.com> Date: Mon Sep 7 01:07:28 2015 +0200 Add warnings for extra arguments of failwithf function commit 47944923aaaedc3d229e5fcd881216fef23fdeaf Author: dungpa <phananhdung309@yahoo.com> Date: Sun Sep 6 00:25:58 2015 +0200 Add similar warnings for failwith, invalidArg, nullArg and invalidOp commit a23e312c8a88563c470dd0237e1a3e3aaee757b7 Author: dungpa <phananhdung309@yahoo.com> Date: Sat Sep 5 23:49:54 2015 +0200 Check number of arguments of function 'raise'
1 parent 3dd2d62 commit 499b2c3

17 files changed

+138
-12
lines changed

src/fsharp/CheckFormatStrings.fs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ let newInfo ()=
4848
addZeros = false;
4949
precision = false}
5050

51-
let ParseFormatString m g fmt bty cty dty =
51+
let parseFormatStringInternal m g fmt bty cty =
5252
let len = String.length fmt
5353

5454
let rec parseLoop acc i =
@@ -58,10 +58,7 @@ let ParseFormatString m g fmt bty cty dty =
5858
acc |> List.map snd |> List.rev
5959
else
6060
failwithf "%s" <| FSComp.SR.forPositionalSpecifiersNotPermitted()
61-
62-
let aty = List.foldBack (-->) argtys dty
63-
let ety = mkTupledTy g argtys
64-
aty,ety
61+
argtys
6562
elif System.Char.IsSurrogatePair(fmt,i) then
6663
parseLoop acc (i+2)
6764
else
@@ -230,3 +227,16 @@ let ParseFormatString m g fmt bty cty dty =
230227
| _ -> parseLoop acc (i+1)
231228
parseLoop [] 0
232229

230+
let ParseFormatString m g fmt bty cty dty =
231+
let argtys = parseFormatStringInternal m g fmt bty cty
232+
let aty = List.foldBack (-->) argtys dty
233+
let ety = mkTupledTy g argtys
234+
aty, ety
235+
236+
let TryCountFormatStringArguments m g fmt bty cty =
237+
try
238+
parseFormatStringInternal m g fmt bty cty
239+
|> List.length
240+
|> Some
241+
with _ ->
242+
None

src/fsharp/CheckFormatStrings.fsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ open Microsoft.FSharp.Compiler.TcGlobals
1414
open Microsoft.FSharp.Compiler.AbstractIL.Internal
1515

1616
val ParseFormatString : Range.range -> TcGlobals -> string -> TType -> TType -> TType -> TType * TType
17+
18+
val TryCountFormatStringArguments : m:Range.range -> g:TcGlobals -> fmt:string -> bty:TType -> cty:TType -> int option

src/fsharp/FSComp.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,3 +1343,4 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS
13431343
3186,pickleMissingDefinition,"An error occurred while reading the F# metadata node at position %d in table '%s' of assembly '%s'. The node had no matching declaration. Please report this warning. You may need to recompile the F# assembly you are using."
13441344
3187,checkNotSufficientlyGenericBecauseOfScope,"Type inference caused the type variable %s to escape its scope. Consider adding an explicit type parameter declaration or adjusting your code to be less generic."
13451345
3188,checkNotSufficientlyGenericBecauseOfScopeAnon,"Type inference caused an inference type variable to escape its scope. Consider adding type annotations to make your code less generic."
1346+
3189,checkRaiseFamilyFunctionArgumentCount,"Redundant arguments are being ignored in function '%s'. Expected %d but got %d arguments."

src/fsharp/FSharp.Core/Query.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ type QueryBuilder() =
148148
acc <- plus acc (selector e.Current)
149149
count <- count + 1
150150
if count = 0 then
151-
invalidOp "source" (System.Linq.Enumerable.Average ([| |]: int[])) // raise the same error as LINQ
151+
invalidOp "source"
152152
LanguagePrimitives.DivideByInt< (^U) > acc count
153153

154154
member inline __.SumBy< 'T, 'Q, ^Value

src/fsharp/FSharp.Core/quotations.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1717,7 +1717,7 @@ module Patterns =
17171717
ci
17181718
let paramTypes = mi.GetParameters() |> getTypesFromParamInfos
17191719
Key(declaringType, tyArgsCount, methodBase.Name, paramTypes, declaringType)
1720-
| _ -> failwith "Unexpected MethodBase type, %A" (methodBase.GetType()) // per MSDN ConstructorInfo and MethodInfo are the only derived types from MethodBase
1720+
| _ -> failwithf "Unexpected MethodBase type, %A" (methodBase.GetType()) // per MSDN ConstructorInfo and MethodInfo are the only derived types from MethodBase
17211721
#else
17221722
[<StructuralEquality; NoComparison>]
17231723
type ReflectedDefinitionTableKey =

src/fsharp/PostInferenceChecks.fs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ let CheckMultipleInterfaceInstantiations cenv interfaces m =
456456
errorR(Error(FSComp.SR.chkMultipleGenericInterfaceInstantiations((NicePrint.minimalStringOfType cenv.denv typ1), (NicePrint.minimalStringOfType cenv.denv typ2)),m))
457457

458458

459-
let rec CheckExpr (cenv:cenv) (env:env) expr =
459+
let rec CheckExpr (cenv:cenv) (env:env) expr =
460460
CheckExprInContext cenv env expr GeneralContext
461461

462462
and CheckVal (cenv:cenv) (env:env) v m context =
@@ -583,6 +583,38 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) =
583583

584584

585585
| Expr.App(f,fty,tyargs,argsl,m) ->
586+
let (|OptionalCoerce|) = function
587+
| Expr.Op(TOp.Coerce _, _, [Expr.App(f, _, _, [], _)], _) -> f
588+
| x -> x
589+
if cenv.reportErrors then
590+
let g = cenv.g
591+
match f with
592+
| OptionalCoerce(Expr.Val(v, _, funcRange))
593+
when (valRefEq g v g.raise_vref || valRefEq g v g.failwith_vref || valRefEq g v g.null_arg_vref || valRefEq g v g.invalid_op_vref) ->
594+
match argsl with
595+
| [] | [_] -> ()
596+
| _ :: _ :: _ ->
597+
warning(Error(FSComp.SR.checkRaiseFamilyFunctionArgumentCount(v.DisplayName, 1, List.length argsl), funcRange))
598+
| OptionalCoerce(Expr.Val(v, _, funcRange)) when valRefEq g v g.invalid_arg_vref ->
599+
match argsl with
600+
| [] | [_] | [_; _] -> ()
601+
| _ :: _ :: _ :: _ ->
602+
warning(Error(FSComp.SR.checkRaiseFamilyFunctionArgumentCount(v.DisplayName, 2, List.length argsl), funcRange))
603+
| OptionalCoerce(Expr.Val(failwithfFunc, _, funcRange)) when valRefEq g failwithfFunc g.failwithf_vref ->
604+
match argsl with
605+
| Expr.App (Expr.Val(newFormat, _, _), _, [_; typB; typC; _; _], [Expr.Const(Const.String formatString, formatRange, _)], _) :: xs when valRefEq g newFormat g.new_format_vref ->
606+
match CheckFormatStrings.TryCountFormatStringArguments formatRange g formatString typB typC with
607+
| Some n ->
608+
let expected = n + 1
609+
let actual = List.length xs + 1
610+
if expected < actual then
611+
warning(Error(FSComp.SR.checkRaiseFamilyFunctionArgumentCount(failwithfFunc.DisplayName, expected, actual), funcRange))
612+
| None -> ()
613+
| _ ->
614+
()
615+
| _ ->
616+
()
617+
586618
CheckTypeInstNoByrefs cenv env m tyargs;
587619
CheckTypePermitByrefs cenv env m fty;
588620
CheckTypeInstPermitByrefs cenv env m tyargs;

src/fsharp/TcGlobals.fs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,18 @@ type public TcGlobals =
513513
seq_empty_vref : ValRef
514514
new_format_info : IntrinsicValRef
515515
raise_info : IntrinsicValRef
516+
raise_vref : ValRef
517+
failwith_info : IntrinsicValRef
518+
failwith_vref : ValRef
519+
invalid_arg_info : IntrinsicValRef
520+
invalid_arg_vref : ValRef
521+
null_arg_info : IntrinsicValRef
522+
null_arg_vref : ValRef
523+
invalid_op_info : IntrinsicValRef
524+
invalid_op_vref : ValRef
525+
failwithf_info : IntrinsicValRef
526+
failwithf_vref : ValRef
527+
516528
lazy_force_info : IntrinsicValRef
517529
lazy_create_info : IntrinsicValRef
518530

@@ -911,7 +923,13 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa
911923
let unchecked_unary_minus_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_UnaryNegation" ,None ,None ,[vara], mk_unop_ty varaTy)
912924
let unchecked_unary_not_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "not" ,None ,Some "Not" ,[], mk_unop_ty bool_ty)
913925

914-
let raise_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "raise" ,None ,Some "Raise" ,[vara],([[mkSysNonGenericTy sys "Exception"]],varaTy))
926+
let raise_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "raise" ,None ,Some "Raise" ,[vara], ([[mkSysNonGenericTy sys "Exception"]],varaTy))
927+
let failwith_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "failwith" ,None ,Some "FailWith" ,[vara], ([[string_ty]],varaTy))
928+
let invalid_arg_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "invalidArg" ,None ,Some "InvalidArg" ,[vara], ([[string_ty]; [string_ty]],varaTy))
929+
let null_arg_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "nullArg" ,None ,Some "NullArg" ,[vara], ([[string_ty]],varaTy))
930+
let invalid_op_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "invalidOp" ,None ,Some "InvalidOp" ,[vara], ([[string_ty]],varaTy))
931+
let failwithf_info = makeIntrinsicValRef(fslib_MFExtraTopLevelOperators_nleref, "failwithf" ,None, Some "PrintFormatToStringThenFail" ,[vara;varb],([[mk_format4_ty varaTy unit_ty string_ty string_ty]], varaTy))
932+
915933
let reraise_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "reraise" ,None ,Some "Reraise",[vara], ([[unit_ty]],varaTy))
916934
let typeof_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "typeof" ,None ,Some "TypeOf" ,[vara], ([],system_Type_typ))
917935
let methodhandleof_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "methodhandleof" ,None ,Some "MethodHandleOf",[vara;varb],([[varaTy --> varbTy]],system_RuntimeMethodHandle_typ))
@@ -1352,6 +1370,18 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa
13521370
equals_operator_info = equals_operator_info
13531371

13541372
raise_info = raise_info
1373+
raise_vref = ValRefForIntrinsic raise_info
1374+
failwith_info = failwith_info
1375+
failwith_vref = ValRefForIntrinsic failwith_info
1376+
invalid_arg_info = invalid_arg_info
1377+
invalid_arg_vref = ValRefForIntrinsic invalid_arg_info
1378+
null_arg_info = null_arg_info
1379+
null_arg_vref = ValRefForIntrinsic null_arg_info
1380+
invalid_op_info = invalid_op_info
1381+
invalid_op_vref = ValRefForIntrinsic invalid_op_info
1382+
failwithf_info = failwithf_info
1383+
failwithf_vref = ValRefForIntrinsic failwithf_info
1384+
13551385
reraise_info = reraise_info
13561386
reraise_vref = ValRefForIntrinsic reraise_info
13571387
methodhandleof_info = methodhandleof_info
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// #Regression #Diagnostics
2+
//<Expects status="warning" span="(4,11-4,19)" id="FS3189">Redundant arguments are being ignored in function 'failwith'\. Expected 1 but got 2 arguments\.$</Expects>
3+
module M
4+
let f() = failwith "Used" "Ignored"
5+
let g() = failwith "Used"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// #Regression #Diagnostics
2+
//<Expects status="warning" span="(4,11-4,20)" id="FS3189">Redundant arguments are being ignored in function 'failwithf'\. Expected 3 but got 4 arguments\.$</Expects>
3+
module M
4+
let f() = failwithf "Used %A %s" "this" "but not" "this"
5+
let g() = failwith "Used %A" "this"
6+
let h() =
7+
let failwithf arg = Printf.ksprintf failwith arg
8+
failwithf "Used" "Ignored"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// #Regression #Diagnostics
2+
//<Expects status="warning" span="(6,5-6,15)" id="FS3189">Redundant arguments are being ignored in function 'invalidArg'\. Expected 2 but got 3 arguments\.$</Expects>
3+
module M
4+
type T() =
5+
member __.M1 source =
6+
invalidArg source "Used" "Ignored"
7+
member __.M2 source =
8+
invalidArg source "Used"

0 commit comments

Comments
 (0)