Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest a function to implement if no abstract method matches #1230

Merged
merged 2 commits into from
Jul 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/fsharp/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,8 @@ tcExpressionWithIfRequiresParenthesis,"This list or array expression includes an
764,tcFieldRequiresAssignment,"No assignment given for field '%s' of type '%s'"
765,tcExtraneousFieldsGivenValues,"Extraneous fields have been given values"
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"
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."
770,tcSimpleMethodNameRequired,"A simple method name is required here"
Expand Down
18 changes: 16 additions & 2 deletions src/fsharp/TypeChecker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6202,14 +6202,28 @@ and GetNameAndArityOfObjExprBinding _cenv _env b =
lookPat pat


and FreshenObjExprAbstractSlot cenv (_env: TcEnv) implty virtNameAndArityPairs (bind,bindAttribs,bindName,absSlots:(_ * MethInfo) list) =
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

match absSlotsByName with
| [] -> errorR(Error(FSComp.SR.tcNoAbstractOrVirtualMemberFound(bindName),mBinding))
| [] ->
let tcref = tcrefOfAppTy cenv.g implty
let containsNonAbstractMemberWithSameName =
tcref.MembersOfFSharpTyconByName
|> Seq.exists (fun kv -> kv.Value |> List.exists (fun valRef -> valRef.DisplayName = bindName))

let predictions =
virtNameAndArityPairs
|> List.map (fst >> fst)
|> ErrorResolutionHints.FilterPredictions bindName

if containsNonAbstractMemberWithSameName then
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))

Expand Down
12 changes: 11 additions & 1 deletion tests/fsharp/typecheck/sigs/neg10.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,17 @@ neg10.fs(174,9,175,20): typecheck error FS0951: Literal enumerations must have t

neg10.fs(180,10,180,11): typecheck error FS0866: Interfaces cannot contain definitions of object constructors

neg10.fs(193,39,193,46): typecheck error FS0767: The member 'MyX' does not correspond to any abstract or virtual method available to override or implement
neg10.fs(193,39,193,46): typecheck error FS0767: The type Foo contains the member 'MyX' but it is not a virtual or abstract method that is available to override or implement.

Maybe you want one of the following:

Equals

ToString

Finalize

GetHashCode

neg10.fs(193,41,193,44): typecheck error FS0017: The member 'MyX : unit -> int' does not have the correct type to override any given virtual method

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// #Regression #Conformance #DataExpressions #ObjectConstructors
// FSB 1683, dispatch slot checking in object expression manages to match non-virtual member

//<Expects id="FS0767" status="error" span="(11,35-11,42)">The member 'MyX' does not correspond to any abstract or virtual method available to override or implement$</Expects>
//<Expects id="FS0767" status="error" span="(11,35-11,42)">The type Foo contains the member 'MyX' but it is not a virtual or abstract method that is available to override or implement.</Expects>
//<Expects id="FS0017" status="error" span="(11,37-11,40)">The member 'MyX : unit -> int' does not have the correct type to override any given virtual method$</Expects>
//<Expects id="FS0783" status="error" span="(11,16-11,19)">At least one override did not correctly implement its corresponding abstract member$</Expects>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// #Warnings
//<Expects status="Error" span="(11,16)" id="FS0767">The type Foo contains the member 'MyX' but it is not a virtual or abstract method that is available to override or implement.</Expects>
//<Expects>ToString</Expects>

type Foo(x : int) =
member v.MyX() = x

let foo =
{ new Foo(3)
with
member v.MyX() = 4 }


exit 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// #Warnings
//<Expects status="Error" span="(11,14)" id="FS0767">The member 'Function' does not correspond to any abstract or virtual method available to override or implement.</Expects>
//<Expects>MyFunction</Expects>

type IInterface =
abstract MyFunction : int32 * int32 -> unit
abstract SomeOtherFunction : int32 * int32 -> unit

let x =
{ new IInterface with
member this.Function (i, j) = ()
}

exit 0
2 changes: 2 additions & 0 deletions tests/fsharpqa/Source/Warnings/env.lst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
SOURCE=CommaInRecCtor.fs # CommaInRecCtor.fs
SOURCE=ValidCommaInRecCtor.fs # ValidCommaInRecCtor.fs
SOURCE=ElseBranchHasWrongType.fs # ElseBranchHasWrongType.fs
SOURCE=MatchingMethodWithSameNameIsNotAbstract.fs # MatchingMethodWithSameNameIsNotAbstract.fs
SOURCE=NoMatchingAbstractMethodWithSameName.fs # NoMatchingAbstractMethodWithSameName.fs
SOURCE=MissingExpressionAfterLet.fs # MissingExpressionAfterLet.fs
SOURCE=AssignmentOnImmutable.fs # AssignmentOnImmutable.fs
SOURCE=UpcastInsteadOfDowncast.fs # UpcastInsteadOfDowncast.fs
Expand Down