Skip to content

Commit 49f4722

Browse files
committed
Improve error reporting for abstract members when used in classes
1 parent 273cea5 commit 49f4722

File tree

5 files changed

+15
-16
lines changed

5 files changed

+15
-16
lines changed

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ type cenv = TcFileState
5454
type MutRecDataForOpen = MutRecDataForOpen of SynOpenDeclTarget * range * appliedScope: range * OpenDeclaration list ref
5555
type MutRecDataForModuleAbbrev = MutRecDataForModuleAbbrev of Ident * LongIdent * range
5656

57+
exception TypeIsImplicitlyAbstract of range
58+
5759
/// Represents the shape of a mutually recursive group of declarations including nested modules
5860
[<RequireQualifiedAccess>]
5961
type MutRecShape<'TypeData, 'LetsData, 'ModuleData> =
@@ -3629,8 +3631,10 @@ module EstablishTypeDefinitionCores =
36293631
noSealedAttributeCheck FSComp.SR.tcTypesAreAlwaysSealedStruct
36303632
noAbstractClassAttributeCheck()
36313633
noAllowNullLiteralAttributeCheck()
3632-
if not (isNil slotsigs) then
3633-
errorR (Error(FSComp.SR.tcStructTypesCannotContainAbstractMembers(), m))
3634+
3635+
for slot in abstractSlots do
3636+
errorR (Error(FSComp.SR.tcStructTypesCannotContainAbstractMembers(), slot.Range))
3637+
36343638
structLayoutAttributeCheck true
36353639

36363640
TFSharpStruct
@@ -3647,8 +3651,11 @@ module EstablishTypeDefinitionCores =
36473651
structLayoutAttributeCheck(not isIncrClass)
36483652
allowNullLiteralAttributeCheck()
36493653
for slot in abstractSlots do
3650-
if not slot.IsInstanceMember then
3651-
errorR(Error(FSComp.SR.chkStaticAbstractMembersOnClasses(), slot.Range))
3654+
if not slot.IsInstanceMember then
3655+
errorR(Error(FSComp.SR.chkStaticAbstractMembersOnClasses(), slot.Range))
3656+
elif not hasAbstractAttr then
3657+
errorR(TypeIsImplicitlyAbstract(slot.Range))
3658+
36523659
TFSharpClass
36533660
| SynTypeDefnKind.Delegate (ty, arity) ->
36543661
noCLIMutableAttributeCheck()

src/Compiler/Checking/CheckDeclarations.fsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,5 @@ val CheckOneSigFile:
7979
exception NotUpperCaseConstructor of range: range
8080

8181
exception NotUpperCaseConstructorWithoutRQA of range: range
82+
83+
exception TypeIsImplicitlyAbstract of range

src/Compiler/Checking/MethodOverrides.fs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ type SlotImplSet =
103103
availablePriorOverrides: OverrideInfo list *
104104
requiredProperties: PropInfo list
105105

106-
exception TypeIsImplicitlyAbstract of range
107106
exception OverrideDoesntOverride of DisplayEnv * OverrideInfo * MethInfo option * TcGlobals * Import.ImportMap * range
108107

109108
module DispatchSlotChecking =
@@ -828,11 +827,7 @@ module DispatchSlotChecking =
828827

829828
if isImplementation && not (isInterfaceTy g overallTy) then
830829
let overrides = allImmediateMembersThatMightImplementDispatchSlots |> List.map snd
831-
let allCorrect = CheckDispatchSlotsAreImplemented (denv, infoReader, m, nenv, sink, tcaug.tcaug_abstract, false, reqdTy, dispatchSlots, availPriorOverrides, overrides)
832-
833-
// Tell the user to mark the thing abstract if it was missing implementations
834-
if not allCorrect && not tcaug.tcaug_abstract && not (isInterfaceTy g reqdTy) then
835-
errorR(TypeIsImplicitlyAbstract(m))
830+
let _ = CheckDispatchSlotsAreImplemented (denv, infoReader, m, nenv, sink, tcaug.tcaug_abstract, false, reqdTy, dispatchSlots, availPriorOverrides, overrides)
836831

