From b180af30343ed275778de68a76653adf31a2d21a Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Sun, 29 Nov 2020 04:40:01 +1100 Subject: [PATCH 01/15] WIP: Set project to not error on warnings. --- .../FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index e732f6fe2e..027e4f7782 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -20,6 +20,10 @@ $(IntermediateOutputPath)$(TargetFramework)\ + + 3239;1182; + + $(BaseOutputPath)\$(Configuration)\$(TargetFramework) From 7c194dcbdee683e97c54b8886aea5ff32eba1160 Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Sun, 29 Nov 2020 04:54:27 +1100 Subject: [PATCH 02/15] WIP: Implement parsing, F# erased type creation/IL generation and pretty print. --- src/fsharp/CheckDeclarations.fs | 3 +- src/fsharp/CheckExpressions.fs | 48 ++++++++++++++++++++++++++++++- src/fsharp/ConstraintSolver.fs | 2 ++ src/fsharp/IlxGen.fs | 3 ++ src/fsharp/NicePrint.fs | 3 ++ src/fsharp/PostInferenceChecks.fs | 1 + src/fsharp/SyntaxTree.fs | 19 ++++++++++++ src/fsharp/TypedTree.fs | 12 +++++++- src/fsharp/TypedTreeOps.fs | 18 ++++++++++-- src/fsharp/TypedTreeOps.fsi | 3 ++ src/fsharp/infos.fs | 13 +++++++++ src/fsharp/pars.fsy | 16 +++++++++++ 12 files changed, 135 insertions(+), 6 deletions(-) diff --git a/src/fsharp/CheckDeclarations.fs b/src/fsharp/CheckDeclarations.fs index abfe10f701..28dacc94aa 100644 --- a/src/fsharp/CheckDeclarations.fs +++ b/src/fsharp/CheckDeclarations.fs @@ -4107,7 +4107,8 @@ module EstablishTypeDefinitionCores = let rec accInAbbrevType ty acc = match stripTyparEqns ty with - | TType_anon (_,l) + | TType_anon (_,l) + | TType_erased_union (_, l) | TType_tuple (_, l) -> accInAbbrevTypes l acc | TType_ucase (UnionCaseRef(tc, _), tinst) | TType_app (tc, tinst) -> diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 5de2ff1d4b..755a6988f3 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -4235,7 +4235,53 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv let item = Item.AnonRecdField(anonInfo, sortedCheckedArgTys, i, x.idRange) CallNameResolutionSink cenv.tcSink (x.idRange,env.NameEnv,item,emptyTyparInst,ItemOccurence.UseInType,env.eAccessRights)) TType_anon(anonInfo, sortedCheckedArgTys),tpenv - + + | SynType.ErasedUnion(synCases, m) -> + // Helper method for eliminating duplicate types from lists of types that form a union type, + // create a disjoint set of cases + // taking into account that a subtype is a "duplicate" of its supertype. + let rec addToCases (pt: TType) (list: ResizeArray) = + if not <| ResizeArray.exists (isObjTy g) list then + if isObjTy g pt then + list.Clear() + list.Add(pt) + elif isErasedUnionTy g pt then + let cases = getErasedUnionCasesTy g pt + for t in cases do addToCases t list + else + let mutable shouldAdd = true + let mutable i = 0 + while i < list.Count && shouldAdd do + let t = list.[i] + if isSubTypeOf cenv.g cenv.amap m pt t then + shouldAdd <- false + elif isSuperTypeOf cenv.g cenv.amap m pt t then + list.RemoveAt(i) + i <- i - 1 // redo this index + i <- i + 1 + if shouldAdd then list.Add pt + + let unionTypeCases = ResizeArray(List.length synCases) + synCases + |> List.map(fun (ErasedUnionCase(typ=ty)) -> TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurence.UseInType env tpenv ty |> fst) + |> List.iter (fun ty -> addToCases ty unionTypeCases) +// |> ListSet.setify (typeEquiv g) +// |> List.sortBy(fun ty -> ty.ToString()) + + let superTypes = + unionTypeCases + |> List.ofSeq + |> List.map (AllPrimarySuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.No) + + let baseType = + List.fold (ListSet.intersect (typeEquiv cenv.g)) (List.head superTypes) (List.tail superTypes) + |> List.head + +// printfn "Types in Union: %0A" (unionTypeCases |> List.ofSeq) +// printfn "SuperTypes in Union: %0A" superTypes + let erasedUnionInfo = ErasedUnionInfo.Create(baseType) + TType_erased_union(erasedUnionInfo, ResizeArray.toList unionTypeCases), tpenv + | SynType.Fun(domainTy, resultTy, _) -> let domainTy', tpenv = TcTypeAndRecover cenv newOk checkCxs occ env tpenv domainTy let resultTy', tpenv = TcTypeAndRecover cenv newOk checkCxs occ env tpenv resultTy diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index a8f2ff5d9d..5e7573f911 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -725,6 +725,7 @@ let rec SimplifyMeasuresInType g resultFirst ((generalizable, generalized) as pa | TType_ucase(_, l) | TType_app (_, l) | TType_anon (_,l) + | TType_erased_union (_,l) | TType_tuple (_, l) -> SimplifyMeasuresInTypes g param l | TType_fun (d, r) -> if resultFirst then SimplifyMeasuresInTypes g param [r;d] else SimplifyMeasuresInTypes g param [d;r] @@ -763,6 +764,7 @@ let rec GetMeasureVarGcdInType v ty = | TType_ucase(_, l) | TType_app (_, l) | TType_anon (_,l) + | TType_erased_union (_,l) | TType_tuple (_, l) -> GetMeasureVarGcdInTypes v l | TType_fun (d, r) -> GcdRational (GetMeasureVarGcdInType v d) (GetMeasureVarGcdInType v r) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 1f541e4bdf..0e51507af4 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -536,6 +536,9 @@ and GenTypeAux amap m (tyenv: TypeReprEnv) voidOK ptrsOK ty = | TType_ucase (ucref, args) -> let cuspec, idx = GenUnionCaseSpec amap m tyenv ucref args EraseUnions.GetILTypeForAlternative cuspec idx + + | TType_erased_union (erasedUnionInfo, _) -> + GenTypeArgAux amap m tyenv erasedUnionInfo.UnionTy | TType_forall (tps, tau) -> let tps = DropErasedTypars tps diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 7062cf1a07..fa5e077e3e 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -700,6 +700,9 @@ module private PrintTypes = layoutTyparRefWithInfo denv env r | TType_measure unt -> layoutMeasure denv unt + + | TType_erased_union (_, t) -> + bracketL (layoutTypesWithInfoAndPrec denv env 2 (wordL (tagPunctuation "|")) t) /// Layout a list of types, separated with the given separator, either '*' or ',' and private layoutTypesWithInfoAndPrec denv env prec sep typl = diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index b3b69aab95..25e3a58aa8 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -374,6 +374,7 @@ let rec CheckTypeDeep (cenv: cenv) ((visitTy, visitTyconRefOpt, visitAppTyOpt, v CheckTypesDeep cenv f g env tys | TType_ucase (_, tinst) -> CheckTypesDeep cenv f g env tinst + | TType_erased_union (_, tys) -> CheckTypesDeep cenv f g env tys | TType_tuple (_, tys) -> CheckTypesDeep cenv f g env tys | TType_fun (s, t) -> CheckTypeDeep cenv f g env true s; CheckTypeDeep cenv f g env true t | TType_var tp -> diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index ac2574e4ea..25a55a44ae 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -454,6 +454,11 @@ type SynType = isStruct: bool * fields:(Ident * SynType) list * range: range + + /// Erased union type definition, type X = (A | B) + | ErasedUnion of + erasedUnionCases: SynErasedUnionCase list * + range: range/// /// F# syntax: type[] | Array of @@ -527,6 +532,7 @@ type SynType = | SynType.Tuple (range=m) | SynType.Array (range=m) | SynType.AnonRecd (range=m) + | SynType.ErasedUnion (range=m) | SynType.Fun (range=m) | SynType.Var (range=m) | SynType.Anon (range=m) @@ -1662,6 +1668,19 @@ type SynUnionCase = match this with | UnionCase (range=m) -> m +[] +type SynErasedUnionCase = + + /// The untyped, unchecked syntax tree for one case in a union definition. + | ErasedUnionCase of + typ: SynType * + xmlDoc: PreXmlDoc * + range: range + + member this.Range = + match this with + | ErasedUnionCase (range=m) -> m + /// Represents the syntax tree for the right-hand-side of union definition, excluding members, /// in either a signature or implementation. [] diff --git a/src/fsharp/TypedTree.fs b/src/fsharp/TypedTree.fs index b5f3bffaf6..fdfcf505e6 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -3953,7 +3953,9 @@ type TType = | TType_ucase of UnionCaseRef * TypeInst /// Indicates the type is a variable type, whether declared, generalized or an inference type parameter - | TType_var of Typar + | TType_var of Typar + + | TType_erased_union of ErasedUnionInfo * TTypes /// Indicates the type is a unit-of-measure expression being used as an argument to a type or member | TType_measure of Measure @@ -3972,6 +3974,7 @@ type TType = | TType_ucase (_uc, _tinst) -> let (TILObjectReprData(scope, _nesting, _definition)) = _uc.Tycon.ILTyconInfo scope.QualifiedName + | TType_erased_union _ -> "" [] member x.DebugText = x.ToString() @@ -3997,6 +4000,7 @@ type TType = | None -> tp.DisplayName | Some _ -> tp.DisplayName + " (solved)" | TType_measure ms -> ms.ToString() + | TType_erased_union (_, l) -> "( " + String.concat " | " (List.map string l) + " )" type TypeInst = TType list @@ -4054,6 +4058,12 @@ type AnonRecdTypeInfo = member x.IsLinked = (match x.SortedIds with null -> true | _ -> false) +[] +type ErasedUnionInfo = + { UnionTy: TType } + static member Create(unionTy: TType) = + { UnionTy = unionTy } + [] type TupInfo = /// Some constant, e.g. true or false for tupInfo diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 54708141bc..a7e90ed6d1 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -193,6 +193,10 @@ let rec remapTypeAux (tyenv: Remap) (ty: TType) = match tyenv.tyconRefRemap.TryFind tcref with | Some tcref' -> TType_ucase (UnionCaseRef(tcref', n), remapTypesAux tyenv tinst) | None -> TType_ucase (UnionCaseRef(tcref, n), remapTypesAux tyenv tinst) + + // SWOORUP TODO: idk whats this + | TType_erased_union _ as ty -> + ty | TType_anon (anonInfo, l) as ty -> let tupInfo' = remapTupInfoAux tyenv anonInfo.TupInfo @@ -809,6 +813,7 @@ let destStructTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupIn let destTyparTy g ty = ty |> stripTyEqns g |> (function TType_var v -> v | _ -> failwith "destTyparTy: not a typar type") let destAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var v -> v | TType_measure unt -> destUnitParMeasure g unt | _ -> failwith "destAnyParTy: not a typar or unpar type") let destMeasureTy g ty = ty |> stripTyEqns g |> (function TType_measure m -> m | _ -> failwith "destMeasureTy: not a unit-of-measure type") +let getErasedUnionCasesTy g ty = ty |> stripTyEqns g |> (function TType_erased_union (_, l) -> l | _ -> failwith "getErasedUnionCasesTy: not an erased union type") let isFunTy g ty = ty |> stripTyEqns g |> (function TType_fun _ -> true | _ -> false) let isForallTy g ty = ty |> stripTyEqns g |> (function TType_forall _ -> true | _ -> false) let isAnyTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple _ -> true | _ -> false) @@ -817,6 +822,7 @@ let isStructTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupInfo let isAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon _ -> true | _ -> false) let isStructAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon (anonInfo, _) -> evalAnonInfoIsStruct anonInfo | _ -> false) let isUnionTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsUnionTycon | _ -> false) +let isErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union _ -> true | _ -> false) let isReprHiddenTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsHiddenReprTycon | _ -> false) let isFSharpObjModelTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsFSharpObjectModelTycon | _ -> false) let isRecdTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsRecordTycon | _ -> false) @@ -1020,6 +1026,7 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = | EraseNone -> measureAEquiv g aenv m1 m2 | _ -> true | _ -> false + // SWOORUP TODO: Erased union here and anonInfoEquiv (anonInfo1: AnonRecdTypeInfo) (anonInfo2: AnonRecdTypeInfo) = @@ -1083,7 +1090,7 @@ let rec getErasedTypes g ty = getErasedTypes g rty | TType_var tp -> if tp.IsErased then [ty] else [] - | TType_app (_, b) | TType_ucase(_, b) | TType_anon (_, b) | TType_tuple (_, b) -> + | TType_app (_, b) | TType_ucase(_, b) | TType_anon (_, b) | TType_tuple (_, b) -> List.foldBack (fun ty tys -> getErasedTypes g ty @ tys) b [] | TType_fun (dty, rty) -> getErasedTypes g dty @ getErasedTypes g rty @@ -2140,6 +2147,8 @@ and accFreeInType opts ty acc = match stripTyparEqns ty with | TType_tuple (tupInfo, l) -> accFreeInTypes opts l (accFreeInTupInfo opts tupInfo acc) | TType_anon (anonInfo, l) -> accFreeInTypes opts l (accFreeInTupInfo opts anonInfo.TupInfo acc) + // SWOOORUP TODO: No idea whatsoever + | TType_erased_union (_, l) -> accFreeInTypes opts l acc | TType_app (tc, tinst) -> let acc = accFreeTycon opts tc acc match tinst with @@ -2243,7 +2252,10 @@ and accFreeInTypeLeftToRight g cxFlag thruFlag acc ty = | TType_app (_, tinst) -> accFreeInTypesLeftToRight g cxFlag thruFlag acc tinst | TType_ucase (_, tinst) -> - accFreeInTypesLeftToRight g cxFlag thruFlag acc tinst + accFreeInTypesLeftToRight g cxFlag thruFlag acc tinst + // SWOORUP TODO: No idea wtf this is + | TType_erased_union (_, tinst) -> + accFreeInTypesLeftToRight g cxFlag thruFlag acc tinst | TType_fun (d, r) -> let dacc = accFreeInTypeLeftToRight g cxFlag thruFlag acc d accFreeInTypeLeftToRight g cxFlag thruFlag dacc r @@ -2680,7 +2692,7 @@ module SimplifyTypes = | TType_forall (_, body) -> foldTypeButNotConstraints f z body | TType_app (_, tys) | TType_ucase (_, tys) - | TType_anon (_, tys) + | TType_anon (_, tys) | TType_tuple (_, tys) -> List.fold (foldTypeButNotConstraints f) z tys | TType_fun (s, t) -> foldTypeButNotConstraints f (foldTypeButNotConstraints f z s) t | TType_var _ -> z diff --git a/src/fsharp/TypedTreeOps.fsi b/src/fsharp/TypedTreeOps.fsi index ecb112426d..2ac1f1eaee 100755 --- a/src/fsharp/TypedTreeOps.fsi +++ b/src/fsharp/TypedTreeOps.fsi @@ -625,6 +625,9 @@ val isStructAnonRecdTy : TcGlobals -> TType -> bool val isAnonRecdTy : TcGlobals -> TType -> bool val isUnionTy : TcGlobals -> TType -> bool +val isErasedUnionTy : TcGlobals -> TType -> bool + +val getErasedUnionCasesTy : TcGlobals -> TType -> TTypes val isReprHiddenTy : TcGlobals -> TType -> bool diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 26ff383c38..78aaaece25 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -266,6 +266,9 @@ let SearchEntireHierarchyOfType f g amap m ty = | None -> if f ty then Some ty else None | Some _ -> acc) g amap m ty None + +let AllPrimarySuperTypesOfType g amap m allowMultiIntfInst ty = + FoldPrimaryHierarchyOfType (ListSet.insert (typeEquiv g)) g amap m allowMultiIntfInst ty [] /// Get all super types of the type, including the type itself let AllSuperTypesOfType g amap m allowMultiIntfInst ty = @@ -289,6 +292,16 @@ let HasHeadType g tcref ty2 = match tryTcrefOfAppTy g ty2 with | ValueSome tcref2 -> tyconRefEq g tcref tcref2 | ValueNone -> false + +let isSubTypeOf g amap m typeToSearchFrom typeToLookFor = + ExistsInEntireHierarchyOfType (typeEquiv g typeToLookFor) g amap m AllowMultiIntfInstantiations.Yes typeToSearchFrom + +let isSuperTypeOf g amap m typeToSearchFrom typeToLookFor = + isSubTypeOf g amap m typeToLookFor typeToSearchFrom + +/// choose 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 ChooseSameHeadTypeInHierarchy g amap m typeToSearchFrom typeToLookFor = + SearchEntireHierarchyOfType (HaveSameHeadType g typeToLookFor) g amap m typeToSearchFrom /// 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 = diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 2f22918350..09a3a0ebd1 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -5012,6 +5012,7 @@ atomTypeOrAnonRecdType: | (Field([], false, Some id, ty, false, _xmldoc, None, _m)) -> Some (id, ty) | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) SynType.AnonRecd (isStruct, flds2, rhs parseState 1) } + | erasedUnionType { SynType.ErasedUnion ($1, (rhs parseState 1, $1 |> List.map(fun (ErasedUnionCase(range = m)) -> m)) ||> List.fold unionRanges) } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ @@ -5085,6 +5086,21 @@ atomType: { if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectedNameAfterToken()) $1 } +/* The core of an erased union type definition */ +erasedUnionType: + /* Note the next three rules are required to disambiguate this from type x = y */ + /* Attributes can only appear on a single constructor if you've used a | */ + | LPAREN attrErasedUnionCaseDecl barAndgrabXmlDoc attrErasedUnionCaseDecls rparen + { ($2 (grabXmlDoc(parseState, 1))) :: $4 $3 } + +attrErasedUnionCaseDecls: + | attrErasedUnionCaseDecl barAndgrabXmlDoc attrErasedUnionCaseDecls { (fun xmlDoc -> $1 xmlDoc :: $3 $2) } + | attrErasedUnionCaseDecl { (fun xmlDoc -> [ $1 xmlDoc ]) } + +/* The core of an anon union case definition */ +attrErasedUnionCaseDecl: + | typ { let mDecl = rhs parseState 3 in (fun xmlDoc -> ErasedUnionCase ($1, xmlDoc, mDecl)) } + typeArgsNoHpaDeprecated: | typeArgsActual { let mLessThan, mGreaterThan, parsedOk, args, commas, mAll = $1 From 2944c4f3cc6572661f4f2dd3da16dbfa2924e315 Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Mon, 30 Nov 2020 00:18:59 +1100 Subject: [PATCH 03/15] Testing constraint solver rules. (Still lot of fails) --- src/fsharp/CheckExpressions.fs | 10 +++------- src/fsharp/ConstraintSolver.fs | 11 ++++++++++- src/fsharp/IlxGen.fs | 2 +- src/fsharp/TypedTree.fs | 7 ++++--- src/fsharp/TypedTreeOps.fs | 26 ++++++++++++++++++++------ src/fsharp/TypedTreeOps.fsi | 9 +++++++-- 6 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 755a6988f3..4f0c0c2260 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -4246,7 +4246,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv list.Clear() list.Add(pt) elif isErasedUnionTy g pt then - let cases = getErasedUnionCasesTy g pt + let cases = getDisjointErasedUnionCasesTyps g pt for t in cases do addToCases t list else let mutable shouldAdd = true @@ -4265,21 +4265,17 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv synCases |> List.map(fun (ErasedUnionCase(typ=ty)) -> TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurence.UseInType env tpenv ty |> fst) |> List.iter (fun ty -> addToCases ty unionTypeCases) -// |> ListSet.setify (typeEquiv g) -// |> List.sortBy(fun ty -> ty.ToString()) let superTypes = unionTypeCases |> List.ofSeq |> List.map (AllPrimarySuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.No) - let baseType = + let commonAncestorTy = List.fold (ListSet.intersect (typeEquiv cenv.g)) (List.head superTypes) (List.tail superTypes) |> List.head -// printfn "Types in Union: %0A" (unionTypeCases |> List.ofSeq) -// printfn "SuperTypes in Union: %0A" superTypes - let erasedUnionInfo = ErasedUnionInfo.Create(baseType) + let erasedUnionInfo = ErasedUnionInfo.Create(commonAncestorTy) TType_erased_union(erasedUnionInfo, ResizeArray.toList unionTypeCases), tpenv | SynType.Fun(domainTy, resultTy, _) -> diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 5e7573f911..a8f29880dc 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -299,6 +299,7 @@ let rec occursCheck g un ty = | TType_ucase(_, l) | TType_app (_, l) | TType_anon(_, l) + | TType_erased_union (_, l) | TType_tuple (_, l) -> List.exists (occursCheck g un) l | TType_fun (d, r) -> occursCheck g un d || occursCheck g un r | TType_var r -> typarEq un r @@ -981,7 +982,7 @@ and SolveAnonInfoEqualsAnonInfo (csenv: ConstraintSolverEnv) m2 (anonInfo1: Anon ErrorD (ConstraintSolverError(message, csenv.m,m2)) else ResultD ()) - + /// Add the constraint "ty1 = ty2" to the constraint problem. /// Propagate all effects of adding this constraint, e.g. to solve type variables and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) (cxsln:(TraitConstraintInfo * TraitConstraintSln) option) ty1 ty2 = @@ -1018,6 +1019,14 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr -> SolveTypeEqualsType csenv ndeep m2 trace None ms (TType_measure Measure.One) | TType_app (tc1, l1), TType_app (tc2, l2) when tyconRefEq g tc1 tc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 + + | TType_app (_,_), TType_erased_union (_, _) -> + if typeAEquiv csenv.g csenv.EquivEnv sty1 sty2 then + CompleteD + else localAbortD + | TType_erased_union (_, _), TType_app (_,_) + | TType_erased_union (_, _), TType_erased_union (_,_) when typeAEquiv csenv.g csenv.EquivEnv sty1 sty2 -> + CompleteD | TType_app (_, _), TType_app (_, _) -> localAbortD | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) -> if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2)) else diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 0e51507af4..b620b7cabb 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -538,7 +538,7 @@ and GenTypeAux amap m (tyenv: TypeReprEnv) voidOK ptrsOK ty = EraseUnions.GetILTypeForAlternative cuspec idx | TType_erased_union (erasedUnionInfo, _) -> - GenTypeArgAux amap m tyenv erasedUnionInfo.UnionTy + GenTypeArgAux amap m tyenv erasedUnionInfo.CommonAncestorTy | TType_forall (tps, tau) -> let tps = DropErasedTypars tps diff --git a/src/fsharp/TypedTree.fs b/src/fsharp/TypedTree.fs index fdfcf505e6..64e588c46e 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -3955,6 +3955,7 @@ type TType = /// Indicates the type is a variable type, whether declared, generalized or an inference type parameter | TType_var of Typar + /// Indicates the type is a union type, containing common ancestor type and the disjoint cases | TType_erased_union of ErasedUnionInfo * TTypes /// Indicates the type is a unit-of-measure expression being used as an argument to a type or member @@ -4060,9 +4061,9 @@ type AnonRecdTypeInfo = [] type ErasedUnionInfo = - { UnionTy: TType } - static member Create(unionTy: TType) = - { UnionTy = unionTy } + { CommonAncestorTy: TType } + static member Create(commonAncestorTy: TType) = + { CommonAncestorTy = commonAncestorTy } [] type TupInfo = diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index a7e90ed6d1..4d42dc4da5 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -194,9 +194,11 @@ let rec remapTypeAux (tyenv: Remap) (ty: TType) = | Some tcref' -> TType_ucase (UnionCaseRef(tcref', n), remapTypesAux tyenv tinst) | None -> TType_ucase (UnionCaseRef(tcref, n), remapTypesAux tyenv tinst) - // SWOORUP TODO: idk whats this - | TType_erased_union _ as ty -> - ty + // Remap single disjoint? + | TType_erased_union (_, l) as ty -> + match l with + | [singleCase] -> singleCase + | _ -> ty | TType_anon (anonInfo, l) as ty -> let tupInfo' = remapTupInfoAux tyenv anonInfo.TupInfo @@ -813,7 +815,6 @@ let destStructTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupIn let destTyparTy g ty = ty |> stripTyEqns g |> (function TType_var v -> v | _ -> failwith "destTyparTy: not a typar type") let destAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var v -> v | TType_measure unt -> destUnitParMeasure g unt | _ -> failwith "destAnyParTy: not a typar or unpar type") let destMeasureTy g ty = ty |> stripTyEqns g |> (function TType_measure m -> m | _ -> failwith "destMeasureTy: not a unit-of-measure type") -let getErasedUnionCasesTy g ty = ty |> stripTyEqns g |> (function TType_erased_union (_, l) -> l | _ -> failwith "getErasedUnionCasesTy: not an erased union type") let isFunTy g ty = ty |> stripTyEqns g |> (function TType_fun _ -> true | _ -> false) let isForallTy g ty = ty |> stripTyEqns g |> (function TType_forall _ -> true | _ -> false) let isAnyTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple _ -> true | _ -> false) @@ -831,7 +832,7 @@ let isFSharpEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) - let isTyparTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | _ -> false) let isAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | TType_measure unt -> isUnitParMeasure g unt | _ -> false) let isMeasureTy g ty = ty |> stripTyEqns g |> (function TType_measure _ -> true | _ -> false) - +let getDisjointErasedUnionCasesTyps g ty = ty |> stripTyEqns g |> (function TType_erased_union (_, l) -> l | _ -> failwith "getDisjointErasedUnionCasesTyps: not an erased union type") let isProvenUnionCaseTy ty = match ty with TType_ucase _ -> true | _ -> false @@ -995,6 +996,7 @@ and tcrefAEquiv g aenv tc1 tc2 = tyconRefEq g tc1 tc2 || (match aenv.EquivTycons.TryFind tc1 with Some v -> tyconRefEq g v tc2 | None -> false) +/// Union types alters the meaning of in such a way the A is equal to (A|B) and typeAEquivAux erasureFlag g aenv ty1 ty2 = let ty1 = stripTyEqnsWrtErasure erasureFlag g ty1 let ty2 = stripTyEqnsWrtErasure erasureFlag g ty2 @@ -1003,6 +1005,12 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = typarsAEquivAux erasureFlag g aenv tps1 tps2 && typeAEquivAux erasureFlag g (aenv.BindEquivTypars tps1 tps2) rty1 rty2 | TType_var tp1, TType_var tp2 when typarEq tp1 tp2 -> true + | TType_var tp1, TType_erased_union (_, tps2) -> + match aenv.EquivTypars.TryFind tp1 with + | Some v -> erasedCaseTypsIsSubsetOfOtherAux erasureFlag g aenv [v] tps2 + | None -> false + | TType_erased_union (_, typs1), TType_app _ -> + erasedCaseTypsIsSubsetOfOtherAux erasureFlag g aenv [ty2] typs1 | TType_var tp1, _ -> match aenv.EquivTypars.TryFind tp1 with | Some v -> typeEquivAux erasureFlag g v ty2 @@ -1024,7 +1032,10 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = | TType_measure m1, TType_measure m2 -> match erasureFlag with | EraseNone -> measureAEquiv g aenv m1 m2 - | _ -> true + | _ -> true + | TType_erased_union (_, l1), TType_erased_union (_, l2) -> + // TODO: Check if entirety is subset + erasedCaseTypsIsSubsetOfOtherAux erasureFlag g aenv l2 l1 | _ -> false // SWOORUP TODO: Erased union here @@ -1053,6 +1064,7 @@ and measureAEquiv g aenv un1 un2 = and typesAEquivAux erasureFlag g aenv l1 l2 = List.lengthsEqAndForall2 (typeAEquivAux erasureFlag g aenv) l1 l2 +and erasedCaseTypsIsSubsetOfOtherAux erasureFlag g aenv l1 l2 = ListSet.isSubsetOf (typeAEquivAux erasureFlag g aenv) l1 l2 and typeEquivAux erasureFlag g ty1 ty2 = typeAEquivAux erasureFlag g TypeEquivEnv.Empty ty1 ty2 let typeAEquiv g aenv ty1 ty2 = typeAEquivAux EraseNone g aenv ty1 ty2 @@ -1061,6 +1073,7 @@ let traitsAEquiv g aenv t1 t2 = traitsAEquivAux EraseNone g aenv t1 t2 let traitKeysAEquiv g aenv t1 t2 = traitKeysAEquivAux EraseNone g aenv t1 t2 let typarConstraintsAEquiv g aenv c1 c2 = typarConstraintsAEquivAux EraseNone g aenv c1 c2 let typarsAEquiv g aenv d1 d2 = typarsAEquivAux EraseNone g aenv d1 d2 +let erasedCaseTypsIsSubsetOfOther g aenv d1 d2 = erasedCaseTypsIsSubsetOfOtherAux EraseNone g aenv d1 d2 let returnTypesAEquiv g aenv t1 t2 = returnTypesAEquivAux EraseNone g aenv t1 t2 let measureEquiv g m1 m2 = measureAEquiv g TypeEquivEnv.Empty m1 m2 @@ -2693,6 +2706,7 @@ module SimplifyTypes = | TType_app (_, tys) | TType_ucase (_, tys) | TType_anon (_, tys) + | TType_erased_union (_, tys) // fold to up | TType_tuple (_, tys) -> List.fold (foldTypeButNotConstraints f) z tys | TType_fun (s, t) -> foldTypeButNotConstraints f (foldTypeButNotConstraints f z s) t | TType_var _ -> z diff --git a/src/fsharp/TypedTreeOps.fsi b/src/fsharp/TypedTreeOps.fsi index 2ac1f1eaee..060ff98676 100755 --- a/src/fsharp/TypedTreeOps.fsi +++ b/src/fsharp/TypedTreeOps.fsi @@ -627,8 +627,6 @@ val isAnonRecdTy : TcGlobals -> TType -> bool val isUnionTy : TcGlobals -> TType -> bool val isErasedUnionTy : TcGlobals -> TType -> bool -val getErasedUnionCasesTy : TcGlobals -> TType -> TTypes - val isReprHiddenTy : TcGlobals -> TType -> bool val isFSharpObjModelTy : TcGlobals -> TType -> bool @@ -844,6 +842,7 @@ val typarConstraintsAEquivAux : Erasure -> TcGlobals -> TypeEquivEnv -> TyparCon val typarConstraintsAEquiv : TcGlobals -> TypeEquivEnv -> TyparConstraint -> TyparConstraint -> bool val typarsAEquiv : TcGlobals -> TypeEquivEnv -> Typars -> Typars -> bool +val erasedCaseTypsIsSubsetOfOther : TcGlobals -> TypeEquivEnv -> TTypes -> TTypes -> bool val typeAEquivAux : Erasure -> TcGlobals -> TypeEquivEnv -> TType -> TType -> bool @@ -2219,6 +2218,12 @@ val AdjustPossibleSubsumptionExpr : TcGlobals -> Expr -> Exprs -> (Expr * Exprs) val NormalizeAndAdjustPossibleSubsumptionExprs : TcGlobals -> Expr -> Expr +//------------------------------------------------------------------------- +// Erased union constructors +//------------------------------------------------------------------------- + +val getDisjointErasedUnionCasesTyps : TcGlobals -> TType -> TTypes + //------------------------------------------------------------------------- // XmlDoc signatures, used by both VS mode and XML-help emit //------------------------------------------------------------------------- From 0f5140b59ab39a353154bb98efdfe9afc2185304 Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Tue, 1 Dec 2020 17:10:10 +1100 Subject: [PATCH 04/15] [WIP] Don't subsume on typeEqui instead only test when explicitly coerce as current F# spec --- src/fsharp/CheckExpressions.fs | 36 ++++++++++++++++++---------------- src/fsharp/ConstraintSolver.fs | 34 ++++++++++++++++++++++++-------- src/fsharp/TypeRelations.fs | 1 + src/fsharp/TypedTree.fs | 10 +++++++--- src/fsharp/TypedTreeOps.fs | 12 ++---------- 5 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 4f0c0c2260..aa7fc51505 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -2849,7 +2849,7 @@ let TcStaticUpcast cenv denv m tgtTy srcTy = error(IndeterminateStaticCoercion(denv, srcTy, tgtTy, m)) //else warning(UpcastUnnecessary m) - if isSealedTy cenv.g tgtTy && not (isTyparTy cenv.g tgtTy) then + if isSealedTy cenv.g tgtTy && not (isTyparTy cenv.g tgtTy) && not (isErasedUnionTy cenv.g tgtTy) then warning(CoercionTargetSealed(denv, tgtTy, m)) if typeEquiv cenv.g srcTy tgtTy then @@ -4260,23 +4260,25 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv i <- i - 1 // redo this index i <- i + 1 if shouldAdd then list.Add pt + let createCases synCases = + let unionTypeCases = ResizeArray() + do + synCases + |> List.map(fun (ErasedUnionCase(typ=ty)) -> TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurence.UseInType env tpenv ty |> fst) + |> List.iter (fun ty -> addToCases ty unionTypeCases) + ResizeArray.toList unionTypeCases - let unionTypeCases = ResizeArray(List.length synCases) - synCases - |> List.map(fun (ErasedUnionCase(typ=ty)) -> TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurence.UseInType env tpenv ty |> fst) - |> List.iter (fun ty -> addToCases ty unionTypeCases) - - let superTypes = - unionTypeCases - |> List.ofSeq - |> List.map (AllPrimarySuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.No) - - let commonAncestorTy = - List.fold (ListSet.intersect (typeEquiv cenv.g)) (List.head superTypes) (List.tail superTypes) - |> List.head + let cases = createCases synCases + let superTypes = List.map (AllPrimarySuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.No) cases + let commonAncestorTy = List.fold (ListSet.intersect (typeEquiv cenv.g)) (List.head superTypes) (List.tail superTypes) |> List.head - let erasedUnionInfo = ErasedUnionInfo.Create(commonAncestorTy) - TType_erased_union(erasedUnionInfo, ResizeArray.toList unionTypeCases), tpenv + let (sourceOrderIndices, cases') = + cases + |> List.indexed + |> List.sortBy (fun ty -> ty.ToString()) + |> List.unzip + let erasedUnionInfo = ErasedUnionInfo.Create(commonAncestorTy, sourceOrderIndices) + TType_erased_union(erasedUnionInfo, cases'), tpenv | SynType.Fun(domainTy, resultTy, _) -> let domainTy', tpenv = TcTypeAndRecover cenv newOk checkCxs occ env tpenv domainTy @@ -5519,7 +5521,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = | SynExpr.Typed (synBodyExpr, synType, m) -> let tgtTy, tpenv = TcTypeAndRecover cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv synType UnifyTypes cenv env m overallTy tgtTy - let expr, tpenv = TcExpr cenv overallTy env tpenv synBodyExpr + let expr, tpenv = TcExpr cenv overallTy env tpenv synBodyExpr expr, tpenv // e :? ty diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index a8f29880dc..60691243d9 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -299,7 +299,6 @@ let rec occursCheck g un ty = | TType_ucase(_, l) | TType_app (_, l) | TType_anon(_, l) - | TType_erased_union (_, l) | TType_tuple (_, l) -> List.exists (occursCheck g un) l | TType_fun (d, r) -> occursCheck g un d || occursCheck g un r | TType_var r -> typarEq un r @@ -1020,12 +1019,7 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr | TType_app (tc1, l1), TType_app (tc2, l2) when tyconRefEq g tc1 tc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 - | TType_app (_,_), TType_erased_union (_, _) -> - if typeAEquiv csenv.g csenv.EquivEnv sty1 sty2 then - CompleteD - else localAbortD - | TType_erased_union (_, _), TType_app (_,_) - | TType_erased_union (_, _), TType_erased_union (_,_) when typeAEquiv csenv.g csenv.EquivEnv sty1 sty2 -> + | TType_erased_union (_, l1), TType_erased_union (_,l2) when ListSet.equals (typeAEquiv g aenv) l2 l1 -> CompleteD | TType_app (_, _), TType_app (_, _) -> localAbortD | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) -> @@ -1076,6 +1070,26 @@ and SolveFunTypeEqn csenv ndeep m2 trace cxsln d1 d2 r1 r2 = trackErrors { return! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln r1 r2 } +// ty1: expected +// ty2: actual +// +// "ty2 casts to any of the disjoint cases of ty1" +// "a value of type ty2 can be used where a value of type ty1 is expected" +and SolveErasedUnionTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) cxsln ty1Cases ty2 = + let g = csenv.g + let aenv = csenv.EquivEnv + match ty2 with + // What if TType_app wraps another TType_erased_union + | TType_app (_,_) when ListSet.contains (typeAEquiv g aenv) ty2 ty1Cases -> + match List.tryFind (typeAEquiv g aenv ty2) ty1Cases with + | Some v1 -> + SolveTypeSubsumesType csenv ndeep m2 trace cxsln v1 ty2 + | None -> failwithf "SolveErasedUnionTypeSubsumesType failed" + | TType_erased_union (_,l2) when ListSet.isSubsetOf (typeAEquiv g aenv) l2 ty1Cases -> + let subset1 = ListSet.intersect (typeAEquiv g aenv) l2 ty1Cases + SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln subset1 l2 + | _ -> failwithf "SolveErasedUnionTypeSubsumesType: Should never reach here" + // ty1: expected // ty2: actual // @@ -1143,7 +1157,11 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 - + + | TType_erased_union (_, l1), TType_app (_,_) when ListSet.contains (typeAEquiv g aenv) sty2 l1 -> + SolveErasedUnionTypeSubsumesType csenv ndeep m2 trace cxsln l1 sty2 + | TType_erased_union (_, l1), TType_erased_union (_, l2) when ListSet.isSubsetOf (typeAEquiv g aenv) l2 l1 -> + SolveErasedUnionTypeSubsumesType csenv ndeep m2 trace cxsln l1 sty2 | _ -> // By now we know the type is not a variable type diff --git a/src/fsharp/TypeRelations.fs b/src/fsharp/TypeRelations.fs index 487d8f96c3..2d25d380be 100755 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -94,6 +94,7 @@ let TypesFeasiblyEquivStripMeasures g amap m ty1 ty2 = TypesFeasiblyEquivalent true 0 g amap m ty1 ty2 /// The feasible coercion relation. Part of the language spec. +/// Test whether ty2 :> ty1, for erased union (A|B :> A) let rec TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce ty2 = if ndeep > 100 then error(InternalError("recursive class hierarchy (detected in TypeFeasiblySubsumesType), ty1 = " + (DebugPrint.showType ty1), m)) let ty1 = stripTyEqns g ty1 diff --git a/src/fsharp/TypedTree.fs b/src/fsharp/TypedTree.fs index 64e588c46e..b709eae7da 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -4061,9 +4061,13 @@ type AnonRecdTypeInfo = [] type ErasedUnionInfo = - { CommonAncestorTy: TType } - static member Create(commonAncestorTy: TType) = - { CommonAncestorTy = commonAncestorTy } + { /// the common ancestor type for all cases in this union type + CommonAncestorTy: TType + /// as sorted in source + CaseSourceSortingIndices: int list } + static member Create(commonAncestorTy: TType, caseSourceSortingIndices) = + { CommonAncestorTy = commonAncestorTy + CaseSourceSortingIndices = caseSourceSortingIndices } [] type TupInfo = diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 4d42dc4da5..4bc2febe8c 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -996,7 +996,7 @@ and tcrefAEquiv g aenv tc1 tc2 = tyconRefEq g tc1 tc2 || (match aenv.EquivTycons.TryFind tc1 with Some v -> tyconRefEq g v tc2 | None -> false) -/// Union types alters the meaning of in such a way the A is equal to (A|B) +/// Test ty1 = ty2 and typeAEquivAux erasureFlag g aenv ty1 ty2 = let ty1 = stripTyEqnsWrtErasure erasureFlag g ty1 let ty2 = stripTyEqnsWrtErasure erasureFlag g ty2 @@ -1005,12 +1005,6 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = typarsAEquivAux erasureFlag g aenv tps1 tps2 && typeAEquivAux erasureFlag g (aenv.BindEquivTypars tps1 tps2) rty1 rty2 | TType_var tp1, TType_var tp2 when typarEq tp1 tp2 -> true - | TType_var tp1, TType_erased_union (_, tps2) -> - match aenv.EquivTypars.TryFind tp1 with - | Some v -> erasedCaseTypsIsSubsetOfOtherAux erasureFlag g aenv [v] tps2 - | None -> false - | TType_erased_union (_, typs1), TType_app _ -> - erasedCaseTypsIsSubsetOfOtherAux erasureFlag g aenv [ty2] typs1 | TType_var tp1, _ -> match aenv.EquivTypars.TryFind tp1 with | Some v -> typeEquivAux erasureFlag g v ty2 @@ -1034,10 +1028,8 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = | EraseNone -> measureAEquiv g aenv m1 m2 | _ -> true | TType_erased_union (_, l1), TType_erased_union (_, l2) -> - // TODO: Check if entirety is subset - erasedCaseTypsIsSubsetOfOtherAux erasureFlag g aenv l2 l1 + typesAEquivAux erasureFlag g aenv l1 l2 | _ -> false - // SWOORUP TODO: Erased union here and anonInfoEquiv (anonInfo1: AnonRecdTypeInfo) (anonInfo2: AnonRecdTypeInfo) = From 53c25d376d362b45d3162be022dc8000a677632c Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Tue, 1 Dec 2020 17:13:42 +1100 Subject: [PATCH 05/15] Remove ugly methods no longer required. --- src/fsharp/TypedTreeOps.fs | 2 -- src/fsharp/TypedTreeOps.fsi | 1 - 2 files changed, 3 deletions(-) diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 4bc2febe8c..f637cc9b9d 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -1056,7 +1056,6 @@ and measureAEquiv g aenv un1 un2 = and typesAEquivAux erasureFlag g aenv l1 l2 = List.lengthsEqAndForall2 (typeAEquivAux erasureFlag g aenv) l1 l2 -and erasedCaseTypsIsSubsetOfOtherAux erasureFlag g aenv l1 l2 = ListSet.isSubsetOf (typeAEquivAux erasureFlag g aenv) l1 l2 and typeEquivAux erasureFlag g ty1 ty2 = typeAEquivAux erasureFlag g TypeEquivEnv.Empty ty1 ty2 let typeAEquiv g aenv ty1 ty2 = typeAEquivAux EraseNone g aenv ty1 ty2 @@ -1065,7 +1064,6 @@ let traitsAEquiv g aenv t1 t2 = traitsAEquivAux EraseNone g aenv t1 t2 let traitKeysAEquiv g aenv t1 t2 = traitKeysAEquivAux EraseNone g aenv t1 t2 let typarConstraintsAEquiv g aenv c1 c2 = typarConstraintsAEquivAux EraseNone g aenv c1 c2 let typarsAEquiv g aenv d1 d2 = typarsAEquivAux EraseNone g aenv d1 d2 -let erasedCaseTypsIsSubsetOfOther g aenv d1 d2 = erasedCaseTypsIsSubsetOfOtherAux EraseNone g aenv d1 d2 let returnTypesAEquiv g aenv t1 t2 = returnTypesAEquivAux EraseNone g aenv t1 t2 let measureEquiv g m1 m2 = measureAEquiv g TypeEquivEnv.Empty m1 m2 diff --git a/src/fsharp/TypedTreeOps.fsi b/src/fsharp/TypedTreeOps.fsi index 060ff98676..c98c5616f0 100755 --- a/src/fsharp/TypedTreeOps.fsi +++ b/src/fsharp/TypedTreeOps.fsi @@ -842,7 +842,6 @@ val typarConstraintsAEquivAux : Erasure -> TcGlobals -> TypeEquivEnv -> TyparCon val typarConstraintsAEquiv : TcGlobals -> TypeEquivEnv -> TyparConstraint -> TyparConstraint -> bool val typarsAEquiv : TcGlobals -> TypeEquivEnv -> Typars -> Typars -> bool -val erasedCaseTypsIsSubsetOfOther : TcGlobals -> TypeEquivEnv -> TTypes -> TTypes -> bool val typeAEquivAux : Erasure -> TcGlobals -> TypeEquivEnv -> TType -> TType -> bool From 9ee97f9e6c56d0e6458726d00e1e1a6a2595d446 Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Tue, 1 Dec 2020 22:51:07 +1100 Subject: [PATCH 06/15] Allow downcast to a erased union one or more subtypes --- src/fsharp/TypedTreeOps.fs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index f637cc9b9d..1ec6cabd72 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -823,11 +823,12 @@ let isStructTupleTy g ty = ty |> stripTyEqns g |> (function TType_tuple (tupInfo let isAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon _ -> true | _ -> false) let isStructAnonRecdTy g ty = ty |> stripTyEqns g |> (function TType_anon (anonInfo, _) -> evalAnonInfoIsStruct anonInfo | _ -> false) let isUnionTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsUnionTycon | _ -> false) -let isErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union _ -> true | _ -> false) let isReprHiddenTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsHiddenReprTycon | _ -> false) let isFSharpObjModelTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsFSharpObjectModelTycon | _ -> false) let isRecdTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsRecordTycon | _ -> false) let isFSharpStructOrEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsFSharpStructOrEnumTycon | _ -> false) +let isErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union _ -> true | _ -> false) +let isStructErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union (erasedUnionInfo, _) -> isFSharpStructOrEnumTy g erasedUnionInfo.CommonAncestorTy | _ -> false) let isFSharpEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsFSharpEnumTycon | _ -> false) let isTyparTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | _ -> false) let isAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | TType_measure unt -> isUnitParMeasure g unt | _ -> false) @@ -1093,7 +1094,7 @@ let rec getErasedTypes g ty = getErasedTypes g rty | TType_var tp -> if tp.IsErased then [ty] else [] - | TType_app (_, b) | TType_ucase(_, b) | TType_anon (_, b) | TType_tuple (_, b) -> + | TType_app (_, b) | TType_ucase(_, b) | TType_anon (_, b) | TType_tuple (_, b) | TType_erased_union (_, b) -> List.foldBack (fun ty tys -> getErasedTypes g ty @ tys) b [] | TType_fun (dty, rty) -> getErasedTypes g dty @ getErasedTypes g rty @@ -1829,7 +1830,7 @@ let isStructTy g ty = | ValueSome tcref -> isStructTyconRef tcref | _ -> - isStructAnonRecdTy g ty || isStructTupleTy g ty + isStructAnonRecdTy g ty || isStructTupleTy g ty || isStructErasedUnionTy g ty let isRefTy g ty = not (isStructOrEnumTyconTy g ty) && @@ -1842,7 +1843,8 @@ let isRefTy g ty = isReprHiddenTy g ty || isFSharpObjModelRefTy g ty || isUnitTy g ty || - (isAnonRecdTy g ty && not (isStructAnonRecdTy g ty)) + (isAnonRecdTy g ty && not (isStructAnonRecdTy g ty)) || + (isErasedUnionTy g ty && not (isStructErasedUnionTy g ty)) ) let isForallFunctionTy g ty = @@ -8385,9 +8387,13 @@ let MemberIsCompiledAsInstance g parent isExtensionMember (membInfo: ValMemberIn let isSealedTy g ty = let ty = stripTyEqnsAndMeasureEqns g ty - not (isRefTy g ty) || - isUnitTy g ty || - isArrayTy g ty || + let isRefTy' = isRefTy g ty + let isUnitTy' = isUnitTy g ty + let isArrayTy' = isArrayTy g ty + + not (isRefTy') || + isUnitTy' || + isArrayTy' || match metadataOfTy g ty with #if !NO_EXTENSIONTYPING @@ -8398,7 +8404,9 @@ let isSealedTy g ty = if (isFSharpInterfaceTy g ty || isFSharpClassTy g ty) then let tcref = tcrefOfAppTy g ty TryFindFSharpBoolAttribute g g.attrib_SealedAttribute tcref.Attribs = Some true - else + elif (isErasedUnionTy g ty) then + false + else // All other F# types, array, byref, tuple types are sealed true From f73fbcbc647cf73dbfd5bbce6d620f9916b90a02 Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Wed, 2 Dec 2020 22:28:44 +1100 Subject: [PATCH 07/15] Use ListSet instead for equality check in union types. Maintain source order while pretty print --- src/fsharp/CheckExpressions.fs | 38 ++++++++++++++++++++-------------- src/fsharp/ConstraintSolver.fs | 4 ++-- src/fsharp/NicePrint.fs | 12 +++++++++-- src/fsharp/TypedTree.fs | 10 ++++----- src/fsharp/TypedTreeOps.fs | 20 ++++++++++++++---- src/fsharp/TypedTreeOps.fsi | 4 ++-- 6 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index aa7fc51505..fc569eb33d 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -2849,7 +2849,7 @@ let TcStaticUpcast cenv denv m tgtTy srcTy = error(IndeterminateStaticCoercion(denv, srcTy, tgtTy, m)) //else warning(UpcastUnnecessary m) - if isSealedTy cenv.g tgtTy && not (isTyparTy cenv.g tgtTy) && not (isErasedUnionTy cenv.g tgtTy) then + if isSealedTy cenv.g tgtTy && not (isTyparTy cenv.g tgtTy) then warning(CoercionTargetSealed(denv, tgtTy, m)) if typeEquiv cenv.g srcTy tgtTy then @@ -4246,8 +4246,9 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv list.Clear() list.Add(pt) elif isErasedUnionTy g pt then - let cases = getDisjointErasedUnionCasesTyps g pt - for t in cases do addToCases t list + let otherUnsortedCases = tryUnsortedErasedUnionTyCases g pt |> ValueOption.defaultValue [] + for otherCase in otherUnsortedCases + do addToCases otherCase list else let mutable shouldAdd = true let mutable i = 0 @@ -4260,25 +4261,32 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv i <- i - 1 // redo this index i <- i + 1 if shouldAdd then list.Add pt - let createCases synCases = + + let createDisjointTypes synErasedUnionCases = let unionTypeCases = ResizeArray() do - synCases + synErasedUnionCases |> List.map(fun (ErasedUnionCase(typ=ty)) -> TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurence.UseInType env tpenv ty |> fst) |> List.iter (fun ty -> addToCases ty unionTypeCases) ResizeArray.toList unionTypeCases - - let cases = createCases synCases - let superTypes = List.map (AllPrimarySuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.No) cases - let commonAncestorTy = List.fold (ListSet.intersect (typeEquiv cenv.g)) (List.head superTypes) (List.tail superTypes) |> List.head - let (sourceOrderIndices, cases') = - cases + let commonAncestorTy g amap tys = + let superTypes = List.map (AllPrimarySuperTypesOfType g amap m AllowMultiIntfInstantiations.No) tys + List.fold (ListSet.intersect (typeEquiv g)) (List.head superTypes) (List.tail superTypes) |> List.head + + // Sort into order for ordered equality + let sortedIndexedErasedUnionCases = + createDisjointTypes synCases |> List.indexed - |> List.sortBy (fun ty -> ty.ToString()) - |> List.unzip - let erasedUnionInfo = ErasedUnionInfo.Create(commonAncestorTy, sourceOrderIndices) - TType_erased_union(erasedUnionInfo, cases'), tpenv + |> List.sortBy (snd >> stripTyEqnsAndMeasureEqns g >> string) + + // Map from sorted indexes to unsorted index + let sigma = List.map fst sortedIndexedErasedUnionCases |> List.toArray + let sortedErasedUnionCases = List.map snd sortedIndexedErasedUnionCases + let commonAncestorTy = commonAncestorTy g cenv.amap sortedErasedUnionCases + + let erasedUnionInfo = ErasedUnionInfo.Create(commonAncestorTy, sigma) + TType_erased_union(erasedUnionInfo, sortedErasedUnionCases), tpenv | SynType.Fun(domainTy, resultTy, _) -> let domainTy', tpenv = TcTypeAndRecover cenv newOk checkCxs occ env tpenv domainTy diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 60691243d9..2adee56f84 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -1019,8 +1019,6 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr | TType_app (tc1, l1), TType_app (tc2, l2) when tyconRefEq g tc1 tc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 - | TType_erased_union (_, l1), TType_erased_union (_,l2) when ListSet.equals (typeAEquiv g aenv) l2 l1 -> - CompleteD | TType_app (_, _), TType_app (_, _) -> localAbortD | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) -> if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2)) else @@ -1038,6 +1036,8 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty1 rty2 | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 + | TType_erased_union _, TType_erased_union _ when typeAEquiv g aenv sty1 sty2 -> + CompleteD | _ -> localAbortD diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index fa5e077e3e..c13114b9d3 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -701,8 +701,16 @@ module private PrintTypes = | TType_measure unt -> layoutMeasure denv unt - | TType_erased_union (_, t) -> - bracketL (layoutTypesWithInfoAndPrec denv env 2 (wordL (tagPunctuation "|")) t) + | TType_erased_union (unionInfo, types) -> + let sigma = unionInfo.UnsortedCaseSourceIndices + + let unsortedTyps = + types + |> List.indexed + |> List.sortBy (fun (sortedIdx, _) -> sigma.[sortedIdx]) + |> List.map snd + + bracketL (layoutTypesWithInfoAndPrec denv env 2 (wordL (tagPunctuation "|")) unsortedTyps) /// Layout a list of types, separated with the given separator, either '*' or ',' and private layoutTypesWithInfoAndPrec denv env prec sep typl = diff --git a/src/fsharp/TypedTree.fs b/src/fsharp/TypedTree.fs index b709eae7da..f5e49bb8cd 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -4061,13 +4061,13 @@ type AnonRecdTypeInfo = [] type ErasedUnionInfo = - { /// the common ancestor type for all cases in this union type + { /// Common ancestor type for all cases in this union, used for ILgen CommonAncestorTy: TType - /// as sorted in source - CaseSourceSortingIndices: int list } - static member Create(commonAncestorTy: TType, caseSourceSortingIndices) = + /// Indices representing order of cases they were defined in + UnsortedCaseSourceIndices: int [] } + static member Create(commonAncestorTy: TType, unsortedCaseSourceIndices: int[]) = { CommonAncestorTy = commonAncestorTy - CaseSourceSortingIndices = caseSourceSortingIndices } + UnsortedCaseSourceIndices = unsortedCaseSourceIndices } [] type TupInfo = diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 1ec6cabd72..194dd47fc4 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -828,13 +828,11 @@ let isFSharpObjModelTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, let isRecdTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsRecordTycon | _ -> false) let isFSharpStructOrEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsFSharpStructOrEnumTycon | _ -> false) let isErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union _ -> true | _ -> false) -let isStructErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union (erasedUnionInfo, _) -> isFSharpStructOrEnumTy g erasedUnionInfo.CommonAncestorTy | _ -> false) +let isStructErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union (unionInfo, _) -> isFSharpStructOrEnumTy g unionInfo.CommonAncestorTy | _ -> false) let isFSharpEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsFSharpEnumTycon | _ -> false) let isTyparTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | _ -> false) let isAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | TType_measure unt -> isUnitParMeasure g unt | _ -> false) let isMeasureTy g ty = ty |> stripTyEqns g |> (function TType_measure _ -> true | _ -> false) -let getDisjointErasedUnionCasesTyps g ty = ty |> stripTyEqns g |> (function TType_erased_union (_, l) -> l | _ -> failwith "getDisjointErasedUnionCasesTyps: not an erased union type") - let isProvenUnionCaseTy ty = match ty with TType_ucase _ -> true | _ -> false let mkAppTy tcref tyargs = TType_app(tcref, tyargs) @@ -855,6 +853,20 @@ let (|AppTy|_|) g ty = ty |> stripTyEqns g |> (function TType_app(tcref, tinst) let (|RefTupleTy|_|) g ty = ty |> stripTyEqns g |> (function TType_tuple(tupInfo, tys) when not (evalTupInfoIsStruct tupInfo) -> Some tys | _ -> None) let (|FunTy|_|) g ty = ty |> stripTyEqns g |> (function TType_fun(dty, rty) -> Some (dty, rty) | _ -> None) +let tryUnsortedErasedUnionTyCases g ty = + let ty = ty |> stripTyEqns g + match ty with + | TType_erased_union (unionInfo, tys) -> + let sigma = unionInfo.UnsortedCaseSourceIndices + let unsortedTyps = + tys + |> List.indexed + |> List.sortBy (fun (sortedIdx, _) -> sigma.[sortedIdx]) + |> List.map snd + + ValueSome (unsortedTyps) + | _ -> ValueNone + let tryNiceEntityRefOfTy ty = let ty = stripTyparEqnsAux false ty match ty with @@ -1029,7 +1041,7 @@ and typeAEquivAux erasureFlag g aenv ty1 ty2 = | EraseNone -> measureAEquiv g aenv m1 m2 | _ -> true | TType_erased_union (_, l1), TType_erased_union (_, l2) -> - typesAEquivAux erasureFlag g aenv l1 l2 + ListSet.equals (typeAEquivAux erasureFlag g aenv) l1 l2 | _ -> false diff --git a/src/fsharp/TypedTreeOps.fsi b/src/fsharp/TypedTreeOps.fsi index c98c5616f0..e44d6e954d 100755 --- a/src/fsharp/TypedTreeOps.fsi +++ b/src/fsharp/TypedTreeOps.fsi @@ -2218,10 +2218,10 @@ val AdjustPossibleSubsumptionExpr : TcGlobals -> Expr -> Exprs -> (Expr * Exprs) val NormalizeAndAdjustPossibleSubsumptionExprs : TcGlobals -> Expr -> Expr //------------------------------------------------------------------------- -// Erased union constructors +// Erased union helper //------------------------------------------------------------------------- -val getDisjointErasedUnionCasesTyps : TcGlobals -> TType -> TTypes +val tryUnsortedErasedUnionTyCases : TcGlobals -> TType -> TTypes ValueOption //------------------------------------------------------------------------- // XmlDoc signatures, used by both VS mode and XML-help emit From 38fef9e1c0030aed9af6fb67016f0e08db61e947 Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Tue, 8 Dec 2020 18:43:18 +1100 Subject: [PATCH 08/15] Add erased union type pickling --- src/fsharp/TypedTreePickle.fs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/fsharp/TypedTreePickle.fs b/src/fsharp/TypedTreePickle.fs index 14cb41f75b..b18860574d 100644 --- a/src/fsharp/TypedTreePickle.fs +++ b/src/fsharp/TypedTreePickle.fs @@ -1690,6 +1690,10 @@ let u_tyar_spec st = let u_tyar_specs = (u_list u_tyar_spec) +let u_erasedUnionInfo st = + let (commonAncestor, unsortedIndices) = u_tup2 u_ty (u_array u_int) st + ErasedUnionInfo.Create(commonAncestor, unsortedIndices) + let _ = fill_p_ty2 (fun isStructThisArgPos ty st -> let ty = stripTyparEqns ty @@ -1726,7 +1730,11 @@ let _ = fill_p_ty2 (fun isStructThisArgPos ty st -> | TType_anon (anonInfo, l) -> p_byte 9 st p_anonInfo anonInfo st - p_tys l st) + p_tys l st + | TType_erased_union (unionInfo, l) -> + p_byte 10 st + p_tup2 p_ty (p_array p_int) (unionInfo.CommonAncestorTy, unionInfo.UnsortedCaseSourceIndices) st + p_tys l st) let _ = fill_u_ty (fun st -> let tag = u_byte st @@ -1741,6 +1749,7 @@ let _ = fill_u_ty (fun st -> | 7 -> let uc = u_ucref st in let tinst = u_tys st in TType_ucase (uc, tinst) | 8 -> let l = u_tys st in TType_tuple (tupInfoStruct, l) | 9 -> let anonInfo = u_anonInfo st in let l = u_tys st in TType_anon (anonInfo, l) + | 10-> let erasedUnionInfo = u_erasedUnionInfo st in let l = u_tys st in TType_erased_union (erasedUnionInfo, l) | _ -> ufailwith st "u_typ") From 07017978a7a946e8a68bef675152264bd11c510f Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Tue, 8 Dec 2020 18:58:06 +1100 Subject: [PATCH 09/15] Symbols hashcode --- src/fsharp/symbols/Symbols.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index 4021f93d3d..7da7821c0f 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -2284,6 +2284,7 @@ type FSharpType(cenv, ty:TType) = | TType_fun (dty, rty) -> 10500 + hashType dty + hashType rty | TType_measure _ -> 10600 | TType_anon (_,l1) -> 10800 + List.sumBy hashType l1 + | TType_erased_union (_,l1) -> 10900 + List.sumBy hashType l1 hashType ty member x.Format(context: FSharpDisplayContext) = From a331e2126582b13d82ee435ae9a903c0c824b54d Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Wed, 9 Dec 2020 00:31:12 +1100 Subject: [PATCH 10/15] Implements checks in TypeFeasiblySubsumes and WIP fix TType_erased_union usages --- src/fsharp/CheckExpressions.fs | 4 ++-- src/fsharp/TypeRelations.fs | 11 ++++++++++- src/fsharp/TypedTreeOps.fs | 4 ++++ src/fsharp/service/ItemKey.fs | 6 ++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index fc569eb33d..8f36eadf8d 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -4270,7 +4270,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv |> List.iter (fun ty -> addToCases ty unionTypeCases) ResizeArray.toList unionTypeCases - let commonAncestorTy g amap tys = + let getCommonAncestorOfTys g amap tys = let superTypes = List.map (AllPrimarySuperTypesOfType g amap m AllowMultiIntfInstantiations.No) tys List.fold (ListSet.intersect (typeEquiv g)) (List.head superTypes) (List.tail superTypes) |> List.head @@ -4283,7 +4283,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv // Map from sorted indexes to unsorted index let sigma = List.map fst sortedIndexedErasedUnionCases |> List.toArray let sortedErasedUnionCases = List.map snd sortedIndexedErasedUnionCases - let commonAncestorTy = commonAncestorTy g cenv.amap sortedErasedUnionCases + let commonAncestorTy = getCommonAncestorOfTys g cenv.amap sortedErasedUnionCases let erasedUnionInfo = ErasedUnionInfo.Create(commonAncestorTy, sigma) TType_erased_union(erasedUnionInfo, sortedErasedUnionCases), tpenv diff --git a/src/fsharp/TypeRelations.fs b/src/fsharp/TypeRelations.fs index 2d25d380be..c984cd70c3 100755 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -7,6 +7,7 @@ module internal FSharp.Compiler.TypeRelations open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Lib open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeBasics open FSharp.Compiler.TypedTreeOps @@ -78,6 +79,9 @@ let rec TypesFeasiblyEquivalent stripMeasures ndeep g amap m ty1 ty2 = | TType_fun (d1, r1), TType_fun (d2, r2) -> (TypesFeasiblyEquivalent stripMeasures ndeep g amap m) d1 d2 && (TypesFeasiblyEquivalent stripMeasures ndeep g amap m) r1 r2 + + | TType_erased_union (_, l1), TType_erased_union (_, l2) -> + List.lengthsEqAndForall2 (TypesFeasiblyEquivalent stripMeasures ndeep g amap m) l1 l2 | TType_measure _, TType_measure _ -> true @@ -108,7 +112,12 @@ let rec TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce ty2 = | TType_tuple _, TType_tuple _ | TType_anon _, TType_anon _ | TType_fun _, TType_fun _ -> TypesFeasiblyEquiv ndeep g amap m ty1 ty2 - + | TType_app _, TType_erased_union (_, l2) -> + List.forall (TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce) l2 + | TType_erased_union (_, l1), TType_app _ -> + List.exists (fun x1 -> TypeFeasiblySubsumesType ndeep g amap m x1 canCoerce ty1) l1 + | TType_erased_union (_, l1), TType_erased_union (_, l2) -> + ListSet.isSupersetOf (fun x1 x2 -> TypeFeasiblySubsumesType ndeep g amap m x1 canCoerce x2) l1 l2 | TType_measure _, TType_measure _ -> true diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 194dd47fc4..d4fc7d0100 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -3517,6 +3517,7 @@ module DebugPrint = auxTyparsL env tcL prefix tinst | TType_anon (anonInfo, tys) -> braceBarL (sepListL (wordL (tagText ";")) (List.map2 (fun nm ty -> wordL (tagField nm) --- auxTypeAtomL env ty) (Array.toList anonInfo.SortedNames) tys)) | TType_tuple (_tupInfo, tys) -> sepListL (wordL (tagText "*")) (List.map (auxTypeAtomL env) tys) |> wrap + | TType_erased_union (_, tys) -> leftL (tagText "(") ^^ sepListL (wordL (tagText "|")) (List.map (auxTypeAtomL env) tys) ^^ rightL (tagText ")") | TType_fun (f, x) -> ((auxTypeAtomL env f ^^ wordL (tagText "->")) --- auxTypeL env x) |> wrap | TType_var typar -> auxTyparWrapL env isAtomic typar | TType_measure unt -> @@ -8079,6 +8080,9 @@ let rec typeEnc g (gtpsType, gtpsMethod) ty = typarEnc g (gtpsType, gtpsMethod) typar | TType_measure _ -> "?" + | TType_erased_union (_, tys) -> + // SWOORUP TODO idk + typeEnc g (gtpsType, gtpsMethod) (List.head tys) + "|" and tyargsEnc g (gtpsType, gtpsMethod) args = match args with diff --git a/src/fsharp/service/ItemKey.fs b/src/fsharp/service/ItemKey.fs index f064d4f98c..83b8bf6fda 100644 --- a/src/fsharp/service/ItemKey.fs +++ b/src/fsharp/service/ItemKey.fs @@ -42,6 +42,9 @@ module ItemKeyTags = [] let typeUnionCase = "#U#" + + [] + let typeErasedUnionCase = "#G#" [] let typeMeasureVar = "#p#" @@ -251,6 +254,9 @@ and [] ItemKeyStoreBuilder() = writeString ItemKeyTags.typeUnionCase writeEntityRef tcref writeString nm + | TType_erased_union (_, tinst) -> + writeString ItemKeyTags.typeErasedUnionCase + tinst |> List.iter (writeType false) and writeMeasure isStandalone (ms: Measure) = match ms with From c8257cba3006c663608c27e7afbac07d62dd2a02 Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Wed, 9 Dec 2020 00:54:19 +1100 Subject: [PATCH 11/15] Renable warnings as errors. Logic is no longer required in ConstraintSolver.fs? Fix minor issue in type relation --- src/fsharp/ConstraintSolver.fs | 32 +++++-------------- .../FSharp.Compiler.Private.fsproj | 4 --- src/fsharp/TypeRelations.fs | 2 +- 3 files changed, 9 insertions(+), 29 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 2adee56f84..e6578c184c 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -1070,26 +1070,6 @@ and SolveFunTypeEqn csenv ndeep m2 trace cxsln d1 d2 r1 r2 = trackErrors { return! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln r1 r2 } -// ty1: expected -// ty2: actual -// -// "ty2 casts to any of the disjoint cases of ty1" -// "a value of type ty2 can be used where a value of type ty1 is expected" -and SolveErasedUnionTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) cxsln ty1Cases ty2 = - let g = csenv.g - let aenv = csenv.EquivEnv - match ty2 with - // What if TType_app wraps another TType_erased_union - | TType_app (_,_) when ListSet.contains (typeAEquiv g aenv) ty2 ty1Cases -> - match List.tryFind (typeAEquiv g aenv ty2) ty1Cases with - | Some v1 -> - SolveTypeSubsumesType csenv ndeep m2 trace cxsln v1 ty2 - | None -> failwithf "SolveErasedUnionTypeSubsumesType failed" - | TType_erased_union (_,l2) when ListSet.isSubsetOf (typeAEquiv g aenv) l2 ty1Cases -> - let subset1 = ListSet.intersect (typeAEquiv g aenv) l2 ty1Cases - SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln subset1 l2 - | _ -> failwithf "SolveErasedUnionTypeSubsumesType: Should never reach here" - // ty1: expected // ty2: actual // @@ -1158,10 +1138,14 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 - | TType_erased_union (_, l1), TType_app (_,_) when ListSet.contains (typeAEquiv g aenv) sty2 l1 -> - SolveErasedUnionTypeSubsumesType csenv ndeep m2 trace cxsln l1 sty2 - | TType_erased_union (_, l1), TType_erased_union (_, l2) when ListSet.isSubsetOf (typeAEquiv g aenv) l2 l1 -> - SolveErasedUnionTypeSubsumesType csenv ndeep m2 trace cxsln l1 sty2 + | TType_erased_union (_,l1), TType_erased_union (_,l2) when typeAEquiv g aenv sty1 sty2 -> + SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 + + | TType_erased_union _, TType_app _ + | TType_app _, TType_erased_union _ + | TType_erased_union _, TType_erased_union _ when + TypeFeasiblySubsumesType ndeep csenv.g csenv.amap m2 sty1 CanCoerce sty2 -> + CompleteD | _ -> // By now we know the type is not a variable type diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 027e4f7782..e732f6fe2e 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -20,10 +20,6 @@ $(IntermediateOutputPath)$(TargetFramework)\ - - 3239;1182; - - $(BaseOutputPath)\$(Configuration)\$(TargetFramework) diff --git a/src/fsharp/TypeRelations.fs b/src/fsharp/TypeRelations.fs index c984cd70c3..802625ee81 100755 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -115,7 +115,7 @@ let rec TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce ty2 = | TType_app _, TType_erased_union (_, l2) -> List.forall (TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce) l2 | TType_erased_union (_, l1), TType_app _ -> - List.exists (fun x1 -> TypeFeasiblySubsumesType ndeep g amap m x1 canCoerce ty1) l1 + List.exists (fun x1 -> TypeFeasiblySubsumesType ndeep g amap m x1 canCoerce ty2) l1 | TType_erased_union (_, l1), TType_erased_union (_, l2) -> ListSet.isSupersetOf (fun x1 x2 -> TypeFeasiblySubsumesType ndeep g amap m x1 canCoerce x2) l1 l2 | TType_measure _, TType_measure _ -> From f096896149a1de6899eb9390fc263a5af72d4a83 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 18 Jan 2021 17:58:56 +0000 Subject: [PATCH 12/15] use new subsumption for erased union types --- src/fsharp/CheckExpressions.fs | 63 ++++++++++++++++++++++++--- src/fsharp/ConstraintSolver.fs | 32 +++++++++----- src/fsharp/FSComp.txt | 1 + src/fsharp/TypeRelations.fs | 8 ++-- src/fsharp/TypedTree.fs | 1 + src/fsharp/TypedTreeOps.fs | 20 +++------ src/fsharp/infos.fs | 4 ++ src/fsharp/infos.fsi | 12 +++++ src/fsharp/xlf/FSComp.txt.cs.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.de.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.es.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.fr.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.it.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.ja.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.ko.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.pl.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.ru.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.tr.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 5 +++ src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 5 +++ 21 files changed, 170 insertions(+), 36 deletions(-) diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 70a55c4923..5545d5904c 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -457,7 +457,7 @@ let UnifyTypes cenv (env: TcEnv) m actualTy expectedTy = // then allow subsumption. let UnifyOverallType cenv (env: TcEnv) m overallTy actualTy = match overallTy with - | MustConvertTo(overallTy) when isAppTy cenv.g overallTy && not (isSealedTy cenv.g overallTy) -> + | MustConvertTo(overallTy) when not (isSealedTy cenv.g overallTy) -> let actualTy = tryNormalizeMeasureInType cenv.g actualTy let overallTy = tryNormalizeMeasureInType cenv.g overallTy if AddCxTypeEqualsTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy actualTy then @@ -4304,10 +4304,6 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv |> List.iter (fun ty -> addToCases ty unionTypeCases) ResizeArray.toList unionTypeCases - let getCommonAncestorOfTys g amap tys = - let superTypes = List.map (AllPrimarySuperTypesOfType g amap m AllowMultiIntfInstantiations.No) tys - List.fold (ListSet.intersect (typeEquiv g)) (List.head superTypes) (List.tail superTypes) |> List.head - // Sort into order for ordered equality let sortedIndexedErasedUnionCases = createDisjointTypes synCases @@ -4317,7 +4313,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv // Map from sorted indexes to unsorted index let sigma = List.map fst sortedIndexedErasedUnionCases |> List.toArray let sortedErasedUnionCases = List.map snd sortedIndexedErasedUnionCases - let commonAncestorTy = getCommonAncestorOfTys g cenv.amap sortedErasedUnionCases + let commonAncestorTy = getCommonAncestorOfTys g cenv.amap sortedErasedUnionCases m let erasedUnionInfo = ErasedUnionInfo.Create(commonAncestorTy, sigma) TType_erased_union(erasedUnionInfo, sortedErasedUnionCases), tpenv @@ -4410,6 +4406,59 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv | SynType.Paren(innerType, _) -> TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv) innerType +and TcErasedUnionTypeOr (cenv: cenv) env (tpenv: UnscopedTyparEnv) synCases m = + let g = cenv.g + // Helper method for eliminating duplicate types from lists of types that form a union type, + // create a disjoint set of cases + // taking into account that a subtype is a "duplicate" of its supertype. + let rec addToCases (pt: TType) (list: ResizeArray) = + if not <| ResizeArray.exists (isObjTy g) list then + if isObjTy g pt then + list.Clear() + list.Add(pt) + elif isErasedUnionTy g pt then + let otherUnsortedCases = tryUnsortedErasedUnionTyCases g pt |> ValueOption.defaultValue [] + for otherCase in otherUnsortedCases + do addToCases otherCase list + else + let mutable shouldAdd = true + let mutable i = 0 + while i < list.Count && shouldAdd do + let t = list.[i] + if isSubTypeOf cenv.g cenv.amap m pt t then + shouldAdd <- false + elif isSuperTypeOf cenv.g cenv.amap m pt t then + list.RemoveAt(i) + i <- i - 1 // redo this index + i <- i + 1 + if shouldAdd then list.Add pt + + let createDisjointTypes synErasedUnionCases = + let unionTypeCases = ResizeArray() + do + synErasedUnionCases + |> List.map(fun (ErasedUnionCase(typ=ty)) -> TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurence.UseInType env tpenv ty |> fst) + |> List.iter (fun ty -> addToCases ty unionTypeCases) + ResizeArray.toList unionTypeCases + + let getCommonAncestorOfTys g amap tys = + let superTypes = tys |> List.map (AllPrimarySuperTypesOfType g amap m AllowMultiIntfInstantiations.No) + List.fold (ListSet.intersect (typeEquiv g)) (List.head superTypes) (List.tail superTypes) |> List.head + + // Sort into order for ordered equality + let sortedIndexedErasedUnionCases = + createDisjointTypes synCases + |> List.indexed + |> List.sortBy (snd >> stripTyEqnsAndMeasureEqns g >> string) + + // Map from sorted indexes to unsorted index + let sigma = List.map fst sortedIndexedErasedUnionCases |> List.toArray + let sortedErasedUnionCases = List.map snd sortedIndexedErasedUnionCases + let commonAncestorTy = getCommonAncestorOfTys g cenv.amap sortedErasedUnionCases + + let erasedUnionInfo = ErasedUnionInfo.Create(commonAncestorTy, sigma) + TType_erased_union(erasedUnionInfo, sortedErasedUnionCases), tpenv + and TcType cenv newOk checkCxs occ env (tpenv: UnscopedTyparEnv) ty = TcTypeOrMeasure (Some TyparKind.Type) cenv newOk checkCxs occ env tpenv ty @@ -5492,7 +5541,7 @@ and TcExprUndelayedNoType cenv env tpenv synExpr: Expr * TType * _ = and TcExprLeafProtectExcept p cenv (overallTy: OverallTy) (env: TcEnv) m f = match overallTy with - | MustConvertTo(oty) when not (p oty) && isAppTy cenv.g oty && not (isSealedTy cenv.g oty) -> + | MustConvertTo(oty) when not (p oty) && not (isSealedTy cenv.g oty) -> let oty2 = NewInferenceType() AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace oty oty2 let expr, tpenv = f oty2 diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 1841acf47d..a8d0b6ae06 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -1050,12 +1050,12 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr if not (typarsAEquiv g aenv tps1 tps2) then localAbortD else SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace rty1 rty2 - | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 - | TType_erased_union _, TType_erased_union _ when typeAEquiv g aenv sty1 sty2 -> - CompleteD + | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 -> + SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2 + | TType_erased_union (_, cases1), TType_erased_union (_, cases2) -> + SolveTypeEqualsTypeEqns csenv ndeep m2 trace None cases1 cases2 | _ -> localAbortD - and SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty1 ty2 = SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace None ty1 ty2 and private SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ty1 ty2 = @@ -1152,15 +1152,23 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 -> SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 + + // (int|string) :> sty1 if + // int :> sty1 AND + // string :> sty1 + | _, TType_erased_union (_, cases2) -> + cases2 |> IterateD (fun ty2 -> SolveTypeSubsumesType csenv ndeep m2 trace cxsln sty1 ty2) - | TType_erased_union (_,l1), TType_erased_union (_,l2) when typeAEquiv g aenv sty1 sty2 -> - SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 - - | TType_erased_union _, TType_app _ - | TType_app _, TType_erased_union _ - | TType_erased_union _, TType_erased_union _ when - TypeFeasiblySubsumesType ndeep csenv.g csenv.amap m2 sty1 CanCoerce sty2 -> - CompleteD + // sty2 :> (IComparable|ICloneable) if + // sty2 :> IComparable OR + // sty2 :> ICloneable OR + // when sty2 is not an erased union type + | TType_erased_union (_, cases1), _ -> + match cases1 |> List.tryFind (fun ty1 -> TypeFeasiblySubsumesType ndeep g amap csenv.m ty1 CanCoerce sty2) with + | Some ty1 -> + SolveTypeSubsumesType csenv ndeep m2 trace cxsln ty1 sty2 + | None -> + ErrorD (ConstraintSolverError(FSComp.SR.csErasedUnionTypeNotContained(NicePrint.minimalStringOfType denv sty2, NicePrint.minimalStringOfType denv sty1), csenv.m, m2)) | _ -> // By now we know the type is not a variable type diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 54837b8751..5605a1a61f 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -323,6 +323,7 @@ csTypeIsNotEnumType,"The type '%s' is not a CLI enum type" csTypeHasNonStandardDelegateType,"The type '%s' has a non-standard delegate type" csTypeIsNotDelegateType,"The type '%s' is not a CLI delegate type" csTypeParameterCannotBeNullable,"This type parameter cannot be instantiated to 'Nullable'. This is a restriction imposed in order to ensure the meaning of 'null' in some CLI languages is not confusing when used in conjunction with 'Nullable' values." +csErasedUnionTypeNotContained,"The erased union type '%s' is not compatible with the erased union type '%s'" csGenericConstructRequiresStructType,"A generic construct requires that the type '%s' is a CLI or F# struct type" csGenericConstructRequiresUnmanagedType,"A generic construct requires that the type '%s' is an unmanaged type" csTypeNotCompatibleBecauseOfPrintf,"The type '%s' is not compatible with any of the types %s, arising from the use of a printf-style format string" diff --git a/src/fsharp/TypeRelations.fs b/src/fsharp/TypeRelations.fs index 5a5fc1b9d8..17069f62c3 100755 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -112,12 +112,12 @@ let rec TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce ty2 = | TType_tuple _, TType_tuple _ | TType_anon _, TType_anon _ | TType_fun _, TType_fun _ -> TypesFeasiblyEquiv ndeep g amap m ty1 ty2 - | TType_app _, TType_erased_union (_, l2) -> - List.forall (TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce) l2 - | TType_erased_union (_, l1), TType_app _ -> - List.exists (fun x1 -> TypeFeasiblySubsumesType ndeep g amap m x1 canCoerce ty2) l1 | TType_erased_union (_, l1), TType_erased_union (_, l2) -> ListSet.isSupersetOf (fun x1 x2 -> TypeFeasiblySubsumesType ndeep g amap m x1 canCoerce x2) l1 l2 + | _, TType_erased_union (_, l2) -> + List.forall (TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce) l2 + | TType_erased_union (_, l1), _ -> + List.exists (fun x1 -> TypeFeasiblySubsumesType ndeep g amap m x1 canCoerce ty2) l1 | TType_measure _, TType_measure _ -> true diff --git a/src/fsharp/TypedTree.fs b/src/fsharp/TypedTree.fs index cf98ba39d2..2b75128826 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -4069,6 +4069,7 @@ type AnonRecdTypeInfo = type ErasedUnionInfo = { /// Common ancestor type for all cases in this union, used for ILgen CommonAncestorTy: TType + /// Indices representing order of cases they were defined in UnsortedCaseSourceIndices: int [] } static member Create(commonAncestorTy: TType, unsortedCaseSourceIndices: int[]) = diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 293bbe05f5..e8b865df50 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -791,6 +791,7 @@ let rec stripTyEqnsAndErase eraseFuncAndTuple (g: TcGlobals) ty = ty | TType_fun(a, b) when eraseFuncAndTuple -> TType_app(g.fastFunc_tcr, [ a; b]) | TType_tuple(tupInfo, l) when eraseFuncAndTuple -> mkCompiledTupleTy g (evalTupInfoIsStruct tupInfo) l + | TType_erased_union(unionInfo, _) -> stripTyEqnsAndErase eraseFuncAndTuple g unionInfo.CommonAncestorTy | ty -> ty let stripTyEqnsAndMeasureEqns g ty = @@ -831,7 +832,6 @@ let isFSharpObjModelTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, let isRecdTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsRecordTycon | _ -> false) let isFSharpStructOrEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsFSharpStructOrEnumTycon | _ -> false) let isErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union _ -> true | _ -> false) -let isStructErasedUnionTy g ty = ty |> stripTyEqns g |> (function TType_erased_union (unionInfo, _) -> isFSharpStructOrEnumTy g unionInfo.CommonAncestorTy | _ -> false) let isFSharpEnumTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsFSharpEnumTycon | _ -> false) let isTyparTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | _ -> false) let isAnyParTy g ty = ty |> stripTyEqns g |> (function TType_var _ -> true | TType_measure unt -> isUnitParMeasure g unt | _ -> false) @@ -1845,7 +1845,7 @@ let isStructTy g ty = | ValueSome tcref -> isStructTyconRef tcref | _ -> - isStructAnonRecdTy g ty || isStructTupleTy g ty || isStructErasedUnionTy g ty + isStructAnonRecdTy g ty || isStructTupleTy g ty let isRefTy g ty = not (isStructOrEnumTyconTy g ty) && @@ -1859,7 +1859,7 @@ let isRefTy g ty = isFSharpObjModelRefTy g ty || isUnitTy g ty || (isAnonRecdTy g ty && not (isStructAnonRecdTy g ty)) || - (isErasedUnionTy g ty && not (isStructErasedUnionTy g ty)) + isErasedUnionTy g ty ) let isForallFunctionTy g ty = @@ -8093,9 +8093,7 @@ let rec typeEnc g (gtpsType, gtpsMethod) ty = typarEnc g (gtpsType, gtpsMethod) typar | TType_measure _ -> "?" - | TType_erased_union (_, tys) -> - // SWOORUP TODO idk - typeEnc g (gtpsType, gtpsMethod) (List.head tys) + "|" + | TType_erased_union _ -> failwith "unreachable" // always erased by stripTyEqnsAndMeasureEqns and tyargsEnc g (gtpsType, gtpsMethod) args = match args with @@ -8416,13 +8414,9 @@ let MemberIsCompiledAsInstance g parent isExtensionMember (membInfo: ValMemberIn let isSealedTy g ty = let ty = stripTyEqnsAndMeasureEqns g ty - let isRefTy' = isRefTy g ty - let isUnitTy' = isUnitTy g ty - let isArrayTy' = isArrayTy g ty - - not (isRefTy') || - isUnitTy' || - isArrayTy' || + not (isRefTy g ty) || + isUnitTy g ty || + isArrayTy g ty || match metadataOfTy g ty with #if !NO_EXTENSIONTYPING diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index e394d70385..63ac091955 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -299,6 +299,10 @@ let isSubTypeOf g amap m typeToSearchFrom typeToLookFor = let isSuperTypeOf g amap m typeToSearchFrom typeToLookFor = isSubTypeOf g amap m typeToLookFor typeToSearchFrom +let getCommonAncestorOfTys g amap tys m = + let superTypes = List.map (AllPrimarySuperTypesOfType g amap m AllowMultiIntfInstantiations.No) tys + List.fold (ListSet.intersect (typeEquiv g)) (List.head superTypes) (List.tail superTypes) |> List.head + /// choose 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 ChooseSameHeadTypeInHierarchy g amap m typeToSearchFrom typeToLookFor = SearchEntireHierarchyOfType (HaveSameHeadType g typeToLookFor) g amap m typeToSearchFrom diff --git a/src/fsharp/infos.fsi b/src/fsharp/infos.fsi index 0e0e2b475c..a6dba8d8c5 100644 --- a/src/fsharp/infos.fsi +++ b/src/fsharp/infos.fsi @@ -60,6 +60,9 @@ val SearchEntireHierarchyOfType: f:(TType -> bool) -> g:TcGlobals -> amap:Import /// Get all super types of the type, including the type itself val AllSuperTypesOfType: g:TcGlobals -> amap:ImportMap -> m:range -> allowMultiIntfInst:AllowMultiIntfInstantiations -> ty:TType -> TType list +/// Get all super types of the type, including the type itself +val AllPrimarySuperTypesOfType: g:TcGlobals -> amap:ImportMap -> m:range -> allowMultiIntfInst:AllowMultiIntfInstantiations -> ty:TType -> TType list + /// Get all interfaces of a type, including the type itself if it is an interface val AllInterfacesOfType: g:TcGlobals -> amap:ImportMap -> m:range -> allowMultiIntfInst:AllowMultiIntfInstantiations -> ty:TType -> TType list @@ -75,6 +78,15 @@ val ExistsSameHeadTypeInHierarchy: g:TcGlobals -> amap:ImportMap -> m:range -> t /// Check if a type exists somewhere in the hierarchy which has the given head type. val ExistsHeadTypeInEntireHierarchy: g:TcGlobals -> amap:ImportMap -> m:range -> typeToSearchFrom:TType -> tcrefToLookFor:TyconRef -> bool +/// Check if one (nominal) type is a subtype of another +val isSubTypeOf: g: TcGlobals -> amap: ImportMap -> m: range -> typeToSearchFrom: TType -> typeToLookFor: TType -> bool + +/// Check if one (nominal) type is a supertype of another +val isSuperTypeOf: g: TcGlobals -> amap: ImportMap -> m: range -> typeToSearchFrom: TType -> typeToLookFor: TType -> bool + +/// Get the common ancestor of a set of nominal types +val getCommonAncestorOfTys: g: TcGlobals -> amap: ImportMap -> tys: TTypes -> m: range -> TType + /// Read an Abstract IL type from metadata and convert to an F# type. val ImportILTypeFromMetadata: amap:ImportMap -> m:range -> scoref:ILScopeRef -> tinst:TType list -> minst:TType list -> ilty:ILType -> TType diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index aefc534fb8..d521ee4d70 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -22,6 +22,11 @@ Dostupná přetížení:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Obecná konstrukce vyžaduje, aby byl parametr obecného typu známý jako typ struct nebo reference. Zvažte možnost přidat anotaci typu. diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index 5f97c380a0..0ffd3f9ebe 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -22,6 +22,11 @@ Verfügbare Überladungen:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Für ein generisches Konstrukt muss ein generischer Typparameter als Struktur- oder Verweistyp bekannt sein. Erwägen Sie das Hinzufügen einer Typanmerkung. diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index e7bc48797f..f46ed7ec62 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -22,6 +22,11 @@ Sobrecargas disponibles:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Una construcción genérica requiere que un parámetro de tipo genérico se conozca como tipo de referencia o estructura. Puede agregar una anotación de tipo. diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index fc6e721dd7..cb27c1387b 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -22,6 +22,11 @@ Surcharges disponibles :\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. L'utilisation d'une construction générique est possible uniquement si un paramètre de type générique est connu en tant que type struct ou type référence. Ajoutez une annotation de type. diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index 1bb64339ba..127fc8b725 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -22,6 +22,11 @@ Overload disponibili:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Un costrutto generico richiede che un parametro di tipo generico sia noto come tipo riferimento o struct. Provare ad aggiungere un'annotazione di tipo. diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index a280cec07e..dc3693a7c9 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -22,6 +22,11 @@ 使用可能なオーバーロード:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. ジェネリック コンストラクトでは、ジェネリック型パラメーターが構造体または参照型として認識されている必要があります。型の注釈の追加を検討してください。 diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index 2d4186317b..c812e4f061 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -22,6 +22,11 @@ 사용 가능한 오버로드:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 제네릭 구문을 사용하려면 구조체 또는 참조 형식의 제네릭 형식 매개 변수가 필요합니다. 형식 주석을 추가하세요. diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 13bb0af4bb..457614278d 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -22,6 +22,11 @@ Dostępne przeciążenia:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Konstrukcja ogólna wymaga, aby parametr typu ogólnego był znany jako struktura lub typ referencyjny. Rozważ dodanie adnotacji typu. diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 958dab0dc8..63d16190e1 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -22,6 +22,11 @@ Sobrecargas disponíveis:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Um constructo genérico exige que um parâmetro de tipo genérico seja conhecido como um tipo de referência ou struct. Considere adicionar uma anotação de tipo. diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index ba2871ca7d..c70142f9ec 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -22,6 +22,11 @@ Доступные перегрузки:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. В универсальной конструкции требуется использовать параметр универсального типа, известный как структура или ссылочный тип. Рекомендуется добавить заметку с типом. diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index eec54a3f23..9273e07f7c 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -22,6 +22,11 @@ Kullanılabilir aşırı yüklemeler:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Genel yapı, genel bir tür parametresinin yapı veya başvuru türü olarak bilinmesini gerektirir. Tür ek açıklaması eklemeyi düşünün. diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 23d95c576c..ee71ea54f6 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -22,6 +22,11 @@ 可用重载:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 泛型构造要求泛型类型参数被视为结构或引用类型。请考虑添加类型注释。 diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 6e31af6d1f..536d2361e5 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -22,6 +22,11 @@ 可用的多載:\n{0} + + The erased union type '{0}' is not compatible with the erased union type '{1}' + The erased union type '{0}' is not compatible with the erased union type '{1}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 泛型建構要求泛型型別參數必須指定為結構或參考型別。請考慮新增型別註解。 From 4707072aee8695e3d3aa0cd116d4c85e17a01a7a Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 18 Jan 2021 18:30:35 +0000 Subject: [PATCH 13/15] update baseline --- .../SurfaceArea.netstandard.fs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index f9beaa8e1b..0603caf999 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -8784,6 +8784,28 @@ FSharp.Compiler.SyntaxTree+SynType+WithGlobalConstraints: Microsoft.FSharp.Colle FSharp.Compiler.SyntaxTree+SynType+WithGlobalConstraints: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynTypeConstraint] get_constraints() FSharp.Compiler.SyntaxTree+SynType+WithGlobalConstraints: SynType get_typeName() FSharp.Compiler.SyntaxTree+SynType+WithGlobalConstraints: SynType typeName +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: FSharp.Compiler.Text.Range Range +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: FSharp.Compiler.Text.Range get_Range() +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: FSharp.Compiler.Text.Range range +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: Int32 Tag +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: Int32 get_Tag() +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: PreXmlDoc get_xmlDoc() +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: PreXmlDoc xmlDoc +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: SynErasedUnionCase NewErasedUnionCase(SynType, PreXmlDoc, FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: SynType get_typ() +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: SynType typ +FSharp.Compiler.SyntaxTree+SynErasedUnionCase: System.String ToString() +FSharp.Compiler.SyntaxTree+SynType+ErasedUnion: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.SyntaxTree+SynType+ErasedUnion: FSharp.Compiler.Text.Range range +FSharp.Compiler.SyntaxTree+SynType+ErasedUnion: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynErasedUnionCase] erasedUnionCases +FSharp.Compiler.SyntaxTree+SynType+ErasedUnion: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynErasedUnionCase] get_erasedUnionCases() +FSharp.Compiler.SyntaxTree+SynType+Tags: Int32 ErasedUnion +FSharp.Compiler.SyntaxTree+SynType: Boolean IsErasedUnion +FSharp.Compiler.SyntaxTree+SynType: Boolean get_IsErasedUnion() +FSharp.Compiler.SyntaxTree+SynType: FSharp.Compiler.SyntaxTree+SynType+ErasedUnion +FSharp.Compiler.SyntaxTree+SynType: SynType NewErasedUnion(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynErasedUnionCase], FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynErasedUnionCase FSharp.Compiler.SyntaxTree+SynType: Boolean IsAnon FSharp.Compiler.SyntaxTree+SynType: Boolean IsAnonRecd FSharp.Compiler.SyntaxTree+SynType: Boolean IsApp From 4d1ca9c24c007982ce175b59d8104c1ce6d76ceb Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 19 Jan 2021 14:24:29 +0000 Subject: [PATCH 14/15] update xlf --- src/fsharp/xlf/FSComp.txt.cs.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.de.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.es.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.fr.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.it.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.ja.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.ko.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.pl.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.ru.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.tr.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 9 +++++++-- src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 9 +++++++-- 13 files changed, 91 insertions(+), 26 deletions(-) diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index d521ee4d70..37df778dee 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -97,6 +97,11 @@ literál float32 bez tečky + + erased unions + erased unions + + more types support units of measure více typů podporuje měrné jednotky @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index 0ffd3f9ebe..92dcd20443 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -97,6 +97,11 @@ punktloses float32-Literal + + erased unions + erased unions + + more types support units of measure Maßeinheitenunterstützung durch weitere Typen @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index f46ed7ec62..948b750c6b 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -97,6 +97,11 @@ literal float32 sin punto + + erased unions + erased unions + + more types support units of measure más tipos admiten las unidades de medida @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index cb27c1387b..42d0e53fd9 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -97,6 +97,11 @@ littéral float32 sans point + + erased unions + erased unions + + more types support units of measure d'autres types prennent en charge les unités de mesure @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index 127fc8b725..047800d1d9 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -97,6 +97,11 @@ valore letterale float32 senza punti + + erased unions + erased unions + + more types support units of measure più tipi supportano le unità di misura @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index dc3693a7c9..10f1460a86 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -97,6 +97,11 @@ ドットなしの float32 リテラル + + erased unions + erased unions + + more types support units of measure 単位をサポートするその他の型 @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index c812e4f061..d069a861fe 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -97,6 +97,11 @@ 점이 없는 float32 리터럴 + + erased unions + erased unions + + more types support units of measure 더 많은 형식이 측정 단위를 지원함 @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 457614278d..50a2c46258 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -97,6 +97,11 @@ bezkropkowy literał float32 + + erased unions + erased unions + + more types support units of measure więcej typów obsługuje jednostki miary @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 63d16190e1..83b11dcede 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -97,6 +97,11 @@ literal float32 sem ponto + + erased unions + erased unions + + more types support units of measure mais tipos dão suporte para unidades de medida @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index c70142f9ec..bee5fac9e7 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -97,6 +97,11 @@ литерал float32 без точки + + erased unions + erased unions + + more types support units of measure другие типы поддерживают единицы измерения @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index 9273e07f7c..dc72d110b0 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -97,6 +97,11 @@ noktasız float32 sabit değeri + + erased unions + erased unions + + more types support units of measure tür daha ölçü birimlerini destekler @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index ee71ea54f6..f247b3f4af 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -97,6 +97,11 @@ 无点 float32 文本 + + erased unions + erased unions + + more types support units of measure 更多类型支持度量单位 @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 536d2361e5..41b0adfe16 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -97,6 +97,11 @@ 無點號的 float32 常值 + + erased unions + erased unions + + more types support units of measure 更多支援測量單位的類型 @@ -113,8 +118,8 @@ - implicit upcasts and other conversions for function returns, bindings and other expressions - implicit upcasts and other conversions for function returns, bindings and other expressions + additional implicit conversions + additional implicit conversions From d53974422221ed40a4f534327642c2fcfc31b3b0 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 24 May 2021 18:32:07 +0100 Subject: [PATCH 15/15] update baselines --- .../SurfaceArea.netstandard.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index f191f84367..73ff1afdaa 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -6077,9 +6077,9 @@ FSharp.Compiler.Syntax.SynEnumCase: Microsoft.FSharp.Collections.FSharpList`1[FS FSharp.Compiler.Syntax.SynEnumCase: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] get_attributes() FSharp.Compiler.Syntax.SynEnumCase: System.String ToString() FSharp.Compiler.Syntax.SynErasedUnionCase -FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Syntax.PreXmlDoc get_xmlDoc() -FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Syntax.PreXmlDoc xmlDoc -FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Syntax.SynErasedUnionCase NewSynErasedUnionCase(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.PreXmlDoc, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Xml.PreXmlDoc get_xmlDoc() +FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Xml.PreXmlDoc xmlDoc +FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Syntax.SynErasedUnionCase NewSynErasedUnionCase(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Syntax.SynType get_typ() FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Syntax.SynType typ FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Text.Range Range