diff --git a/src/fsharp/CheckDeclarations.fs b/src/fsharp/CheckDeclarations.fs index f8942a5beb2..0a42266221c 100644 --- a/src/fsharp/CheckDeclarations.fs +++ b/src/fsharp/CheckDeclarations.fs @@ -4120,7 +4120,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 9f4f02d5b24..dba320ffd55 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -4303,8 +4303,12 @@ 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) -> + checkLanguageFeatureError cenv.g.langVersion LanguageFeature.ErasedUnions m + TcErasedUnionTypeOr cenv env tpenv synCases m - | SynType.Fun(domainTy, resultTy, _) -> + | 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 (domainTy' --> resultTy'), tpenv @@ -4392,6 +4396,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 (SynErasedUnionCase(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 diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 74336feb445..d709cd51109 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -739,6 +739,7 @@ let rec SimplifyMeasuresInType g resultFirst (generalizable, generalized as para | 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] @@ -777,6 +778,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) @@ -993,7 +995,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 = @@ -1046,10 +1048,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_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 = @@ -1147,6 +1151,22 @@ 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) + + // 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 31a3d4d521b..408a7bcb89a 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -324,6 +324,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" @@ -1529,6 +1530,7 @@ featureNullableOptionalInterop,"nullable optional interop" featureDefaultInterfaceMemberConsumption,"default interface member consumption" featureStringInterpolation,"string interpolation" featureWitnessPassing,"witness passing for trait constraints in F# quotations" +featureErasedUnions,"erased unions" featureAdditionalImplicitConversions,"additional type-directed conversions" featureStructActivePattern,"struct representation for active patterns" 3353,fsiInvalidDirective,"Invalid directive '#%s %s'" diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 0e6ba2aac83..7df0f5d9ba8 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -547,6 +547,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.CommonAncestorTy | TType_forall (tps, tau) -> let tps = DropErasedTypars tps diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 94f24a9a81f..4a667e0d4e7 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -31,6 +31,7 @@ type LanguageFeature = | NullableOptionalInterop | DefaultInterfaceMemberConsumption | WitnessPassing + | ErasedUnions | AdditionalTypeDirectedConversions | InterfacesWithMultipleGenericInstantiation | StringInterpolation @@ -79,6 +80,7 @@ type LanguageVersion (specifiedVersionAsString) = LanguageFeature.StringInterpolation, languageVersion50 // F# preview + LanguageFeature.ErasedUnions, previewVersion LanguageFeature.AdditionalTypeDirectedConversions, previewVersion LanguageFeature.OverloadsForCustomOperations, previewVersion LanguageFeature.ExpandedMeasurables, previewVersion @@ -159,6 +161,7 @@ type LanguageVersion (specifiedVersionAsString) = | LanguageFeature.NullableOptionalInterop -> FSComp.SR.featureNullableOptionalInterop() | LanguageFeature.DefaultInterfaceMemberConsumption -> FSComp.SR.featureDefaultInterfaceMemberConsumption() | LanguageFeature.WitnessPassing -> FSComp.SR.featureWitnessPassing() + | LanguageFeature.ErasedUnions -> FSComp.SR.featureErasedUnions() | LanguageFeature.AdditionalTypeDirectedConversions -> FSComp.SR.featureAdditionalImplicitConversions() | LanguageFeature.InterfacesWithMultipleGenericInstantiation -> FSComp.SR.featureInterfacesWithMultipleGenericInstantiation() | LanguageFeature.StringInterpolation -> FSComp.SR.featureStringInterpolation() diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index 4c5afffd9da..85657eb74e9 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -21,6 +21,7 @@ type LanguageFeature = | NullableOptionalInterop | DefaultInterfaceMemberConsumption | WitnessPassing + | ErasedUnions | AdditionalTypeDirectedConversions | InterfacesWithMultipleGenericInstantiation | StringInterpolation diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 4ffa52da0aa..0df983273c9 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -799,6 +799,17 @@ module private PrintTypes = layoutTyparRefWithInfo denv env r | TType_measure unt -> layoutMeasure denv unt + + | 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/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index e230643baa4..fcbe263bc87 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -387,6 +387,7 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi 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 23d46cd3d05..cf31b2b15f1 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -371,6 +371,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/// | Array of rank: int * @@ -431,6 +436,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) @@ -1384,6 +1390,18 @@ type SynUnionCase = match this with | SynUnionCase (range=m) -> m +[] +type SynErasedUnionCase = + + | SynErasedUnionCase of + typ: SynType * + xmlDoc: PreXmlDoc * + range: range + + member this.Range = + match this with + | SynErasedUnionCase (range=m) -> m + [] type SynUnionCaseKind = diff --git a/src/fsharp/SyntaxTree.fsi b/src/fsharp/SyntaxTree.fsi index 035f3d9b42d..cee1a607909 100644 --- a/src/fsharp/SyntaxTree.fsi +++ b/src/fsharp/SyntaxTree.fsi @@ -465,6 +465,11 @@ type SynType = 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 rank: int * @@ -1546,6 +1551,17 @@ type SynUnionCase = /// Gets the syntax range of this construct member Range: range +[] +type SynErasedUnionCase = + + /// The untyped, unchecked syntax tree for one case in a union definition. + | SynErasedUnionCase of + typ: SynType * + xmlDoc: PreXmlDoc * + range: range + + member Range: range + /// 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/TypeRelations.fs b/src/fsharp/TypeRelations.fs index b52dfac4dda..23d154a2361 100755 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -6,6 +6,7 @@ module internal FSharp.Compiler.TypeRelations open Internal.Utilities.Collections open Internal.Utilities.Library +open Internal.Utilities.Library.Extras open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Infos open FSharp.Compiler.TcGlobals @@ -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 @@ -94,6 +98,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 @@ -107,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_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 800d4b361e5..7ab916fea46 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -3970,6 +3970,9 @@ type TType = /// Indicates the type is a variable type, whether declared, generalized or an inference type parameter | TType_var of typar: Typar + + /// Indicates the type is a union type, containing common ancestor type and the disjoint cases + | TType_erased_union of unionInfo: ErasedUnionInfo * choices: TTypes /// Indicates the type is a unit-of-measure expression being used as an argument to a type or member | TType_measure of measure: Measure @@ -3988,6 +3991,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() @@ -4013,6 +4017,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 @@ -4070,6 +4075,17 @@ type AnonRecdTypeInfo = member x.IsLinked = (match x.SortedIds with null -> true | _ -> false) +[] +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[]) = + { CommonAncestorTy = commonAncestorTy + UnsortedCaseSourceIndices = unsortedCaseSourceIndices } + [] type TupInfo = /// Some constant, e.g. true or false for tupInfo diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 679f59a1693..1f9e03e2cbf 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -188,6 +188,12 @@ 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) + + // 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 @@ -777,6 +783,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 = @@ -816,12 +823,11 @@ let isReprHiddenTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) - 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 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 isProvenUnionCaseTy ty = match ty with TType_ucase _ -> true | _ -> false let mkAppTy tcref tyargs = TType_app(tcref, tyargs) @@ -842,6 +848,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 @@ -984,6 +1004,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) +/// Test ty1 = ty2 and typeAEquivAux erasureFlag g aenv ty1 ty2 = let ty1 = stripTyEqnsWrtErasure erasureFlag g ty1 let ty2 = stripTyEqnsWrtErasure erasureFlag g ty2 @@ -1013,7 +1034,9 @@ 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) -> + ListSet.equals (typeAEquivAux erasureFlag g aenv) l1 l2 | _ -> false @@ -1078,7 +1101,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 @@ -1826,7 +1849,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 ) let isForallFunctionTy g ty = @@ -2134,6 +2158,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 @@ -2237,7 +2263,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 @@ -2674,7 +2703,8 @@ module SimplifyTypes = | TType_forall (_, body) -> foldTypeButNotConstraints f z body | TType_app (_, tys) | TType_ucase (_, tys) - | TType_anon (_, 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 @@ -3532,6 +3562,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 -> @@ -8190,6 +8221,7 @@ let rec typeEnc g (gtpsType, gtpsMethod) ty = typarEnc g (gtpsType, gtpsMethod) typar | TType_measure _ -> "?" + | TType_erased_union _ -> failwith "unreachable" // always erased by stripTyEqnsAndMeasureEqns and tyargsEnc g (gtpsType, gtpsMethod) args = match args with @@ -8523,7 +8555,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 diff --git a/src/fsharp/TypedTreeOps.fsi b/src/fsharp/TypedTreeOps.fsi index 4830cf4ee19..8dc0a626fd2 100755 --- a/src/fsharp/TypedTreeOps.fsi +++ b/src/fsharp/TypedTreeOps.fsi @@ -621,6 +621,8 @@ val isAnonRecdTy: TcGlobals -> TType -> bool val isUnionTy: TcGlobals -> TType -> bool +val isErasedUnionTy: TcGlobals -> TType -> bool + val isReprHiddenTy: TcGlobals -> TType -> bool val isFSharpObjModelTy: TcGlobals -> TType -> bool @@ -2257,6 +2259,12 @@ val AdjustPossibleSubsumptionExpr: TcGlobals -> Expr -> Exprs -> (Expr * Exprs) val NormalizeAndAdjustPossibleSubsumptionExprs: TcGlobals -> Expr -> Expr +//------------------------------------------------------------------------- +// Erased union helper +//------------------------------------------------------------------------- + +val tryUnsortedErasedUnionTyCases : TcGlobals -> TType -> TTypes ValueOption + //------------------------------------------------------------------------- // XmlDoc signatures, used by both VS mode and XML-help emit //------------------------------------------------------------------------- diff --git a/src/fsharp/TypedTreePickle.fs b/src/fsharp/TypedTreePickle.fs index a2a51c00471..c44e185af79 100644 --- a/src/fsharp/TypedTreePickle.fs +++ b/src/fsharp/TypedTreePickle.fs @@ -1704,6 +1704,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 @@ -1740,7 +1744,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 @@ -1755,6 +1763,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") diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index fb0b58e5272..dae2a761474 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -275,6 +275,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 = @@ -298,6 +301,20 @@ 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 + +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 /// 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/infos.fsi b/src/fsharp/infos.fsi index 5b0c29f11a8..a0a3ed7b25d 100644 --- a/src/fsharp/infos.fsi +++ b/src/fsharp/infos.fsi @@ -62,6 +62,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 @@ -77,6 +80,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/pars.fsy b/src/fsharp/pars.fsy index d1519188df4..0d39c943167 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -5097,6 +5097,7 @@ atomTypeOrAnonRecdType: | (SynField([], 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 (SynErasedUnionCase(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" */ @@ -5170,6 +5171,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 -> SynErasedUnionCase ($1, xmlDoc, mDecl)) } + typeArgsNoHpaDeprecated: | typeArgsActual { let mLessThan, mGreaterThan, parsedOk, args, commas, mAll = $1 diff --git a/src/fsharp/service/ItemKey.fs b/src/fsharp/service/ItemKey.fs index ebeafff9ff9..c483dbb3886 100644 --- a/src/fsharp/service/ItemKey.fs +++ b/src/fsharp/service/ItemKey.fs @@ -40,6 +40,9 @@ module ItemKeyTags = [] let typeUnionCase = "#U#" + + [] + let typeErasedUnionCase = "#G#" [] let typeMeasureVar = "#p#" @@ -242,6 +245,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 diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index fdf67fb3111..329efbc37ee 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -2433,6 +2433,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 _.Format(context: FSharpDisplayContext) = diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index 01f3649a721..aac717b641b 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -32,6 +32,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. @@ -117,6 +122,11 @@ literál float32 bez tečky + + erased unions + erased unions + + more types support units of measure více typů podporuje měrné jednotky diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index 775a2c4cf14..060561fe292 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -32,6 +32,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. @@ -117,6 +122,11 @@ punktloses float32-Literal + + erased unions + erased unions + + more types support units of measure Maßeinheitenunterstützung durch weitere Typen diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index 0b6f20a0f6c..a6aaec72736 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -32,6 +32,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. @@ -117,6 +122,11 @@ literal float32 sin punto + + erased unions + erased unions + + more types support units of measure más tipos admiten las unidades de medida diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index 2807f6d07a7..e7c55becf0f 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -32,6 +32,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. @@ -117,6 +122,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 diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index 4c38385f04d..ac8d814ee91 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -32,6 +32,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. @@ -117,6 +122,11 @@ valore letterale float32 senza punti + + erased unions + erased unions + + more types support units of measure più tipi supportano le unità di misura diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 1996966dcc8..4bea2ada534 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -32,6 +32,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. ジェネリック コンストラクトでは、ジェネリック型パラメーターが構造体または参照型として認識されている必要があります。型の注釈の追加を検討してください。 @@ -117,6 +122,11 @@ ドットなしの float32 リテラル + + erased unions + erased unions + + more types support units of measure 単位をサポートするその他の型 diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index 000fb0e0fef..abe04e5cee3 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -32,6 +32,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. 제네릭 구문을 사용하려면 구조체 또는 참조 형식의 제네릭 형식 매개 변수가 필요합니다. 형식 주석을 추가하세요. @@ -117,6 +122,11 @@ 점이 없는 float32 리터럴 + + erased unions + erased unions + + more types support units of measure 더 많은 형식이 측정 단위를 지원함 diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index ebb9b583e79..5fe06bb8155 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -32,6 +32,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. @@ -117,6 +122,11 @@ bezkropkowy literał float32 + + erased unions + erased unions + + more types support units of measure więcej typów obsługuje jednostki miary diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 2a5d20c85fc..c1ee7c212ce 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -32,6 +32,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. @@ -117,6 +122,11 @@ literal float32 sem ponto + + erased unions + erased unions + + more types support units of measure mais tipos dão suporte para unidades de medida diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index 5c35a4d3180..c1019e87b0d 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -32,6 +32,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. В универсальной конструкции требуется использовать параметр универсального типа, известный как структура или ссылочный тип. Рекомендуется добавить заметку с типом. @@ -117,6 +122,11 @@ литерал float32 без точки + + erased unions + erased unions + + more types support units of measure другие типы поддерживают единицы измерения diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index a5eab0e8d41..8bdc990558e 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -32,6 +32,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. @@ -117,6 +122,11 @@ noktasız float32 sabit değeri + + erased unions + erased unions + + more types support units of measure tür daha ölçü birimlerini destekler diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 5aa158ea406..f6ace552b4b 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -32,6 +32,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. 泛型构造要求泛型类型参数被视为结构或引用类型。请考虑添加类型注释。 @@ -117,6 +122,11 @@ 无点 float32 文本 + + erased unions + erased unions + + more types support units of measure 更多类型支持度量单位 diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index e8f1ffae44a..5c6398d2c19 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -32,6 +32,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. 泛型建構要求泛型型別參數必須指定為結構或參考型別。請考慮新增型別註解。 @@ -117,6 +122,11 @@ 無點號的 float32 常值 + + erased unions + erased unions + + more types support units of measure 更多支援測量單位的類型 diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 9d49174ce6e..26b23a43fe9 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -6045,6 +6045,19 @@ FSharp.Compiler.Syntax.SynEnumCase: Int32 get_Tag() FSharp.Compiler.Syntax.SynEnumCase: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] attributes 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.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 +FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Text.Range get_Range() +FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynErasedUnionCase: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynErasedUnionCase: Int32 Tag +FSharp.Compiler.Syntax.SynErasedUnionCase: Int32 get_Tag() +FSharp.Compiler.Syntax.SynErasedUnionCase: System.String ToString() FSharp.Compiler.Syntax.SynExceptionDefn FSharp.Compiler.Syntax.SynExceptionDefn: FSharp.Compiler.Syntax.SynExceptionDefn NewSynExceptionDefn(FSharp.Compiler.Syntax.SynExceptionDefnRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExceptionDefn: FSharp.Compiler.Syntax.SynExceptionDefnRepr exnRepr @@ -8148,6 +8161,10 @@ FSharp.Compiler.Syntax.SynType+Array: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynType+Array: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynType+Array: Int32 get_rank() FSharp.Compiler.Syntax.SynType+Array: Int32 rank +FSharp.Compiler.Syntax.SynType+ErasedUnion: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynType+ErasedUnion: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynType+ErasedUnion: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynErasedUnionCase] erasedUnionCases +FSharp.Compiler.Syntax.SynType+ErasedUnion: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynErasedUnionCase] get_erasedUnionCases() FSharp.Compiler.Syntax.SynType+Fun: FSharp.Compiler.Syntax.SynType argType FSharp.Compiler.Syntax.SynType+Fun: FSharp.Compiler.Syntax.SynType get_argType() FSharp.Compiler.Syntax.SynType+Fun: FSharp.Compiler.Syntax.SynType get_returnType() @@ -8208,6 +8225,7 @@ FSharp.Compiler.Syntax.SynType+Tags: Int32 Anon FSharp.Compiler.Syntax.SynType+Tags: Int32 AnonRecd FSharp.Compiler.Syntax.SynType+Tags: Int32 App FSharp.Compiler.Syntax.SynType+Tags: Int32 Array +FSharp.Compiler.Syntax.SynType+Tags: Int32 ErasedUnion FSharp.Compiler.Syntax.SynType+Tags: Int32 Fun FSharp.Compiler.Syntax.SynType+Tags: Int32 HashConstraint FSharp.Compiler.Syntax.SynType+Tags: Int32 LongIdent @@ -8241,6 +8259,7 @@ FSharp.Compiler.Syntax.SynType: Boolean IsAnon FSharp.Compiler.Syntax.SynType: Boolean IsAnonRecd FSharp.Compiler.Syntax.SynType: Boolean IsApp FSharp.Compiler.Syntax.SynType: Boolean IsArray +FSharp.Compiler.Syntax.SynType: Boolean IsErasedUnion FSharp.Compiler.Syntax.SynType: Boolean IsFun FSharp.Compiler.Syntax.SynType: Boolean IsHashConstraint FSharp.Compiler.Syntax.SynType: Boolean IsLongIdent @@ -8258,6 +8277,7 @@ FSharp.Compiler.Syntax.SynType: Boolean get_IsAnon() FSharp.Compiler.Syntax.SynType: Boolean get_IsAnonRecd() FSharp.Compiler.Syntax.SynType: Boolean get_IsApp() FSharp.Compiler.Syntax.SynType: Boolean get_IsArray() +FSharp.Compiler.Syntax.SynType: Boolean get_IsErasedUnion() FSharp.Compiler.Syntax.SynType: Boolean get_IsFun() FSharp.Compiler.Syntax.SynType: Boolean get_IsHashConstraint() FSharp.Compiler.Syntax.SynType: Boolean get_IsLongIdent() @@ -8275,6 +8295,7 @@ FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewAnon(FSharp.Co FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewAnonRecd(Boolean, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Syntax.SynType]], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewApp(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynType], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Boolean, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewArray(Int32, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewErasedUnion(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynErasedUnionCase], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewFun(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewHashConstraint(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType NewLongIdent(FSharp.Compiler.Syntax.LongIdentWithDots) @@ -8292,6 +8313,7 @@ FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Anon FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+AnonRecd FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+App FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Array +FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+ErasedUnion FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+Fun FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+HashConstraint FSharp.Compiler.Syntax.SynType: FSharp.Compiler.Syntax.SynType+LongIdent