837832
let overridesToCheck =
838833
allImmediateMembersThatMightImplementDispatchSlots
@@ -882,7 +877,7 @@ module DispatchSlotChecking =
882877
overrideBy.MemberInfo.Value.ImplementedSlotSigs <- overriden)
883878

884879
/// "Type Completion" inference and a few other checks at the end of the inference scope
885-
let FinalTypeDefinitionChecksAtEndOfInferenceScope (infoReader: InfoReader, nenv, sink, isImplementation, denv, tycon: Tycon) =
880+
let FinalTypeDefinitionChecksAtEndOfInferenceScope (infoReader: InfoReader, nenv: NameResolutionEnv, sink: TcResultsSink, isImplementation, denv: DisplayEnv, tycon: Tycon) =
886881

887882
let g = infoReader.g
888883
let amap = infoReader.amap

src/Compiler/Checking/MethodOverrides.fsi

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ type SlotImplSet =
7777
availablePriorOverrides: OverrideInfo list *
7878
requiredProperties: PropInfo list
7979

80-
exception TypeIsImplicitlyAbstract of range
81-
8280
exception OverrideDoesntOverride of DisplayEnv * OverrideInfo * MethInfo option * TcGlobals * ImportMap * range
8381

8482
module DispatchSlotChecking =

tests/FSharp.Compiler.ComponentTests/Conformance/GeneratedEqualityHashingComparison/Basic/Basic.fs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,12 @@ module Basic =
6262
(Error 344, Line 13, Col 6, Line 13, Col 7, "The struct, record or union type 'R' has an explicit implementation of 'Object.GetHashCode' or 'Object.Equals'. You must apply the 'CustomEquality' attribute to the type")
6363
(Warning 345, Line 13, Col 6, Line 13, Col 7, "The struct, record or union type 'R' has an explicit implementation of 'Object.GetHashCode'. Consider implementing a matching override for 'Object.Equals(obj)'")
6464
(Error 359, Line 13, Col 6, Line 13, Col 7, "More than one override implements 'GetHashCode: unit -> int'")
65-
(Error 54, Line 13, Col 6, Line 13, Col 7, "This type is 'abstract' since some abstract members have not been given an implementation. If this is intentional then add the '[<AbstractClass>]' attribute to your type.")
6665
(Error 344, Line 17, Col 6, Line 17, Col 7, "The struct, record or union type 'U' has an explicit implementation of 'Object.GetHashCode' or 'Object.Equals'. You must apply the 'CustomEquality' attribute to the type")
6766
(Warning 345, Line 17, Col 6, Line 17, Col 7, "The struct, record or union type 'U' has an explicit implementation of 'Object.GetHashCode'. Consider implementing a matching override for 'Object.Equals(obj)'")
6867
(Error 359, Line 17, Col 6, Line 17, Col 7, "More than one override implements 'GetHashCode: unit -> int'")
69-
(Error 54, Line 17, Col 6, Line 17, Col 7, "This type is 'abstract' since some abstract members have not been given an implementation. If this is intentional then add the '[<AbstractClass>]' attribute to your type.")
7068
(Error 344, Line 21, Col 6, Line 21, Col 7, "The struct, record or union type 'S' has an explicit implementation of 'Object.GetHashCode' or 'Object.Equals'. You must apply the 'CustomEquality' attribute to the type")
7169
(Warning 345, Line 21, Col 6, Line 21, Col 7, "The struct, record or union type 'S' has an explicit implementation of 'Object.GetHashCode'. Consider implementing a matching override for 'Object.Equals(obj)'")
7270
(Error 359, Line 21, Col 6, Line 21, Col 7, "More than one override implements 'GetHashCode: unit -> int'")
73-
(Error 54, Line 21, Col 6, Line 21, Col 7, "This type is 'abstract' since some abstract members have not been given an implementation. If this is intentional then add the '[<AbstractClass>]' attribute to your type.")
7471
]
7572

7673
// SOURCE=E_ExceptionsNoComparison.fs SCFLAGS="--test:ErrorRanges" # E_ExceptionsNoComparison.fs

0 commit comments

Comments
 (0)