diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index e9272db3bc0..a153184744b 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -3465,7 +3465,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(tcref2, _), tinst) | TType_app (tcref2, tinst, _) -> diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 02cdd360e86..8be82c49f74 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -7,6 +7,7 @@ module internal FSharp.Compiler.CheckExpressions open System open System.Collections.Generic +open Internal.Utilities open Internal.Utilities.Collections open Internal.Utilities.Library open Internal.Utilities.Library.Extras @@ -35,6 +36,7 @@ open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text open FSharp.Compiler.Text.Position open FSharp.Compiler.Text.Range +open FSharp.Compiler.TypeRelations open FSharp.Compiler.Xml open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeBasics @@ -4324,6 +4326,10 @@ and TcTypeOrMeasure kindOpt (cenv: cenv) newOk checkConstraints occ (iwsam: Warn | SynType.AnonRecd(isStruct, args, m) -> TcAnonRecdType cenv newOk checkConstraints occ env tpenv isStruct args m + | SynType.ErasedUnion(synCases, m) -> + checkLanguageFeatureError cenv.g.langVersion LanguageFeature.ErasedUnions m + TcErasedUnionTypeOr cenv env tpenv synCases m + | SynType.Fun(argType = domainTy; returnType = resultTy) -> TcFunctionType cenv newOk checkConstraints occ env tpenv domainTy resultTy @@ -4572,6 +4578,62 @@ and TcTypeMeasureApp kindOpt (cenv: cenv) newOk checkConstraints occ env tpenv a and TcType (cenv: cenv) newOk checkConstraints occ iwsam env (tpenv: UnscopedTyparEnv) ty = TcTypeOrMeasure (Some TyparKind.Type) cenv newOk checkConstraints occ iwsam env tpenv ty +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 + and TcMeasure (cenv: cenv) newOk checkConstraints occ env (tpenv: UnscopedTyparEnv) (StripParenTypes ty) m = match ty with | SynType.Anon m -> diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 751e71bff5c..824c91169af 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -849,6 +849,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 (domainTy, rangeTy, _) -> @@ -894,6 +895,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 (domainTy, rangeTy, _) -> GcdRational (GetMeasureVarGcdInType v domainTy) (GetMeasureVarGcdInType v rangeTy) @@ -1125,7 +1127,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 = @@ -1203,7 +1205,10 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr if not (typarsAEquiv g aenv tps1 tps2) then localAbortD else SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace bodyTy1 bodyTy2 - | 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 = @@ -1307,6 +1312,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/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index 6f2bcb62f80..3e0c77ba8bf 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -939,6 +939,17 @@ module 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 layoutTypesWithInfoAndPrec denv env prec sep typl = diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs index 9338abd28f5..dc87017010b 100644 --- a/src/Compiler/Checking/PostInferenceChecks.fs +++ b/src/Compiler/Checking/PostInferenceChecks.fs @@ -385,6 +385,9 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi | 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 diff --git a/src/Compiler/Checking/TypeHierarchy.fs b/src/Compiler/Checking/TypeHierarchy.fs index feaaf09e71b..e9df09be72a 100644 --- a/src/Compiler/Checking/TypeHierarchy.fs +++ b/src/Compiler/Checking/TypeHierarchy.fs @@ -314,6 +314,9 @@ let SearchEntireHierarchyOfType f g amap m ty = | 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 = FoldHierarchyOfTypeAux true allowMultiIntfInst SkipUnrefInterfaces.No (ListSet.insert (typeEquiv g)) g amap m ty [] @@ -337,6 +340,20 @@ let HasHeadType g tcref ty2 = | 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 = ExistsInEntireHierarchyOfType (HaveSameHeadType g typeToLookFor) g amap m AllowMultiIntfInstantiations.Yes typeToSearchFrom diff --git a/src/Compiler/Checking/TypeHierarchy.fsi b/src/Compiler/Checking/TypeHierarchy.fsi index 225e6187477..24947575080 100644 --- a/src/Compiler/Checking/TypeHierarchy.fsi +++ b/src/Compiler/Checking/TypeHierarchy.fsi @@ -92,6 +92,15 @@ val AllSuperTypesOfType: 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 -> @@ -115,6 +124,16 @@ val ExistsSameHeadTypeInHierarchy: 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/Compiler/Checking/TypeRelations.fs b/src/Compiler/Checking/TypeRelations.fs old mode 100644 new mode 100755 index 90d5bed1fcb..d888b83fc02 --- a/src/Compiler/Checking/TypeRelations.fs +++ b/src/Compiler/Checking/TypeRelations.fs @@ -6,7 +6,9 @@ module internal FSharp.Compiler.TypeRelations open Internal.Utilities.Collections open Internal.Utilities.Library +open Internal.Utilities.Library.Extras open FSharp.Compiler.DiagnosticsLogger +open FSharp.Compiler.Infos open FSharp.Compiler.TcGlobals open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeBasics @@ -81,6 +83,9 @@ let rec TypesFeasiblyEquivalent stripMeasures ndeep g amap m ty1 ty2 = TypesFeasiblyEquivalent stripMeasures ndeep g amap m domainTy1 domainTy2 && TypesFeasiblyEquivalent stripMeasures ndeep g amap m rangeTy1 rangeTy2 + | TType_erased_union (_, l1), TType_erased_union (_, l2) -> + List.lengthsEqAndForall2 (TypesFeasiblyEquivalent stripMeasures ndeep g amap m) l1 l2 + | TType_measure _, TType_measure _ -> true @@ -96,6 +101,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 @@ -111,6 +117,9 @@ let rec TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce ty2 = | 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_measure _, TType_measure _ -> true diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs old mode 100644 new mode 100755 diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 20208e2870c..f1cee7e7a77 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -704,6 +704,9 @@ and GenTypeAux cenv m (tyenv: TypeReprEnv) voidOK ptrsOK ty = | TType_ucase (ucref, args) -> let cuspec, idx = GenUnionCaseSpec cenv 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/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 7e460abeb92..9e41cbb7873 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -330,6 +330,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" @@ -1549,6 +1550,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" featureRelaxWhitespace2,"whitespace relaxation v2" diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 8644fbe9971..222f839fa79 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -32,6 +32,7 @@ type LanguageFeature = | NullableOptionalInterop | DefaultInterfaceMemberConsumption | WitnessPassing + | ErasedUnions | AdditionalTypeDirectedConversions | InterfacesWithMultipleGenericInstantiation | StringInterpolation @@ -124,6 +125,7 @@ type LanguageVersion(versionText) = LanguageFeature.SelfTypeConstraints, languageVersion70 // F# preview + LanguageFeature.ErasedUnions, previewVersion LanguageFeature.FromEndSlicing, previewVersion LanguageFeature.MatchNotAllowedForUnionCaseWithNoData, previewVersion ] @@ -210,6 +212,7 @@ type LanguageVersion(versionText) = | 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/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index 694a6ae73fd..c157c8bc0d1 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -22,6 +22,7 @@ type LanguageFeature = | NullableOptionalInterop | DefaultInterfaceMemberConsumption | WitnessPassing + | ErasedUnions | AdditionalTypeDirectedConversions | InterfacesWithMultipleGenericInstantiation | StringInterpolation diff --git a/src/Compiler/Service/ItemKey.fs b/src/Compiler/Service/ItemKey.fs index ef769874226..00afcdd972e 100644 --- a/src/Compiler/Service/ItemKey.fs +++ b/src/Compiler/Service/ItemKey.fs @@ -40,6 +40,9 @@ module ItemKeyTags = [] let typeUnionCase = "#U#" + + [] + let typeErasedUnionCase = "#G#" [] let typeMeasureVar = "#p#" @@ -262,6 +265,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/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index 4b8f8c4684b..aa7d04ea26d 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -2513,6 +2513,7 @@ type FSharpType(cenv, ty:TType) = | TType_fun (domainTy, rangeTy, _) -> 10500 + hashType domainTy + hashType rangeTy | 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/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index 66951e620a8..2dfec7440be 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -414,6 +414,9 @@ type SynType = | Tuple of isStruct: bool * path: SynTupleTypeSegment list * range: range | AnonRecd of 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 * elementType: SynType * range: range @@ -448,6 +451,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) @@ -1223,6 +1227,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/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 9d12ce00e81..0e028a9c729 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -474,8 +474,15 @@ type SynType = /// F# syntax: struct {| id: type; ...; id: type |} | AnonRecd of 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 rank: int * elementType: SynType * range: range + | Array of + + rank: int * + elementType: SynType * + range: range /// F# syntax: type -> type | Fun of argType: SynType * returnType: SynType * range: range * trivia: SynTypeFunTrivia @@ -1374,6 +1381,14 @@ 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/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index dfdc9640a0c..645159a4ee1 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -4121,6 +4121,9 @@ type TType = /// /// 'flags' is a placeholder for future features, in particular nullness analysis | TType_var of typar: Typar * flags: byte + + /// 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 @@ -4139,6 +4142,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() @@ -4164,6 +4168,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 @@ -4225,6 +4230,17 @@ type AnonRecdTypeInfo = member x.DisplayNameByIdx idx = x.SortedNames[idx] |> ConvertLogicalNameToDisplayName +[] +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/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index b63942d2c8c..7ee66d74ca0 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -3001,6 +3001,9 @@ type TType = /// 'flags' is a placeholder for future features, in particular nullness analysis | TType_var of typar: Typar * flags: byte + /// 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 @@ -3044,6 +3047,18 @@ type AnonRecdTypeInfo = /// Get the core of the display name for one of the fields of the anonymous record, by index member DisplayNameCoreByIdx: idx: int -> string +[] +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[] -> ErasedUnionInfo + [] type TupInfo = diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index f57954f7bf5..4ad71b66726 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -193,6 +193,12 @@ let rec remapTypeAux (tyenv: Remap) (ty: TType) = match tyenv.tyconRefRemap.TryFind tcref with | Some tcrefR -> TType_ucase (UnionCaseRef(tcrefR, 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 tupInfoR = remapTupInfoAux tyenv anonInfo.TupInfo @@ -794,6 +800,9 @@ let rec stripTyEqnsAndErase eraseFuncAndTuple (g: TcGlobals) ty = | 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 = @@ -853,6 +862,8 @@ let isRecdTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> t 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) @@ -895,6 +906,20 @@ let (|RefTupleTy|_|) g ty = ty |> stripTyEqns g |> (function TType_tuple(tupInfo let (|FunTy|_|) g ty = ty |> stripTyEqns g |> (function TType_fun(domainTy, rangeTy, _) -> Some (domainTy, rangeTy) | _ -> 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 @@ -1038,6 +1063,7 @@ and tcrefAEquiv g aenv tcref1 tcref2 = tyconRefEq g tcref1 tcref2 || (match aenv.EquivTycons.TryFind tcref1 with Some v -> tyconRefEq g v tcref2 | None -> false) +/// Test ty1 = ty2 and typeAEquivAux erasureFlag g aenv ty1 ty2 = let ty1 = stripTyEqnsWrtErasure erasureFlag g ty1 let ty2 = stripTyEqnsWrtErasure erasureFlag g ty2 @@ -1075,7 +1101,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) -> + ListSet.equals (typeAEquivAux erasureFlag g aenv) l1 l2 | _ -> false @@ -1144,12 +1173,20 @@ let rec getErasedTypes g ty = match ty with | TType_forall(_, bodyTy) -> getErasedTypes g bodyTy + | 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 (domainTy, rangeTy, _) -> getErasedTypes g domainTy @ getErasedTypes g rangeTy + | TType_measure _ -> [ty] @@ -1976,7 +2013,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 = @@ -2319,6 +2357,9 @@ and accFreeInType opts ty acc = | TType_anon (anonInfo, l) -> accFreeInTypes opts l (accFreeInTupInfo opts anonInfo.TupInfo acc) + | TType_erased_union (_, l) -> + accFreeInTypes opts l acc + | TType_app (tcref, tinst, _) -> let acc = accFreeTycon opts tcref acc match tinst with @@ -2434,7 +2475,10 @@ and accFreeInTypeLeftToRight g cxFlag thruFlag acc ty = accFreeInTypesLeftToRight g cxFlag thruFlag acc tinst | TType_ucase (_, tinst) -> - accFreeInTypesLeftToRight g cxFlag thruFlag acc tinst + accFreeInTypesLeftToRight g cxFlag thruFlag acc tinst + + | TType_erased_union (_, tinst) -> + accFreeInTypesLeftToRight g cxFlag thruFlag acc tinst | TType_fun (domainTy, rangeTy, _) -> let dacc = accFreeInTypeLeftToRight g cxFlag thruFlag acc domainTy @@ -2985,6 +3029,7 @@ module SimplifyTypes = | TType_app (_, tys, _) | TType_ucase (_, tys) | TType_anon (_, tys) + | TType_erased_union (_, tys) | TType_tuple (_, tys) -> List.fold (foldTypeButNotConstraints f) z tys @@ -3909,6 +3954,9 @@ module DebugPrint = | 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 (domainTy, rangeTy, _) -> ((auxTypeAtomL env domainTy ^^ wordL (tagText "->")) --- auxTypeL env rangeTy) |> wrap @@ -8738,6 +8786,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 @@ -9090,7 +9139,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/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 00d838e04d4..8231a5a989f 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -651,6 +651,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 @@ -2350,6 +2352,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/Compiler/TypedTree/TypedTreePickle.fs b/src/Compiler/TypedTree/TypedTreePickle.fs index 90fd15fa1e2..47f18d9e219 100644 --- a/src/Compiler/TypedTree/TypedTreePickle.fs +++ b/src/Compiler/TypedTree/TypedTreePickle.fs @@ -1714,6 +1714,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 @@ -1762,7 +1766,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 @@ -1811,6 +1819,11 @@ let _ = fill_u_ty (fun st -> let l = u_tys st TType_anon (anonInfo, l) + | 10-> + let erasedUnionInfo = u_erasedUnionInfo st + let l = u_tys st + TType_erased_union (erasedUnionInfo, l) + | _ -> ufailwith st "u_typ") diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 65714a0fc3e..b1e06fdd617 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -5322,6 +5322,7 @@ atomTypeOrAnonRecdType: | (SynField([], false, Some id, ty, false, _xmldoc, None, _m, _trivia)) -> 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" */ @@ -5401,6 +5402,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/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 2d981896ab9..dd1452bdc62 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -72,6 +72,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. @@ -172,6 +177,11 @@ literál float32 bez tečky + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute chyba při zastaralém přístupu konstruktoru s atributem RequireQualifiedAccess diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 7b2e86ccd81..3c02b9fce5e 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -72,6 +72,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. @@ -172,6 +177,11 @@ punktloses float32-Literal + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute Beim veralteten Zugriff auf das Konstrukt mit dem RequireQualifiedAccess-Attribut wird ein Fehler ausgegeben. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 8aad3d6f781..1968d16d5a1 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -72,6 +72,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. @@ -172,6 +177,11 @@ literal float32 sin punto + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute error en el acceso en desuso de la construcción con el atributo RequireQualifiedAccess diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index ffc5e832198..23822296de7 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -72,6 +72,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. @@ -172,6 +177,11 @@ littéral float32 sans point + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute donner une erreur sur l’accès déconseillé de la construction avec l’attribut RequireQualifiedAccess diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 29240e0d98c..7ef0bf64f17 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -72,6 +72,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. @@ -172,6 +177,11 @@ valore letterale float32 senza punti + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute errore durante l'accesso deprecato del costrutto con l'attributo RequireQualifiedAccess diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index c509bc1328e..2dd5ba32c73 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -72,6 +72,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. ジェネリック コンストラクトでは、ジェネリック型パラメーターが構造体または参照型として認識されている必要があります。型の注釈の追加を検討してください。 @@ -172,6 +177,11 @@ ドットなしの float32 リテラル + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute RequireQualifiedAccess 属性を持つコンストラクトの非推奨アクセスでエラーが発生しました diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 9767ff521a6..230024b888b 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -72,6 +72,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. 제네릭 구문을 사용하려면 구조체 또는 참조 형식의 제네릭 형식 매개 변수가 필요합니다. 형식 주석을 추가하세요. @@ -172,6 +177,11 @@ 점이 없는 float32 리터럴 + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute RequireQualifiedAccess 특성을 사용하여 사용되지 않는 구문 액세스에 대한 오류 제공 diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 4a565f29eaf..a96004f8983 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -72,6 +72,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. @@ -172,6 +177,11 @@ bezkropkowy literał float32 + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute wskazywanie błędu w przypadku przestarzałego dostępu do konstrukcji z atrybutem RequireQualifiedAccess diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 140f330414d..5a7d9d24c32 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -72,6 +72,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. @@ -172,6 +177,11 @@ literal float32 sem ponto + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute fornecer erro no acesso preterido do constructo com o atributo RequireQualifiedAccess diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 5c8c1ad44e7..56f012b2ca2 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -72,6 +72,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. В универсальной конструкции требуется использовать параметр универсального типа, известный как структура или ссылочный тип. Рекомендуется добавить заметку с типом. @@ -172,6 +177,11 @@ литерал float32 без точки + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute выдать ошибку при устаревшем доступе к конструкции с атрибутом RequireQualifiedAccess diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index fb8d5406e68..178b225aafe 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -72,6 +72,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. @@ -172,6 +177,11 @@ noktasız float32 sabit değeri + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute RequireQualifiedAccess özniteliğine sahip yapının kullanım dışı erişiminde hata diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index baf4e53d041..c6865df25a2 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -72,6 +72,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. 泛型构造要求泛型类型参数被视为结构或引用类型。请考虑添加类型注释。 @@ -172,6 +177,11 @@ 无点 float32 文本 + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute 对具有 RequireQualifiedAccess 属性的构造进行弃用的访问时出错 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 3711de1d214..10b2222ab55 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -72,6 +72,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. 泛型建構要求泛型型別參數必須指定為結構或參考型別。請考慮新增型別註解。 @@ -172,6 +177,11 @@ 無點號的 float32 常值 + + erased unions + erased unions + + give error on deprecated access of construct with RequireQualifiedAccess attribute 對具有 RequireQualifiedAccess 屬性的建構的已取代存取發出錯誤 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 e1814272d1b..e108d3df79a 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -6180,6 +6180,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.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExceptionDefn: FSharp.Compiler.Syntax.SynExceptionDefnRepr exnRepr @@ -8470,6 +8483,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() @@ -8544,6 +8561,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 @@ -8578,6 +8596,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 @@ -8596,6 +8615,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() @@ -8614,6 +8634,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.SyntaxTrivia.SynTypeFunTrivia) 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.SynLongIdent) @@ -8632,6 +8653,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