From 4adb2ddfc500736d882ac7a4a1a5210ba0a59dea Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 16 Sep 2014 17:45:21 +0100 Subject: [PATCH 1/5] Allow inheritance of types that have multiple interface instantiations --- src/fsharp/FSComp.txt | 2 +- src/fsharp/NicePrint.fs | 3 +-- src/fsharp/check.fs | 8 +++++--- src/fsharp/infos.fs | 20 +++++++++---------- src/fsharp/nameres.fs | 10 +++++----- src/fsharp/tastops.fs | 1 + src/fsharp/tastops.fsi | 1 + src/fsharp/tc.fs | 6 +++--- src/fsharp/typrelns.fs | 4 ++-- .../E_ConsumeMultipleInterfaceFromCS.fs | 1 - 10 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index d2584e08261..6c97b2aa561 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -291,7 +291,7 @@ chkUnionCaseDefaultAugmentation,"default augmentation of the union case" 441,chkDuplicatePropertyWithSuffix,"Duplicate property. The property '%s' has the same name and signature as another property in this type once tuples, functions, units of measure and/or provided types are erased." 442,chkDuplicateMethodInheritedType,"Duplicate method. The abstract method '%s' has the same name and signature as an abstract method in an inherited type." 442,chkDuplicateMethodInheritedTypeWithSuffix,"Duplicate method. The abstract method '%s' has the same name and signature as an abstract method in an inherited type once tuples, functions, units of measure and/or provided types are erased." -443,chkMultipleGenericInterfaceInstantiations,"This type implements or inherits the same interface at different generic instantiations '%s' and '%s'. This is not permitted in this version of F#." +443,chkMultipleGenericInterfaceInstantiations,"This type implements the same interface at different generic instantiations '%s' and '%s'. This is not permitted in this version of F#." 444,chkValueWithDefaultValueMustHaveDefaultValue,"The type of a field using the 'DefaultValue' attribute must admit default initialization, i.e. have 'null' as a proper value or be a struct type whose fields all admit default initialization. You can use 'DefaultValue(false)' to disable this check" 445,chkNoByrefInTypeAbbrev,"The type abbreviation contains byrefs. This is not permitted by F#." # ----------------------------------------------------------------------------- diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 04d2a828c95..1ce1fa784b3 100644 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -1385,8 +1385,7 @@ module private TastDefinitionPrinting = GetImmediateInterfacesOfType g amap m ty |> List.map (fun ity -> wordL (if isInterfaceTy g ty then "inherit" else "interface") --- layoutType denv ity) let props = - //GetImmediateIntrinsicPropInfosOfType (None,ad) g amap m ty - GetIntrinsicPropInfosOfType infoReader (None,ad,AllowMultiIntfInstantiations.No) PreferOverrides m ty + GetIntrinsicPropInfosOfType infoReader (None,ad,AllowMultiIntfInstantiations.Yes) PreferOverrides m ty let events = infoReader.GetEventInfosOfType(None,ad,m,ty) diff --git a/src/fsharp/check.fs b/src/fsharp/check.fs index 4caaa250311..3bb0604ba97 100644 --- a/src/fsharp/check.fs +++ b/src/fsharp/check.fs @@ -495,9 +495,9 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) = CheckInterfaceImpls cenv env basev iimpls; CheckTypePermitByrefs cenv m typ let interfaces = - [ yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes typ + [ //yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes typ for (ty,_) in iimpls do - yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes ty ] + yield ty ] |> List.filter (isInterfaceTy cenv.g) CheckMultipleInterfaceInstantiations cenv interfaces m @@ -1379,7 +1379,9 @@ let CheckEntityDefn cenv env (tycon:Entity) = if cenv.reportErrors then if not tycon.IsTypeAbbrev then - CheckMultipleInterfaceInstantiations cenv interfaces m + let typ = generalizedTyconRef (mkLocalTyconRef tycon) + let immediateInterfaces = GetImmediateInterfacesOfType cenv.g cenv.amap m typ + CheckMultipleInterfaceInstantiations cenv immediateInterfaces m // Check struct fields. We check these late because we have to have first checked that the structs are // free of cycles diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 20f3cc3403b..1a175ae77ba 100644 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -215,7 +215,7 @@ let ExistsInEntireHierarchyOfType f g amap m allowMultiIntfInst typ = /// Search for one element where a function returns a 'Some' result, following interfaces let SearchEntireHierarchyOfType f g amap m typ = - FoldHierarchyOfTypeAux true AllowMultiIntfInstantiations.No + FoldHierarchyOfTypeAux true AllowMultiIntfInstantiations.Yes (fun ty acc -> match acc with | None -> if f ty then Some(ty) else None @@ -243,11 +243,11 @@ let HasHeadType g tcref ty2 = /// Check if a type exists somewhere in the hierarchy which has the same head type as the given type (note, the given type need not have a head type at all) let ExistsSameHeadTypeInHierarchy g amap m typeToSearchFrom typeToLookFor = - ExistsInEntireHierarchyOfType (HaveSameHeadType g typeToLookFor) g amap m AllowMultiIntfInstantiations.No typeToSearchFrom + ExistsInEntireHierarchyOfType (HaveSameHeadType g typeToLookFor) g amap m AllowMultiIntfInstantiations.Yes typeToSearchFrom /// Check if a type exists somewhere in the hierarchy which has the given head type. let ExistsHeadTypeInEntireHierarchy g amap m typeToSearchFrom tcrefToLookFor = - ExistsInEntireHierarchyOfType (HasHeadType g tcrefToLookFor) g amap m AllowMultiIntfInstantiations.No typeToSearchFrom + ExistsInEntireHierarchyOfType (HasHeadType g tcrefToLookFor) g amap m AllowMultiIntfInstantiations.Yes typeToSearchFrom /// Read an Abstract IL type from metadata and convert to an F# type. @@ -3145,13 +3145,13 @@ type InfoReader(g:TcGlobals, amap:Import.ImportMap) = FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicPropInfosOfType (optFilter,ad) g amap m typ :: acc) g amap m allowMultiIntfInst typ [] let GetIntrinsicILFieldInfosUncached ((optFilter,ad),m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicILFieldsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.No typ [] + FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicILFieldsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] let GetIntrinsicEventInfosUncached ((optFilter,ad),m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicEventsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.No typ [] + FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicEventsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] let GetIntrinsicRecdOrClassFieldInfosUncached ((optFilter,ad),m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.No typ [] + FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] let GetEntireTypeHierachyUncached (allowMultiIntfInst,m,typ) = FoldEntireHierarchyOfType (fun typ acc -> typ :: acc) g amap m allowMultiIntfInst typ [] @@ -3182,7 +3182,7 @@ type InfoReader(g:TcGlobals, amap:Import.ImportMap) = | _ -> failwith "Unexpected multiple fields with the same name" // Because an explicit name (i.e., nm) was supplied, there will be only one element at most. | _ -> acc) g amap m - AllowMultiIntfInstantiations.No + AllowMultiIntfInstantiations.Yes typ None @@ -3524,12 +3524,12 @@ let TryFindIntrinsicNamedItemOfType (infoReader:InfoReader) (nm,ad) findFlag m t /// -- getting the Dispose method when resolving the 'use' construct /// -- getting the various methods used to desugar the computation expression syntax let TryFindIntrinsicMethInfo infoReader m ad nm ty = - GetIntrinsicMethInfosOfType infoReader (Some nm,ad,AllowMultiIntfInstantiations.No) IgnoreOverrides m ty + GetIntrinsicMethInfosOfType infoReader (Some nm,ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m ty /// Try to find a particular named property on a type. Only used to ensure that local 'let' definitions and property names /// are distinct, a somewhat adhoc check in tc.fs. let TryFindPropInfo infoReader m ad nm ty = - GetIntrinsicPropInfosOfType infoReader (Some nm,ad,AllowMultiIntfInstantiations.No) IgnoreOverrides m ty + GetIntrinsicPropInfosOfType infoReader (Some nm,ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m ty //------------------------------------------------------------------------- // Helpers related to delegates and events @@ -3546,7 +3546,7 @@ let GetSigOfFunctionForDelegate (infoReader:InfoReader) delty m ad = let g = infoReader.g let amap = infoReader.amap let invokeMethInfo = - match GetIntrinsicMethInfosOfType infoReader (Some "Invoke",ad,AllowMultiIntfInstantiations.No) IgnoreOverrides m delty with + match GetIntrinsicMethInfosOfType infoReader (Some "Invoke",ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m delty with | [h] -> h | [] -> error(Error(FSComp.SR.noInvokeMethodsFound (),m)) | h :: _ -> warning(InternalError(FSComp.SR.moreThanOneInvokeMethodFound (),m)); h diff --git a/src/fsharp/nameres.fs b/src/fsharp/nameres.fs index 710c4b8f1b3..b574085e34c 100644 --- a/src/fsharp/nameres.fs +++ b/src/fsharp/nameres.fs @@ -1029,7 +1029,7 @@ let MakeNestedType (ncenv:NameResolver) (tinst:TType list) m (tcrefNested:TyconR /// Get all the accessible nested types of an existing type. let GetNestedTypesOfType (ad, ncenv:NameResolver, optFilter, staticResInfo, checkForGenerated, m) typ = let g = ncenv.g - ncenv.InfoReader.GetPrimaryTypeHierachy(AllowMultiIntfInstantiations.No,m,typ) |> List.collect (fun typ -> + ncenv.InfoReader.GetPrimaryTypeHierachy(AllowMultiIntfInstantiations.Yes,m,typ) |> List.collect (fun typ -> if isAppTy g typ then let tcref,tinst = destAppTy g typ let tycon = tcref.Deref @@ -1371,7 +1371,7 @@ let ResolveObjectConstructor (ncenv:NameResolver) edenv m ad typ = let IntrinsicPropInfosOfTypeInScope (infoReader:InfoReader) (optFilter, ad) findFlag m typ = let g = infoReader.g let amap = infoReader.amap - let pinfos = GetIntrinsicPropInfoSetsOfType infoReader (optFilter, ad, AllowMultiIntfInstantiations.No) findFlag m typ + let pinfos = GetIntrinsicPropInfoSetsOfType infoReader (optFilter, ad, AllowMultiIntfInstantiations.Yes) findFlag m typ let pinfos = pinfos |> ExcludeHiddenOfPropInfos g amap m pinfos @@ -1399,7 +1399,7 @@ let ExtensionPropInfosOfTypeInScope (infoReader:InfoReader) (nenv: NameResolutio let g = infoReader.g let extMemsFromHierarchy = - infoReader.GetEntireTypeHierachy(AllowMultiIntfInstantiations.No,m,typ) |> List.collect (fun typ -> + infoReader.GetEntireTypeHierachy(AllowMultiIntfInstantiations.Yes,m,typ) |> List.collect (fun typ -> if (isAppTy g typ) then let tcref = tcrefOfAppTy g typ let extMemInfos = nenv.eIndexedExtensionMembers.Find tcref @@ -1461,7 +1461,7 @@ let SelectMethInfosFromExtMembers (infoReader:InfoReader) optFilter apparentTy m let ExtensionMethInfosOfTypeInScope (infoReader:InfoReader) (nenv: NameResolutionEnv) optFilter m typ = let extMemsDangling = SelectMethInfosFromExtMembers infoReader optFilter typ m nenv.eUnindexedExtensionMembers let extMemsFromHierarchy = - infoReader.GetEntireTypeHierachy(AllowMultiIntfInstantiations.No,m,typ) |> List.collect (fun typ -> + infoReader.GetEntireTypeHierachy(AllowMultiIntfInstantiations.Yes,m,typ) |> List.collect (fun typ -> let g = infoReader.g if (isAppTy g typ) then let tcref = tcrefOfAppTy g typ @@ -1472,7 +1472,7 @@ let ExtensionMethInfosOfTypeInScope (infoReader:InfoReader) (nenv: NameResolutio /// Get all the available methods of a type (both intrinsic and extension) let AllMethInfosOfTypeInScope infoReader nenv (optFilter,ad) findFlag m typ = - IntrinsicMethInfosOfType infoReader (optFilter,ad,AllowMultiIntfInstantiations.No) findFlag m typ + IntrinsicMethInfosOfType infoReader (optFilter,ad,AllowMultiIntfInstantiations.Yes) findFlag m typ @ ExtensionMethInfosOfTypeInScope infoReader nenv optFilter m typ diff --git a/src/fsharp/tastops.fs b/src/fsharp/tastops.fs index d2e6c1515b4..e23749c8b80 100644 --- a/src/fsharp/tastops.fs +++ b/src/fsharp/tastops.fs @@ -1239,6 +1239,7 @@ type TyconRefMultiMap<'T>(contents: TyconRefMap<'T list>) = member m.Find v = if contents.ContainsKey v then contents.[v] else [] member m.Add (v, x) = TyconRefMultiMap<'T>(contents.Add v (x :: m.Find v)) static member Empty = TyconRefMultiMap<'T>(TyconRefMap<_>.Empty) + static member OfList vs = (vs, TyconRefMultiMap<'T>.Empty) ||> List.foldBack (fun (x,y) acc -> acc.Add (x, y)) //-------------------------------------------------------------------------- diff --git a/src/fsharp/tastops.fsi b/src/fsharp/tastops.fsi index ecbe9fc0dd3..bdef660b93c 100644 --- a/src/fsharp/tastops.fsi +++ b/src/fsharp/tastops.fsi @@ -278,6 +278,7 @@ type TyconRefMultiMap<'T> = member Find : TyconRef -> 'T list member Add : TyconRef * 'T -> TyconRefMultiMap<'T> static member Empty : TyconRefMultiMap<'T> + static member OfList : (TyconRef * 'T) list -> TyconRefMultiMap<'T> //------------------------------------------------------------------------- diff --git a/src/fsharp/tc.fs b/src/fsharp/tc.fs index f7ce39f9caf..a7584e61401 100644 --- a/src/fsharp/tc.fs +++ b/src/fsharp/tc.fs @@ -118,7 +118,7 @@ let IsSecurityAttribute g amap (casmap : Dictionary) (Attrib(tcref,_ if casmap.ContainsKey(tcs) then casmap.[tcs] else - let exists = ExistsInEntireHierarchyOfType (fun t -> typeEquiv g t (mkAppTy attr.TyconRef [])) g amap m AllowMultiIntfInstantiations.No (mkAppTy tcref []) + let exists = ExistsInEntireHierarchyOfType (fun t -> typeEquiv g t (mkAppTy attr.TyconRef [])) g amap m AllowMultiIntfInstantiations.Yes (mkAppTy tcref []) casmap.[tcs] <- exists exists | _ -> false @@ -5603,7 +5603,7 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg cenv.g cenv.amap mWholeExpr - AllowMultiIntfInstantiations.No + AllowMultiIntfInstantiations.Yes e1ty None | _ -> Some "GetSlice" @@ -14111,7 +14111,7 @@ module EstablishTypeDefinitionCores = begin // validate ConditionalAttribute, should it be applied (it's only valid on a type if the type is an attribute type) match attrs |> List.tryFind (IsMatchingFSharpAttribute cenv.g cenv.g.attrib_ConditionalAttribute) with | Some _ -> - if not(ExistsInEntireHierarchyOfType (fun t -> typeEquiv cenv.g t (mkAppTy cenv.g.tcref_System_Attribute [])) cenv.g cenv.amap m AllowMultiIntfInstantiations.No thisTy) then + if not(ExistsInEntireHierarchyOfType (fun t -> typeEquiv cenv.g t (mkAppTy cenv.g.tcref_System_Attribute [])) cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes thisTy) then errorR(Error(FSComp.SR.tcConditionalAttributeUsage(),m)) | _ -> () diff --git a/src/fsharp/typrelns.fs b/src/fsharp/typrelns.fs index 9584dc2a5fb..2674e66c22b 100644 --- a/src/fsharp/typrelns.fs +++ b/src/fsharp/typrelns.fs @@ -1281,7 +1281,7 @@ module DispatchSlotChecking = // This contains the list of required members and the list of available members [ for (_,reqdTy,reqdTyRange,impliedTys) in reqdTyInfos do - // Build a table of the implied interface types, for quicker lookup + // Build a set of the implied interface types, for quicker lookup, by nominal type let isImpliedInterfaceTable = impliedTys |> List.filter (isInterfaceTy g) @@ -1718,7 +1718,7 @@ type CalledMeth<'T> let returnedObjTy = if minfo.IsConstructor then minfo.EnclosingType else methodRetTy unassignedNamedItem |> List.splitChoose (fun (CallerNamedArg(id,e) as arg) -> let nm = id.idText - let pinfos = GetIntrinsicPropInfoSetsOfType infoReader (Some(nm),ad,AllowMultiIntfInstantiations.No) IgnoreOverrides id.idRange returnedObjTy + let pinfos = GetIntrinsicPropInfoSetsOfType infoReader (Some(nm),ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides id.idRange returnedObjTy let pinfos = pinfos |> ExcludeHiddenOfPropInfos g infoReader.amap m match pinfos with | [pinfo] when pinfo.HasSetter && not pinfo.IsIndexer -> diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs index 3696ec6969f..368c54f9954 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs @@ -1,5 +1,4 @@ // #Conformance #ObjectOrientedTypes #InterfacesAndImplementations #ReqNOMT -// This type implements or inherits the same interface at different generic instantiations 'I_002\' and 'I_002\'\. This is not permitted in this version of F#\. #light let mutable res = true From e655395d7a83de36208f737498e7f35c6c98400b Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 17 Sep 2014 16:54:04 +0100 Subject: [PATCH 2/5] update tests for multiple instantiations of interfaces --- .../ConsumeMultipleInterfaceFromCS.fs | 34 ++++++++++++++++++- .../E_ConsumeMultipleInterfaceFromCS.fs | 34 ------------------- .../E_ImplementGenIFaceTwice01.fs | 2 +- .../E_ImplementGenIFaceTwice02.fs | 2 +- .../InterfaceTypes/MultipleInst01.fs | 2 +- .../InterfaceTypes/MultipleInst04.fs | 2 +- .../InterfaceTypes/env.lst | 2 +- tests/fsharpqa/Source/test.lst | 1 + 8 files changed, 39 insertions(+), 40 deletions(-) delete mode 100644 tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/ConsumeMultipleInterfaceFromCS.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/ConsumeMultipleInterfaceFromCS.fs index 8452697e5ef..80c5920c76d 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/ConsumeMultipleInterfaceFromCS.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/ConsumeMultipleInterfaceFromCS.fs @@ -1,5 +1,5 @@ // #Conformance #ObjectOrientedTypes #InterfacesAndImplementations #ReqNOMT -#light +#light let mutable res = true let t = new T() @@ -15,6 +15,7 @@ if (t.Home(0) <> 0) then System.Console.WriteLine("t.Home failed") res <- false +// Check we can use an object expression implementing a C# interface type inheriting multiple instantiations of an interface if ( {new I_003 with member xxx.Home(i) = i member xxx.Me(c:char) = 0 @@ -26,6 +27,37 @@ if ( {new I_003 with System.Console.WriteLine("I_003.Home failed") res <- false +// Check we can use an object expression inheriting from a C# type implementing multiple instantiations of an interface +if (({new T() with + member x.ToString() = "a" + interface I_003 with + member xxx.Home(i) = i + member xxx.Me(c:char) = 0 + member xxx.Me(s:string) = 0 + } :> I_003).Home ( + {new I_002 with + member x.Me (s) = s + }.Me(0) ) <> 0 ) then + System.Console.WriteLine("T.Home obj expr failed") + res <- false + +// Check we can create an object of a C# type implementing multiple instantiations of an interface +if T().Home(4) <> 0 then + System.Console.WriteLine("T.Home failed") + res <- false + + +// Check we can inherit from a C# type implementing multiple instantiations of an interface +type D() = + inherit T() + interface I_003 with + member xxx.Home(i) = i + +if (D() :> I_003).Home(5) <> 5 then + System.Console.WriteLine("D.Home failed") + res <- false + + if (res = true) then exit 0 diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs deleted file mode 100644 index 368c54f9954..00000000000 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs +++ /dev/null @@ -1,34 +0,0 @@ -// #Conformance #ObjectOrientedTypes #InterfacesAndImplementations #ReqNOMT -#light - -let mutable res = true -let t = new T() -if (t.Me("F#") <> 2) then - System.Console.WriteLine("t.Me(string) failed") - res <- false - -if (t.Me('a') <> 1) then - System.Console.WriteLine("t.Me(char) failed") - res <- false - -if (t.Home(0) <> 0) then - System.Console.WriteLine("t.Home failed") - res <- false - -if ( {new I_003 with - member xxx.Home(i) = i - member xxx.Me(c:char) = 0 - member xxx.Me(s:string) = 0 - }.Home ( - {new I_002 with - member x.Me (s) = s - }.Me(0) ) <> 0 ) then - System.Console.WriteLine("I_003.Home failed") - res <- false - -if (res = true) then - exit 0 - - -exit 1 - diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ImplementGenIFaceTwice01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ImplementGenIFaceTwice01.fs index 57ef2707ef0..10927e41457 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ImplementGenIFaceTwice01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ImplementGenIFaceTwice01.fs @@ -3,7 +3,7 @@ // Verify error when trying to implement the same generic interface twice. // Regression for FSB 3574, PE Verification failure when implementing multiple generic interfaces (one generic, one specifc) -//This type implements or inherits the same interface at different generic instantiations 'IA' and 'IA<'b>'\. This is not permitted in this version of F# +//This type implements the same interface at different generic instantiations 'IA' and 'IA<'b>'\. This is not permitted in this version of F# type IA<'b> = interface diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ImplementGenIFaceTwice02.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ImplementGenIFaceTwice02.fs index 66dc07cb4a1..560cb715586 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ImplementGenIFaceTwice02.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ImplementGenIFaceTwice02.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #ObjectOrientedTypes #InterfacesAndImplementations // Verify error when trying to implement the same generic // interface twice -//This type implements or inherits the same interface at different generic instantiations 'IFoo' and 'IFoo'\. This is not permitted in this version of F# +//This type implements the same interface at different generic instantiations 'IFoo' and 'IFoo'\. This is not permitted in this version of F# type IFoo<'a> = interface diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/MultipleInst01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/MultipleInst01.fs index 37f2d6f31fd..057d2da039d 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/MultipleInst01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/MultipleInst01.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #ObjectOrientedTypes #InterfacesAndImplementations // Regression test for FSHARP1.0:5540 // It is forbidden to implement an interface at multiple instantiations -//This type implements or inherits the same interface at different generic instantiations 'IA' and 'IA'\. This is not permitted in this version of F#\.$ +//This type implements the same interface at different generic instantiations 'IA' and 'IA'\. This is not permitted in this version of F#\.$ type IA<'a> = interface diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/MultipleInst04.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/MultipleInst04.fs index 3a3b2f4b4e5..f1a2bc33753 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/MultipleInst04.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/MultipleInst04.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #ObjectOrientedTypes #InterfacesAndImplementations // Regression test for FSHARP1.0:5540 // It is forbidden to implement an interface at multiple instantiations -//This type implements or inherits the same interface at different generic instantiations 'IA' and 'IA'\. This is not permitted in this version of F#\.$ +//This type implements the same interface at different generic instantiations 'IA' and 'IA'\. This is not permitted in this version of F#\.$ type IA<'a, 'b> = diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/env.lst b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/env.lst index 8aac44615a5..f2b2e131c90 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/env.lst +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/env.lst @@ -30,7 +30,7 @@ NoMT SOURCE=CallCSharpInterface.fs PRECMD="\$CSC_PIPE /t:library ConsumeFromFS. SOURCE=E_MultipleInterfaceInheritance.fs SCFLAGS="--test:ErrorRanges --flaterrors" # E_MultipleInterfaceInheritance.fs -NoMT SOURCE=E_ConsumeMultipleInterfaceFromCS.fs PRECMD="\$CSC_PIPE /t:library MultipleInterfaceInheritanceFromCS.cs" SCFLAGS="-r:MultipleInterfaceInheritanceFromCS.dll --test:ErrorRanges" # E_ConsumeMultipleInterfaceFromCS.fs +NoMT SOURCE=ConsumeMultipleInterfaceFromCS.fs PRECMD="\$CSC_PIPE /t:library MultipleInterfaceInheritanceFromCS.cs" SCFLAGS="-r:MultipleInterfaceInheritanceFromCS.dll --test:ErrorRanges" # ConsumeMultipleInterfaceFromCS.fs SOURCE="E_ImplementGenIFaceTwice01.fs" # E_ImplementGenIFaceTwice01.fs SOURCE="E_ImplementGenIFaceTwice02.fs" # E_ImplementGenIFaceTwice02.fs diff --git a/tests/fsharpqa/Source/test.lst b/tests/fsharpqa/Source/test.lst index 637176988ba..94825ee8f2f 100644 --- a/tests/fsharpqa/Source/test.lst +++ b/tests/fsharpqa/Source/test.lst @@ -196,6 +196,7 @@ Conformance06 Conformance\ObjectOrientedTypeDefinitions\ClassTypes\StaticLetDo Conformance07 Conformance\ObjectOrientedTypeDefinitions\ClassTypes\ValueRestriction Conformance07 Conformance\ObjectOrientedTypeDefinitions\DelegateTypes Conformance07 Conformance\ObjectOrientedTypeDefinitions\EnumTypes +InterfaceTypes Conformance\ObjectOrientedTypeDefinitions\InterfaceTypes Conformance07 Conformance\ObjectOrientedTypeDefinitions\InterfaceTypes Conformance07 Conformance\ObjectOrientedTypeDefinitions\StructTypes Conformance07 Conformance\ObjectOrientedTypeDefinitions\TypeExtensions\basic From 12ea9f8fafe35bb9357ae6385cf580bd36bad2e3 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 15 Jan 2015 15:07:31 +0000 Subject: [PATCH 3/5] fix bug exposed by tests --- src/fsharp/check.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/check.fs b/src/fsharp/check.fs index 50b2ccc3705..28236537291 100644 --- a/src/fsharp/check.fs +++ b/src/fsharp/check.fs @@ -492,7 +492,7 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) = let interfaces = [ //yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes typ for (ty,_) in iimpls do - yield ty ] + yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes ty ] |> List.filter (isInterfaceTy cenv.g) CheckMultipleInterfaceInstantiations cenv interfaces m From e532a145d9eb8139c5d51f2324e0c28d3cac51c5 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 15 Jan 2015 15:09:07 +0000 Subject: [PATCH 4/5] fix bug exposed by tests (2) --- src/fsharp/check.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fsharp/check.fs b/src/fsharp/check.fs index 28236537291..803578468db 100644 --- a/src/fsharp/check.fs +++ b/src/fsharp/check.fs @@ -490,7 +490,8 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) = CheckInterfaceImpls cenv env basev iimpls; CheckTypePermitByrefs cenv m typ let interfaces = - [ //yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes typ + [ if isInterfaceTy cenv.g typ then + yield typ //yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes typ for (ty,_) in iimpls do yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes ty ] |> List.filter (isInterfaceTy cenv.g) From 3f7d3224650349918729ad61fe7289227bb26143 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 16 Jan 2015 11:15:13 +0000 Subject: [PATCH 5/5] adjust for more thorough fsharpqa test runs for multiple interfaces --- src/fsharp/check.fs | 7 +- .../Attributes/New/Test06.fs | 2 +- .../E_ObjExprWithSameInterface01.fs | 2 +- .../ConsumeMultipleInterfaceFromCS.fs | 25 +------ .../E_ClassConsumeMultipleInterfaceFromCS.fs | 23 +++++++ .../E_ConsumeMultipleInterfaceFromCS.fs | 68 +++++++++++++++++++ .../InterfaceTypes/env.lst | 4 +- ...InterfaceWithDifferentGenInstantiations.fs | 2 +- 8 files changed, 104 insertions(+), 29 deletions(-) create mode 100644 tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ClassConsumeMultipleInterfaceFromCS.fs create mode 100644 tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs diff --git a/src/fsharp/check.fs b/src/fsharp/check.fs index 803578468db..32d38f9f9ed 100644 --- a/src/fsharp/check.fs +++ b/src/fsharp/check.fs @@ -491,7 +491,7 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) = CheckTypePermitByrefs cenv m typ let interfaces = [ if isInterfaceTy cenv.g typ then - yield typ //yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes typ + yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes typ for (ty,_) in iimpls do yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes ty ] |> List.filter (isInterfaceTy cenv.g) @@ -1370,7 +1370,10 @@ let CheckEntityDefn cenv env (tycon:Entity) = if not tycon.IsTypeAbbrev then let typ = generalizedTyconRef (mkLocalTyconRef tycon) let immediateInterfaces = GetImmediateInterfacesOfType cenv.g cenv.amap m typ - CheckMultipleInterfaceInstantiations cenv immediateInterfaces m + let interfaces = + [ for ty in immediateInterfaces do + yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes ty ] + CheckMultipleInterfaceInstantiations cenv interfaces m // Check struct fields. We check these late because we have to have first checked that the structs are // free of cycles diff --git a/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/New/Test06.fs b/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/New/Test06.fs index 181c7402294..aad6f7dfa1d 100644 --- a/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/New/Test06.fs +++ b/tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/New/Test06.fs @@ -1,5 +1,5 @@ // #Regression #Conformance #TypesAndModules #GeneratedEqualityAndHashing #Attributes -//This type uses an invalid mix of the attributes 'NoEquality', 'ReferenceEquality', 'StructuralEquality', 'NoComparison' and 'StructuralComparison' attributes$ +//This type uses an invalid mix of the attributes 'NoEquality', 'ReferenceEquality', 'StructuralEquality', 'NoComparison' and 'StructuralComparison'$ //A type with attribute 'CustomComparison' must have an explicit implementation of at least one of 'System\.IComparable' or 'System\.Collections\.IStructuralComparable'$ module M06 = diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ObjectExpressions/E_ObjExprWithSameInterface01.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ObjectExpressions/E_ObjExprWithSameInterface01.fs index f73ee06948e..45f0de9b487 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ObjectExpressions/E_ObjExprWithSameInterface01.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/ObjectExpressions/E_ObjExprWithSameInterface01.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions #ObjectConstructors // This was Dev10:854519 and Dev11:5525. The fix was to make this a compile error to avoid a runtime exception. -//This type implements or inherits the same interface at different generic instantiations 'IQueue<'T>' and 'IQueue'\. This is not permitted in this version of F#\.$ +//This type implements the same interface at different generic instantiations 'IQueue<'T>' and 'IQueue'\. This is not permitted in this version of F#\.$ type IQueue<'a> = abstract Addd: 'a -> IQueue<'a> diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/ConsumeMultipleInterfaceFromCS.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/ConsumeMultipleInterfaceFromCS.fs index 80c5920c76d..258e97be58a 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/ConsumeMultipleInterfaceFromCS.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/ConsumeMultipleInterfaceFromCS.fs @@ -15,29 +15,10 @@ if (t.Home(0) <> 0) then System.Console.WriteLine("t.Home failed") res <- false -// Check we can use an object expression implementing a C# interface type inheriting multiple instantiations of an interface -if ( {new I_003 with - member xxx.Home(i) = i - member xxx.Me(c:char) = 0 - member xxx.Me(s:string) = 0 - }.Home ( - {new I_002 with - member x.Me (s) = s - }.Me(0) ) <> 0 ) then - System.Console.WriteLine("I_003.Home failed") - res <- false - // Check we can use an object expression inheriting from a C# type implementing multiple instantiations of an interface if (({new T() with member x.ToString() = "a" - interface I_003 with - member xxx.Home(i) = i - member xxx.Me(c:char) = 0 - member xxx.Me(s:string) = 0 - } :> I_003).Home ( - {new I_002 with - member x.Me (s) = s - }.Me(0) ) <> 0 ) then + } :> I_003).Home (4) <> 0 ) then System.Console.WriteLine("T.Home obj expr failed") res <- false @@ -50,10 +31,8 @@ if T().Home(4) <> 0 then // Check we can inherit from a C# type implementing multiple instantiations of an interface type D() = inherit T() - interface I_003 with - member xxx.Home(i) = i -if (D() :> I_003).Home(5) <> 5 then +if (D() :> I_003).Home(5) <> 0 then System.Console.WriteLine("D.Home failed") res <- false diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ClassConsumeMultipleInterfaceFromCS.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ClassConsumeMultipleInterfaceFromCS.fs new file mode 100644 index 00000000000..ed87e24dbda --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ClassConsumeMultipleInterfaceFromCS.fs @@ -0,0 +1,23 @@ +// #Conformance #ObjectOrientedTypes #InterfacesAndImplementations #ReqNOMT +// This type implements the same interface at different generic instantiations 'I_002\' and 'I_002\'\. This is not permitted in this version of F#\. +#light + +let mutable res = true + +// Check we can't implement an interface inheriting from multiple instantiations of an interface when defining an object expression inheriting from a C# class type +type D() = + inherit T() + interface I_003 with + member xxx.Home(i) = i + +if (D() :> I_003).Home(5) <> 5 then + System.Console.WriteLine("D.Home failed") + res <- false + + +if (res = true) then + exit 0 + + +exit 1 + diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs new file mode 100644 index 00000000000..ce206ece82f --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/E_ConsumeMultipleInterfaceFromCS.fs @@ -0,0 +1,68 @@ +// #Conformance #ObjectOrientedTypes #InterfacesAndImplementations #ReqNOMT +// This type implements the same interface at different generic instantiations 'I_002\' and 'I_002\'\. This is not permitted in this version of F#\. +// This type implements the same interface at different generic instantiations 'I_002\' and 'I_002\'\. This is not permitted in this version of F#\. +#light + +let mutable res = true +let t = new T() +if (t.Me("F#") <> 2) then + System.Console.WriteLine("t.Me(string) failed") + res <- false + +if (t.Me('a') <> 1) then + System.Console.WriteLine("t.Me(char) failed") + res <- false + +if (t.Home(0) <> 0) then + System.Console.WriteLine("t.Home failed") + res <- false + +// Check we can't implement an interface inheriting from multiple instantiations of an interface when defining an object expression implementing a C# interface type +if ( {new I_003 with + member xxx.Home(i) = i + member xxx.Me(c:char) = 0 + member xxx.Me(s:string) = 0 + }.Home ( + {new I_002 with + member x.Me (s) = s + }.Me(0) ) <> 0 ) then + System.Console.WriteLine("I_003.Home failed") + res <- false + +// Check we can't implement an interface inheriting from multiple instantiations of an interface when defining an object expression inheriting from a C# class type +if (({new T() with + member x.ToString() = "a" + interface I_003 with + member xxx.Home(i) = i + member xxx.Me(c:char) = 0 + member xxx.Me(s:string) = 0 + } :> I_003).Home ( + {new I_002 with + member x.Me (s) = s + }.Me(0) ) <> 0 ) then + System.Console.WriteLine("T.Home obj expr failed") + res <- false + +// Check we can create an object of a C# type implementing multiple instantiations of an interface +if T().Home(4) <> 0 then + System.Console.WriteLine("T.Home failed") + res <- false + + +// Check we can't implement an interface inheriting from multiple instantiations of an interface when defining an object expression inheriting from a C# class type +type D() = + inherit T() + interface I_003 with + member xxx.Home(i) = i + +if (D() :> I_003).Home(5) <> 5 then + System.Console.WriteLine("D.Home failed") + res <- false + + +if (res = true) then + exit 0 + + +exit 1 + diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/env.lst b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/env.lst index f2b2e131c90..d41c7253450 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/env.lst +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/InterfaceTypes/env.lst @@ -30,7 +30,9 @@ NoMT SOURCE=CallCSharpInterface.fs PRECMD="\$CSC_PIPE /t:library ConsumeFromFS. SOURCE=E_MultipleInterfaceInheritance.fs SCFLAGS="--test:ErrorRanges --flaterrors" # E_MultipleInterfaceInheritance.fs -NoMT SOURCE=ConsumeMultipleInterfaceFromCS.fs PRECMD="\$CSC_PIPE /t:library MultipleInterfaceInheritanceFromCS.cs" SCFLAGS="-r:MultipleInterfaceInheritanceFromCS.dll --test:ErrorRanges" # ConsumeMultipleInterfaceFromCS.fs +NoMT SOURCE=ConsumeMultipleInterfaceFromCS.fs PRECMD="\$CSC_PIPE /t:library MultipleInterfaceInheritanceFromCS.cs" SCFLAGS="-r:MultipleInterfaceInheritanceFromCS.dll" # ConsumeMultipleInterfaceFromCS.fs +NoMT SOURCE=E_ConsumeMultipleInterfaceFromCS.fs PRECMD="\$CSC_PIPE /t:library MultipleInterfaceInheritanceFromCS.cs" SCFLAGS="-r:MultipleInterfaceInheritanceFromCS.dll --test:ErrorRanges" # E_ConsumeMultipleInterfaceFromCS.fs +NoMT SOURCE=E_ClassConsumeMultipleInterfaceFromCS.fs PRECMD="\$CSC_PIPE /t:library MultipleInterfaceInheritanceFromCS.cs" SCFLAGS="-r:MultipleInterfaceInheritanceFromCS.dll --test:ErrorRanges" # E_ClassConsumeMultipleInterfaceFromCS.fs SOURCE="E_ImplementGenIFaceTwice01.fs" # E_ImplementGenIFaceTwice01.fs SOURCE="E_ImplementGenIFaceTwice02.fs" # E_ImplementGenIFaceTwice02.fs diff --git a/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/TypeChecker/E_GenInterfaceWithDifferentGenInstantiations.fs b/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/TypeChecker/E_GenInterfaceWithDifferentGenInstantiations.fs index 9ae44c8d2e9..b948171d4d1 100644 --- a/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/TypeChecker/E_GenInterfaceWithDifferentGenInstantiations.fs +++ b/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/TypeChecker/E_GenInterfaceWithDifferentGenInstantiations.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #UnitsOfMeasure #TypeInference #TypeConstraints // Regression test for FSHARP1.0:4782 // It is illegal to implement or inherit the same interface at different generic instantiations -//This type implements or inherits the same interface at different generic instantiations 'IA' and 'IA<'b>'\. This is not permitted in this version of F# +//This type implements the same interface at different generic instantiations 'IA' and 'IA<'b>'\. This is not permitted in this version of F# [] type kg