Skip to content

Commit 296e7f2

Browse files
authored
Merge pull request #1230 from forki/no-matching
Suggest a function to implement if no abstract method matches
2 parents 23ef783 + 3e7ddee commit 296e7f2

File tree

7 files changed

+60
-5
lines changed

7 files changed

+60
-5
lines changed

src/fsharp/FSComp.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,8 @@ tcExpressionWithIfRequiresParenthesis,"This list or array expression includes an
590590
764,tcFieldRequiresAssignment,"No assignment given for field '%s' of type '%s'"
591591
765,tcExtraneousFieldsGivenValues,"Extraneous fields have been given values"
592592
766,tcObjectExpressionsCanOnlyOverrideAbstractOrVirtual,"Only overrides of abstract and virtual members may be specified in object expressions"
593-
767,tcNoAbstractOrVirtualMemberFound,"The member '%s' does not correspond to any abstract or virtual method available to override or implement"
593+
767,tcNoAbstractOrVirtualMemberFound,"The member '%s' does not correspond to any abstract or virtual method available to override or implement.%s"
594+
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"
594595
768,tcArgumentArityMismatch,"The member '%s' does not accept the correct number of arguments, %d arguments are expected"
595596
769,tcArgumentArityMismatchOneOverload,"The member '%s' does not accept the correct number of arguments. One overload accepts %d arguments."
596597
770,tcSimpleMethodNameRequired,"A simple method name is required here"

src/fsharp/TypeChecker.fs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6210,14 +6210,28 @@ and GetNameAndArityOfObjExprBinding _cenv _env b =
62106210
lookPat pat
62116211

62126212

6213-
and FreshenObjExprAbstractSlot cenv (_env: TcEnv) implty virtNameAndArityPairs (bind,bindAttribs,bindName,absSlots:(_ * MethInfo) list) =
6213+
and FreshenObjExprAbstractSlot cenv (_env: TcEnv) (implty:TType) virtNameAndArityPairs (bind,bindAttribs,bindName,absSlots:(_ * MethInfo) list) =
62146214
let (NormalizedBinding (_,_,_,_,_,_,synTyparDecls,_,_,_,mBinding,_)) = bind
62156215
match absSlots with
62166216
| [] when not (CompileAsEvent cenv.g bindAttribs) ->
62176217
let absSlotsByName = List.filter (fst >> fst >> (=) bindName) virtNameAndArityPairs
62186218

62196219
match absSlotsByName with
6220-
| [] -> errorR(Error(FSComp.SR.tcNoAbstractOrVirtualMemberFound(bindName),mBinding))
6220+
| [] ->
6221+
let tcref = tcrefOfAppTy cenv.g implty
6222+
let containsNonAbstractMemberWithSameName =
6223+
tcref.MembersOfFSharpTyconByName
6224+
|> Seq.exists (fun kv -> kv.Value |> List.exists (fun valRef -> valRef.DisplayName = bindName))
6225+
6226+
let predictions =
6227+
virtNameAndArityPairs
6228+
|> List.map (fst >> fst)
6229+
|> ErrorResolutionHints.FilterPredictions bindName
6230+
6231+
if containsNonAbstractMemberWithSameName then
6232+
errorR(Error(FSComp.SR.tcMemberFoundIsNotAbstractOrVirtual(tcref.DisplayName, bindName, ErrorResolutionHints.FormatPredictions predictions),mBinding))
6233+
else
6234+
errorR(Error(FSComp.SR.tcNoAbstractOrVirtualMemberFound(bindName, ErrorResolutionHints.FormatPredictions predictions),mBinding))
62216235
| [(_,absSlot:MethInfo)] -> errorR(Error(FSComp.SR.tcArgumentArityMismatch(bindName, (List.sum absSlot.NumArgs)),mBinding))
62226236
| (_,absSlot:MethInfo) :: _ -> errorR(Error(FSComp.SR.tcArgumentArityMismatchOneOverload(bindName, (List.sum absSlot.NumArgs)),mBinding))
62236237

tests/fsharp/typecheck/sigs/neg10.bsl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,17 @@ neg10.fs(174,9,175,20): typecheck error FS0951: Literal enumerations must have t
6969

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

72-
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
72+
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.
73+
74+
Maybe you want one of the following:
75+
76+
Equals
77+
78+
ToString
79+
80+
Finalize
81+
82+
GetHashCode
7383

7484
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
7585

tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ObjectExpressions/E_MembersMustBeVirtual01.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// #Regression #Conformance #DataExpressions #ObjectConstructors
22
// FSB 1683, dispatch slot checking in object expression manages to match non-virtual member
33

4-
//<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>
4+
//<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>
55
//<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>
66
//<Expects id="FS0783" status="error" span="(11,16-11,19)">At least one override did not correctly implement its corresponding abstract member$</Expects>
77

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// #Warnings
2+
//<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>
3+
//<Expects>ToString</Expects>
4+
5+
type Foo(x : int) =
6+
member v.MyX() = x
7+
8+
let foo =
9+
{ new Foo(3)
10+
with
11+
member v.MyX() = 4 }
12+
13+
14+
exit 0
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// #Warnings
2+
//<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>
3+
//<Expects>MyFunction</Expects>
4+
5+
type IInterface =
6+
abstract MyFunction : int32 * int32 -> unit
7+
abstract SomeOtherFunction : int32 * int32 -> unit
8+
9+
let x =
10+
{ new IInterface with
11+
member this.Function (i, j) = ()
12+
}
13+
14+
exit 0

tests/fsharpqa/Source/Warnings/env.lst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
SOURCE=AccessOfTypeAbbreviation5.fs # AccessOfTypeAbbreviation5.fs
1212
SOURCE=AccessOfTypeAbbreviation6.fs # AccessOfTypeAbbreviation6.fs
1313
SOURCE=ElseBranchHasWrongType.fs # ElseBranchHasWrongType.fs
14+
SOURCE=MatchingMethodWithSameNameIsNotAbstract.fs # MatchingMethodWithSameNameIsNotAbstract.fs
15+
SOURCE=NoMatchingAbstractMethodWithSameName.fs # NoMatchingAbstractMethodWithSameName.fs
1416
SOURCE=MissingExpressionAfterLet.fs # MissingExpressionAfterLet.fs
1517
SOURCE=AssignmentOnImmutable.fs # AssignmentOnImmutable.fs
1618
SOURCE=SuggestFieldsInCtor.fs # SuggestFieldsInCtor.fs

0 commit comments

Comments
 (0)