From 63285bff782941827a4fc897a236d35d5e6ced6c Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 31 May 2016 12:08:07 +0200 Subject: [PATCH] Better error message when abstract member impl is wrong - fixes #1203 --- src/fsharp/FSComp.txt | 5 +++-- src/fsharp/TypeChecker.fs | 22 +++++++++++++++---- .../Source/Warnings/TupleInAbstractMethod.fs | 13 +++++++++++ tests/fsharpqa/Source/Warnings/env.lst | 1 + 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 tests/fsharpqa/Source/Warnings/TupleInAbstractMethod.fs diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index c9d4ddf807..a89478b5fe 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -22,6 +22,7 @@ derefInsteadOfNot,"The '!' operator is used to dereference a ref cell. Consider buildUnexpectedTypeArgs,"The non-generic type '%s' does not expect any type arguments, but here is given %d type argument(s)" returnUsedInsteadOfReturnBang,"Consider using 'return!' instead of 'return'." yieldUsedInsteadOfYieldBang,"Consider using 'yield!' instead of 'yield'." +tupleRequiredInAbstractMethod,"\nA tuple type is required for one or more arguments. Consider wrapping the given arguments in additional parentheses or review the definition of the interface." 203,buildInvalidWarningNumber,"Invalid warning number '%s'" 204,buildInvalidVersionString,"Invalid version string '%s'" 205,buildInvalidVersionFile,"Invalid version file '%s'" @@ -592,8 +593,8 @@ tcExpressionWithIfRequiresParenthesis,"This list or array expression includes an 766,tcObjectExpressionsCanOnlyOverrideAbstractOrVirtual,"Only overrides of abstract and virtual members may be specified in object expressions" 767,tcNoAbstractOrVirtualMemberFound,"The member '%s' does not correspond to any abstract or virtual method available to override or implement.%s" 767,tcMemberFoundIsNotAbstractOrVirtual,"The type %s contains the member '%s' but it is not a virtual or abstract method that is available to override or implement.%s" -768,tcArgumentArityMismatch,"The member '%s' does not accept the correct number of arguments, %d arguments are expected" -769,tcArgumentArityMismatchOneOverload,"The member '%s' does not accept the correct number of arguments. One overload accepts %d arguments." +768,tcArgumentArityMismatch,"The member '%s' does not accept the correct number of arguments. %d argument(s) are expected, but %d were given. The required signature is '%s'.%s" +769,tcArgumentArityMismatchOneOverload,"The member '%s' does not accept the correct number of arguments. One overload accepts %d arguments, but %d were given. The required signature is '%s'.%s" 770,tcSimpleMethodNameRequired,"A simple method name is required here" 771,tcPredefinedTypeCannotBeUsedAsSuperType,"The types System.ValueType, System.Enum, System.Delegate, System.MulticastDelegate and System.Array cannot be used as super types in an object expression or class" 772,tcNewMustBeUsedWithNamedType,"'new' must be used with a named type" diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index da9676f083..059850eeb7 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -6210,11 +6210,23 @@ and GetNameAndArityOfObjExprBinding _cenv _env b = lookPat pat -and FreshenObjExprAbstractSlot cenv (_env: TcEnv) (implty:TType) virtNameAndArityPairs (bind,bindAttribs,bindName,absSlots:(_ * MethInfo) list) = - let (NormalizedBinding (_,_,_,_,_,_,synTyparDecls,_,_,_,mBinding,_)) = bind +and FreshenObjExprAbstractSlot cenv (env: TcEnv) (implty:TType) virtNameAndArityPairs (bind,bindAttribs,bindName,absSlots:(_ * MethInfo) list) = + let (NormalizedBinding (_,_,_,_,_,_,synTyparDecls,_,_,_,mBinding,_)) = bind match absSlots with | [] when not (CompileAsEvent cenv.g bindAttribs) -> let absSlotsByName = List.filter (fst >> fst >> (=) bindName) virtNameAndArityPairs + let getSignature absSlot = (NicePrint.stringOfMethInfo cenv.amap mBinding env.DisplayEnv absSlot).Replace("abstract ","") + let getDetails (absSlot:MethInfo) = + if absSlot.GetParamTypes(cenv.amap,mBinding,[]) |> List.existsSquared (isTupleTy cenv.g) then + FSComp.SR.tupleRequiredInAbstractMethod() + else "" + + // Compute the argument counts of the member arguments + let _,synValInfo = GetNameAndArityOfObjExprBinding cenv env bind + let arity = + match SynInfo.AritiesOfArgs synValInfo with + | _::x::_ -> x + | _ -> 0 match absSlotsByName with | [] -> @@ -6232,8 +6244,10 @@ and FreshenObjExprAbstractSlot cenv (_env: TcEnv) (implty:TType) virtNameAndArit errorR(Error(FSComp.SR.tcMemberFoundIsNotAbstractOrVirtual(tcref.DisplayName, bindName, ErrorResolutionHints.FormatPredictions predictions),mBinding)) else errorR(Error(FSComp.SR.tcNoAbstractOrVirtualMemberFound(bindName, ErrorResolutionHints.FormatPredictions predictions),mBinding)) - | [(_,absSlot:MethInfo)] -> errorR(Error(FSComp.SR.tcArgumentArityMismatch(bindName, (List.sum absSlot.NumArgs)),mBinding)) - | (_,absSlot:MethInfo) :: _ -> errorR(Error(FSComp.SR.tcArgumentArityMismatchOneOverload(bindName, (List.sum absSlot.NumArgs)),mBinding)) + | [(_,absSlot:MethInfo)] -> + errorR(Error(FSComp.SR.tcArgumentArityMismatch(bindName, List.sum absSlot.NumArgs, arity, getSignature absSlot, getDetails absSlot),mBinding)) + | (_,absSlot:MethInfo) :: _ -> + errorR(Error(FSComp.SR.tcArgumentArityMismatchOneOverload(bindName, List.sum absSlot.NumArgs, arity, getSignature absSlot, getDetails absSlot),mBinding)) None diff --git a/tests/fsharpqa/Source/Warnings/TupleInAbstractMethod.fs b/tests/fsharpqa/Source/Warnings/TupleInAbstractMethod.fs new file mode 100644 index 0000000000..0ed439073e --- /dev/null +++ b/tests/fsharpqa/Source/Warnings/TupleInAbstractMethod.fs @@ -0,0 +1,13 @@ +// #Warnings +//The member 'Function' does not accept the correct number of arguments. +//A tuple type is required for one or more arguments + +type IInterface = + abstract Function : (int32 * int32) -> unit + +let x = + { new IInterface with + member this.Function (i, j) = () + } + +exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 5f94f985bb..8a644022e8 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -2,6 +2,7 @@ SOURCE=WarnIfMissingElseBranch.fs # WarnIfMissingElseBranch.fs SOURCE=ReturnInsteadOfReturnBang.fs # ReturnInsteadOfReturnBang.fs SOURCE=YieldInsteadOfYieldBang.fs # YieldInsteadOfYieldBang.fs + SOURCE=TupleInAbstractMethod.fs # TupleInAbstractMethod.fs SOURCE=InvalidRecord.fs # InvalidRecord.fs SOURCE=CommaInRecCtor.fs # CommaInRecCtor.fs SOURCE=ValidCommaInRecCtor.fs # ValidCommaInRecCtor.fs