Skip to content

Commit 848c934

Browse files
authored
Merge pull request #1377 from smoothdeveloper/issue-35-return-type-abstract-method-unit
Better error message when specializing generic abstract type with unit
2 parents 53fe4ef + 17ec8ce commit 848c934

File tree

7 files changed

+49
-7
lines changed

7 files changed

+49
-7
lines changed

src/fsharp/CompileOps.fs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ let TypeTestUnnecessaryE() = DeclareResourceString("TypeTestUnnecessary","")
524524
let OverrideDoesntOverride1E() = DeclareResourceString("OverrideDoesntOverride1","%s")
525525
let OverrideDoesntOverride2E() = DeclareResourceString("OverrideDoesntOverride2","%s")
526526
let OverrideDoesntOverride3E() = DeclareResourceString("OverrideDoesntOverride3","%s")
527+
let OverrideDoesntOverride4E() = DeclareResourceString("OverrideDoesntOverride4","%s")
527528
let UnionCaseWrongArgumentsE() = DeclareResourceString("UnionCaseWrongArguments","%d%d")
528529
let UnionPatternsBindDifferentNamesE() = DeclareResourceString("UnionPatternsBindDifferentNames","")
529530
let RequiredButNotSpecifiedE() = DeclareResourceString("RequiredButNotSpecified","%s%s%s")
@@ -1144,15 +1145,32 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) =
11441145
Printf.bprintf os "%s" msg
11451146
| OverrideDoesntOverride(denv,impl,minfoVirtOpt,g,amap,m) ->
11461147
let sig1 = DispatchSlotChecking.FormatOverride denv impl
1147-
begin match minfoVirtOpt with
1148+
match minfoVirtOpt with
11481149
| None ->
11491150
os.Append(OverrideDoesntOverride1E().Format sig1) |> ignore
1150-
| Some minfoVirt ->
1151-
os.Append(OverrideDoesntOverride2E().Format sig1) |> ignore
1152-
let sig2 = DispatchSlotChecking.FormatMethInfoSig g amap m denv minfoVirt
1153-
if sig1 <> sig2 then
1154-
os.Append(OverrideDoesntOverride3E().Format sig2) |> ignore
1155-
end
1151+
| Some minfoVirt ->
1152+
// https://github.com/Microsoft/visualfsharp/issues/35
1153+
// Improve error message when attempting to override generic return type with unit:
1154+
// we need to check if unit was used as a type argument
1155+
let rec hasUnitTType_app (types: TType list) =
1156+
match types with
1157+
| TType_app (maybeUnit, []) :: ts ->
1158+
match maybeUnit.TypeAbbrev with
1159+
| Some ttype when Tastops.isUnitTy g ttype -> true
1160+
| _ -> hasUnitTType_app ts
1161+
| _ :: ts -> hasUnitTType_app ts
1162+
| [] -> false
1163+
1164+
match minfoVirt.EnclosingType with
1165+
| TType_app (t, types) when t.IsFSharpInterfaceTycon && hasUnitTType_app types ->
1166+
// match abstract member with 'unit' passed as generic argument
1167+
os.Append(OverrideDoesntOverride4E().Format sig1) |> ignore
1168+
| _ ->
1169+
os.Append(OverrideDoesntOverride2E().Format sig1) |> ignore
1170+
let sig2 = DispatchSlotChecking.FormatMethInfoSig g amap m denv minfoVirt
1171+
if sig1 <> sig2 then
1172+
os.Append(OverrideDoesntOverride3E().Format sig2) |> ignore
1173+
11561174
| UnionCaseWrongArguments (_,n1,n2,_) ->
11571175
os.Append(UnionCaseWrongArgumentsE().Format n2 n1) |> ignore
11581176
| UnionPatternsBindDifferentNames _ ->

src/fsharp/FSStrings.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,9 @@
867867
<data name="OverrideDoesntOverride3" xml:space="preserve">
868868
<value> The required signature is '{0}'.</value>
869869
</data>
870+
<data name="OverrideDoesntOverride4" xml:space="preserve">
871+
<value>The member '{0}' is specialized with 'unit' but 'unit' can't be used as return type of an abstract method parameterized on return type.</value>
872+
</data>
870873
<data name="UnionCaseWrongArguments" xml:space="preserve">
871874
<value>This constructor is applied to {0} argument(s) but expects {1}</value>
872875
</data>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// #UnitGenericAbstractType
2+
//<Expects status="success"></Expects>
3+
4+
type Foo<'t> =
5+
abstract member Bar : 't -> int
6+
7+
type Bar() =
8+
interface Foo<unit> with
9+
member x.Bar _ = 1

tests/fsharpqa/Source/Conformance/TypesAndTypeConstraints/TypeParameterDefinitions/env.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
SOURCE=E_LazyInType02.fs SCFLAGS="--test:ErrorRanges" # E_LazyInType02.fs
77
SOURCE=MultipleConstraints01.fs # MultipleConstraints01.fs
88
SOURCE=ValueTypesWithConstraints01.fs # ValueTypesWithConstraints01.fs
9+
SOURCE=UnitSpecialization.fs # UnitSpecialization.fs
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// #ErrorMessages #UnitGenericAbstractType
2+
//<Expects status="error" span="(7,21)" id="FS0017">The member 'Apply : int -> unit' is specialized with 'unit' but 'unit' can't be used as return type of an abstract method parameterized on return type\.</Expects>
3+
type EDF<'S> =
4+
abstract member Apply : int -> 'S
5+
type SomeEDF () =
6+
interface EDF<unit> with
7+
member this.Apply d =
8+
// [ERROR] The member 'Apply' does not have the correct type to override the corresponding abstract method.
9+
()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SOURCE=E_UnitGenericAbstractType1.fs # E_UnitGenericAbstractType1

tests/fsharpqa/Source/test.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ Misc01 Libraries\Core\Reflection
260260
Misc01 Libraries\Core\Unchecked
261261
Misc01 Warnings
262262
Misc01 ErrorMessages\NameResolution
263+
Misc01 ErrorMessages\UnitGenericAbstractType
263264

264265
Misc02 Libraries\Portable
265266
Misc02 Misc

0 commit comments

Comments
 (0)